- 浏览: 929305 次
- 性别:
- 来自: 北京
文章分类
最新评论
-
itzhongyuan:
java Random类详解 -
david_je:
你好,我看到你在C里面回调JAVA里面的方法是在native里 ...
Android NDK开发(1)----- Java与C互相调用实例详解 -
fykyx521:
请求锁是在 oncreate 释放实在ondestroy?? ...
Android如何保持程序一直运行 -
aduo_vip:
不错,总结得好!
Android读取assets目录下的资源 -
f839903061:
给的网址很给力哦!
Android 4.0.1 源码下载,编译和运行
一、概述
对于大部分应用开发者来说可能都不怎么接触到NDK,但如果涉及到硬件操作的话就不得不使用NDK了。使用NDK还有另一个原因,就是C/C++的效率比较高,因此我们可以把一些耗时的操作放在NDK中实现。
关于java与c/c++的互相调用,网上有一大堆的文章介绍。但仔细观察可以发现,基本都是讲在java中调用一个本地方法,然后由该本地方法直接返回一个参数给java(例如,在java中定义的本地方法为private int callJNI(int i))。但在大多数时候要求的并不是由开发者在java层主动去调JNI中的函数来返回想要的数据,而是由JNI主动去调java中的函数。举个最简单的例子,Android中的Camera,图像数据由内核一直往上传到java层,然而这些数据的传递并不需要开发者每一次主动去调用来JNI中的函数来获取,而是由JNI主动传给用java中方法,这类似于Linux驱动机制中的异步通知。
二、要求
用NDK实现Java与C/C++互调,实现int,string,byte[]这三种类型的互相传递。
三、实现
下面的实现中,每次java调用JNI中的某个函数时,最后会在该函数里回调java中相应的方法而不是直接返回一个参数。可能你会觉得这不还是每次都是由开发者来主动调用吗,其实这只是为了讲解而已,在实际应用中,回调java中的方法应该由某个事件(非java层)来触发。
新建工程MyCallback,修改main.xml文件,在里面添加3个Button,分别对应3种类型的调用和3个TextView分别显示由JNI回调java时传给java的数据。完整的main.xml文件如下:
新建工程MyCallback,修改main.xml文件,在里面添加3个Button,分别对应3种类型的调用和3个TextView分别显示由JNI回调java时传给java的数据。完整的main.xml文件如下:
修改MyCallbackActivity.java文件,定义了一个Handler,当JNI回调java的方法时,用来发送消息;实现3个Button的监听。如下:
最后就是本篇随笔的“重头戏”,在工程的根目录下新建jni文件夹,在里面添加一个Android.mk文件和一个callback.c文件,Android.mk文件如下:
callback.c文件如下:
利用ndk-build编译生成相应的库。
对于大部分应用开发者来说可能都不怎么接触到NDK,但如果涉及到硬件操作的话就不得不使用NDK了。使用NDK还有另一个原因,就是C/C++的效率比较高,因此我们可以把一些耗时的操作放在NDK中实现。
关于java与c/c++的互相调用,网上有一大堆的文章介绍。但仔细观察可以发现,基本都是讲在java中调用一个本地方法,然后由该本地方法直接返回一个参数给java(例如,在java中定义的本地方法为private int callJNI(int i))。但在大多数时候要求的并不是由开发者在java层主动去调JNI中的函数来返回想要的数据,而是由JNI主动去调java中的函数。举个最简单的例子,Android中的Camera,图像数据由内核一直往上传到java层,然而这些数据的传递并不需要开发者每一次主动去调用来JNI中的函数来获取,而是由JNI主动传给用java中方法,这类似于Linux驱动机制中的异步通知。
二、要求
用NDK实现Java与C/C++互调,实现int,string,byte[]这三种类型的互相传递。
三、实现
下面的实现中,每次java调用JNI中的某个函数时,最后会在该函数里回调java中相应的方法而不是直接返回一个参数。可能你会觉得这不还是每次都是由开发者来主动调用吗,其实这只是为了讲解而已,在实际应用中,回调java中的方法应该由某个事件(非java层)来触发。
新建工程MyCallback,修改main.xml文件,在里面添加3个Button,分别对应3种类型的调用和3个TextView分别显示由JNI回调java时传给java的数据。完整的main.xml文件如下:
新建工程MyCallback,修改main.xml文件,在里面添加3个Button,分别对应3种类型的调用和3个TextView分别显示由JNI回调java时传给java的数据。完整的main.xml文件如下:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" > <Button android:id="@+id/intbutton" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="传给JNI一个整数1" /> <TextView android:id="@+id/inttextview" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="接收到的整数:" /> <Button android:id="@+id/stringbutton" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="传给JNI一个字符A" /> <TextView android:id="@+id/stringtextview" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="接收到的字符:" /> <Button android:id="@+id/arraybutton" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="传给JNI一个数组12345" /> <TextView android:id="@+id/arraytextview" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="接收到的数组:" /> </LinearLayout>
修改MyCallbackActivity.java文件,定义了一个Handler,当JNI回调java的方法时,用来发送消息;实现3个Button的监听。如下:
package com.nan.callback; import android.app.Activity; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.view.View; import android.widget.Button; import android.widget.TextView; public class MyCallbackActivity extends Activity { private Button intButton = null; private Button stringButton = null; private Button arrayButton = null; private TextView intTextView = null; private TextView stringTextView = null; private TextView arrayTextView = null; private Handler mHandler = null; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); intButton = (Button)this.findViewById(R.id.intbutton); //注册按钮监听 intButton.setOnClickListener(new ClickListener()); stringButton = (Button)this.findViewById(R.id.stringbutton); //注册按钮监听 stringButton.setOnClickListener(new ClickListener()); arrayButton = (Button)this.findViewById(R.id.arraybutton); //注册按钮监听 arrayButton.setOnClickListener(new ClickListener()); intTextView = (TextView)this.findViewById(R.id.inttextview); stringTextView = (TextView)this.findViewById(R.id.stringtextview); arrayTextView = (TextView)this.findViewById(R.id.arraytextview); //消息处理 mHandler = new Handler() { @Override public void handleMessage(Message msg) { switch(msg.what) { //整型 case 0: { intTextView.setText(msg.obj.toString()); break; } //字符串 case 1: { stringTextView.setText(msg.obj.toString()); break; } //数组 case 2: { byte[] b = (byte[])msg.obj; arrayTextView.setText(Byte.toString(b[0])+Byte.toString(b[1])+Byte.toString(b[2])+Byte.toString(b[3])+Byte.toString(b[4])); break; } } } }; } //按钮监听实现 public class ClickListener implements View.OnClickListener { @Override public void onClick(View v) { // TODO Auto-generated method stub switch(v.getId()) { case R.id.intbutton: { //调用JNI中的函数 callJNIInt(1); break; } case R.id.stringbutton: { //调用JNI中的函数 callJNIString("你好A"); break; } case R.id.arraybutton: { //调用JNI中的函数 callJNIByte(new byte[]{1,2,3,4,5}); break; } } } } //被JNI调用,参数由JNI传入 private void callbackInt(int i) { Message msg = new Message(); //消息类型 msg.what = 0; //消息内容 msg.obj = i; //发送消息 mHandler.sendMessage(msg); } //被JNI调用,参数由JNI传入 private void callbackString(String s) { Message msg = new Message(); //消息类型 msg.what = 1; //消息内容 msg.obj = s; //发送消息 mHandler.sendMessage(msg); } //被JNI调用,参数由JNI传入 private void callbackByte(byte[] b) { Message msg = new Message(); //消息类型 msg.what = 2; //消息内容 msg.obj = b; //发送消息 mHandler.sendMessage(msg); } //本地方法,由java调用 private native void callJNIInt(int i); private native void callJNIString(String s); private native void callJNIByte(byte[] b); static { //加载本地库 System.loadLibrary("myjni"); } }
最后就是本篇随笔的“重头戏”,在工程的根目录下新建jni文件夹,在里面添加一个Android.mk文件和一个callback.c文件,Android.mk文件如下:
LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := myjni LOCAL_SRC_FILES := callback.c LOCAL_LDLIBS := -llog include $(BUILD_SHARED_LIBRARY)
callback.c文件如下:
#include <string.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/ioctl.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <jni.h> #include <android/log.h> #define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO, "native-activity", __VA_ARGS__)) #define LOGW(...) ((void)__android_log_print(ANDROID_LOG_WARN, "native-activity", __VA_ARGS__)) /**********传输整数************* */ JNIEXPORT void JNICALL Java_com_nan_callback_MyCallbackActivity_callJNIInt( JNIEnv* env, jobject obj , jint i) { //找到java中的类 jclass cls = (*env)->FindClass(env, "com/nan/callback/MyCallbackActivity"); //再找类中的方法 jmethodID mid = (*env)->GetMethodID(env, cls, "callbackInt", "(I)V"); if (mid == NULL) { LOGI("int error"); return; } //打印接收到的数据 LOGI("from java int: %d",i); //回调java中的方法 (*env)->CallVoidMethod(env, obj, mid ,i); } /********传输字符串************* */ JNIEXPORT void JNICALL Java_com_nan_callback_MyCallbackActivity_callJNIString( JNIEnv* env, jobject obj , jstring s) { //找到java中的类 jclass cls = (*env)->FindClass(env, "com/nan/callback/MyCallbackActivity"); //再找类中的方法 jmethodID mid = (*env)->GetMethodID(env, cls, "callbackString", "(Ljava/lang/String;)V"); if (mid == NULL) { LOGI("string error"); return; } const char *ch; //获取由java传过来的字符串 ch = (*env)->GetStringUTFChars(env, s, NULL); //打印 LOGI("from java string: %s",ch); (*env)->ReleaseStringUTFChars(env, s, ch); //回调java中的方法 (*env)->CallVoidMethod(env, obj, mid ,(*env)->NewStringUTF(env,"你好haha")); } /********传输数组(byte[])************* */ JNIEXPORT void JNICALL Java_com_nan_callback_MyCallbackActivity_callJNIByte( JNIEnv* env, jobject obj , jbyteArray b) { //找到java中的类 jclass cls = (*env)->FindClass(env, "com/nan/callback/MyCallbackActivity"); //再找类中的方法 jmethodID mid = (*env)->GetMethodID(env, cls, "callbackByte", "([B)V"); if (mid == NULL) { LOGI("byte[] error"); return; } //获取数组长度 jsize length = (*env)->GetArrayLength(env,b); LOGI("length: %d",length); //获取接收到的数据 int i; jbyte* p = (*env)->GetByteArrayElements(env,b,NULL); //打印 for(i=0;i<length;i++) { LOGI("%d",p[i]); } char c[5]; c[0] = 1;c[1] = 2;c[2] = 3;c[3] = 4;c[4] = 5; //构造数组 jbyteArray carr = (*env)->NewByteArray(env,length); (*env)->SetByteArrayRegion(env,carr,0,length,c); //回调java中的方法 (*env)->CallVoidMethod(env, obj, mid ,carr); }
利用ndk-build编译生成相应的库。
发表评论
-
Android.mk的用法和基础
2013-07-19 14:11 4332一个Android.mk file用来向编译系统描述你的源代码 ... -
eclipse配置NDK-Builder命令
2013-07-18 11:02 10351. 2. -
eclipse配置javah命令
2013-07-18 10:48 19941.找到javah命令所在的目录 我的为 /usr/bi ... -
Android SDL2.0 编译
2013-07-17 13:40 19671,下载: wget http://www.libsdl.o ... -
JNI详解001_c++
2013-05-09 14:57 817public class HelloWorld { p ... -
java_jni详解_04
2013-05-09 14:13 1123public class ObjectArrayTest{ ... -
jni docs
2013-05-09 12:18 887http://docs.oracle.com/javase/1 ... -
java_jni详解_03
2013-05-09 11:55 1035直接看代码 public class I ... -
java_jni详解_02
2013-05-09 11:19 1239直接看代码吧 public clas ... -
java_jni详解_01
2013-05-08 17:15 957java中的jni 例子HelloWorld 准备过程: 1 ... -
Android with the NDK_001
2013-05-08 09:22 11251.设置环境 Microsoft Windows 系统下 ... -
Android NDK 的学习之旅-----JNI LOG 打印
2013-05-08 09:23 23231.创建android 工程 android create p ... -
Android NDK 的学习之旅-----HelloWorld
2013-05-08 09:22 8811.在 ndk sample目录下创建 项目 android ... -
jni开发之一
2012-02-27 10:03 1891JNI在Android系统中有着广 ... -
java JNI HelloWorld
2012-02-17 15:26 1394步骤 /** * 1。Create a class that ... -
Android.mk文件语法规范
2011-07-11 14:16 1241序言: ------------- 此文档旨在描述Andro ...
相关推荐
本实例将详解如何使用NDK进行开发,以及如何在Java层调用C++编译后的.so文件。 首先,我们需要了解NDK的基本概念。NDK是Google提供的一套工具集,用于在Android平台上编译C和C++代码。通过NDK,开发者可以在Android...
**Android NDK 开发详解** Android NDK(Native Development Kit)是Google提供的一款工具集,允许开发者在Android应用中使用C和C++代码,从而利用原生编程语言的高性能和低级硬件控制能力。NDK的主要用途包括处理...
### Android NDK 开发实例详解 #### 一、概述 Android NDK (Native Development Kit) 是一套工具集合,允许开发者使用 C 或 C++ 编写应用程序的部分或全部代码。这在需要高性能计算的情况下非常有用,比如游戏开发...
通过以上实例,你可以逐步了解NDK在实际开发中的应用,熟悉原生代码与Java的交互,以及如何利用NDK提高Android应用的性能。学习过程中,记得查阅官方文档,理解NDK的最新特性和最佳实践,同时不断练习以提升自己的...
综上所述,Android NDK为开发者提供了一个强大的工具集,使得他们能够在Android平台上利用C/C++开发高性能的应用程序。无论是Windows还是Linux环境下的配置与开发,都旨在帮助开发者充分利用NDK的优势,创建出更加...
Android NDK(Native Development Kit)是Android系统中用于开发原生代码的工具集,它允许开发者使用C、C++等语言编写性能高效的代码,尤其适合处理计算密集型任务或调用硬件特性。本篇文章将基于"Android NDK Demo...
### Android NDK开发详解 #### 一、理解Android NDK及其意义 Android NDK(Native Development Kit)是一种允许开发者使用C或C++语言为Android设备编写应用程序的技术。它为那些希望利用高性能计算能力(如图形...
本实例源码提供了一个完整的Android应用开发示例,旨在帮助开发者深入理解和实践Android与OpenCV的集成以及NDK的使用。 一、OpenCV简介 OpenCV是一个强大的跨平台计算机视觉库,它包含了众多图像处理和计算机视觉的...
### Android NDK与OpenGL ES开发详解 #### 一、引言 随着移动设备性能的不断提升,用户对于高质量图形渲染的需求也日益增长。Android平台作为全球最大的移动操作系统之一,提供了多种方式来实现高效的图形处理能力...
在Android开发中,NDK(Native Development Kit)是一个重要的工具集,它允许开发者使用C和C++编写原生代码,从而提升性能、处理底层硬件交互和优化计算密集型任务。本实例将深入探讨如何进行Android NDK编程,包括...
《Android NDK开发详解——基于NdkDemo实例》 在移动应用开发领域,Android Studio作为主流的集成开发环境,提供了丰富的工具和功能,使得开发者能够更高效地构建应用程序。而NDK(Native Development Kit)是...
- **第一个NDK项目**:通过创建一个简单的项目来演示如何将C/C++代码与Java代码结合。 - **多媒体处理**:介绍如何利用NDK来进行音频和视频处理。 ##### 第二部分:进阶篇 1. **性能优化** - **代码优化技巧**:...
在Android开发中,JNI通常用于实现Java与C/C++之间的通信,提供了一种灵活的方式来利用现有的C/C++代码或者优化性能关键的部分。 三、HelloNDK示例 "HelloNDK"是一个经典的入门示例,它展示了如何在Android应用中...
【Android系统原理与开发要点详解】/底层 应用 框架 Android核心分析28篇,强烈推荐android初学者,android进阶者看看这个系列教程 Android应用开发者指南:性能优化 android开发教程合集(推荐新手看下这一季教程)...
- **Android公共库**:包含API级别18的Java类库,开发者可以通过这些类库调用Android系统服务和API。 - **系统图像**:用于模拟器,让开发者能够在没有实际设备的情况下测试应用程序。 - **头文件和库**:用于C/C++...
**Android NDK 开发详解** ...通过这个实例,你可以学习到NDK的基本配置、本地库的创建、Java与本地代码的交互,以及性能优化等关键知识点。深入理解这些概念,将有助于你构建更高效、功能更强大的Android应用。