经过几天的努力终于搞定了androidJNI部分,下面将我的这个小程序和大家分享一下。androidJNI是连接androidJava部分和C/C++部分的纽带,完整使用JNI需要Java代码和C/C++代码。其中C/C++代码用于生成库文件,Java代码用于引用C/C++库文件以及调用C/C++方法。
androidJava部分代码:
03 | package com.hello.jnitest; |
07 | import android.app.Activity; |
09 | import android.os.Bundle; |
13 | public class
jnitest extends Activity{
|
15 | /**Calledwhentheactivityisfirstcreated.*/ |
19 | public
void onCreate(BundlesavedInstanceState){ |
21 | super .onCreate(savedInstanceState); |
23 | setContentView(R.layout.main); |
27 | setTitle( "TheNativeAddResultis" +String.valueOf(test.nadd( 10 , 20 ))); |
35 | package com.hello.jnitest; |
43 | System.loadLibrary( "hello_jni" ); |
49 | public native
int nadd( int
a, int b); |
Java代码说明:
1)jnitest.java是一个activity的类对象,在该类对象中生成调用JNI函数的类对象,同时调用JNI方法,最后将JNI方法的结果显示到标题栏上;
2)Nadd.java是一个引用和声明JNI库和函数的类,其中System.loadLibrary();函数用来引用JNI库,默认JNI库放在android系统的/system/lib/目录下;publicnaddintnadd(inta,intb);为声明需要在java程序中使用的JNI库中的函数;
JNI中java部分的代码到此就结束了,总结一下在java代码中需要做两件事:
1)使用System.loadLibrary()函数来引用JNI库;
2)声明调用JNI库的函数且前面添加native关键字;
androidC/C++部分代码:
01 | #defineLOG_TAG"hello-JNI" |
11 | #include"android_runtime/AndroidRuntime.h" |
12 | static jintcom_hello_jnitest_jnitest_nadd(JNIEnv*env,jobjectobj,jinta,jintb)
|
16 | static JNINativeMethodgMethods[]={
|
17 | { "nadd" , "(II)I" ,( void
*)com_hello_jnitest_jnitest_nadd}, |
19 | static int register_android_test_hello(JNIEnv*env) |
21 | return android::AndroidRuntime::registerNativeMethods(env,
"com/hello/jnitest/Nadd" ,gMethods,NELEM(gMethods)); |
23 | jintJNI_OnLoad(JavaVM*vm, void
*reserved) |
26 | if (vm->GetEnv(( void
**)&env,JNI_VERSION_1_4)!=JNI_OK){ |
27 | printf ( "ErrorGetEnv\n" ); |
31 | if (register_android_test_hello(env)<0){ |
32 | printf ( "register_android_test_helloerror.\n" ); |
JNIC/C++代码说明:
1)JNI_OnLoad()函数。该函数在Java程序调用System.loadLibrary()时,被调用执行,用于向JavaVM注册JNI函数等。在本例中首先通过参数JavaVM(Java虚拟机指针)获取当前应用程序所在的线程,即:JNIEnv。再通过调用android::AndroidRuntime::registerNativeMethods()注册native实现的函数指针。
2)JNI函数和Java调用函数的映射关系。使用JNINativeMethod将java调用的函数名与JNI实现的函数名联系在一起;
3)JNI函数实现;
Android.mk代码:
1 | LOCAL_PATH:=$(callmy-dir) |
3 | LOCAL_PRELINK_MODULE:= false |
6 | LOCAL_SHARED_LIBRARIES:=\ |
8 | LOCAL_MODULE:=libhello_jni |
9 | include$(BUILD_SHARED_LIBRARY) |
需要注意的是:
1)JNIC/C++部分的代码需要在android源代码树上进行编译,编译完成后我的做法是直接将生成的.so通过adbpush方法上传到android虚拟机的/system/lib/目录下;
2)java代码可以在eclipse下直接编译且在虚拟机上执行;
编译JNIC/C++部分代码(在android内核源代码根目录下):
#makelibhello_jni
之后在out/target/product/generic/system/lib/目录下生成libhello_jni.so
上传libhello_jni.so到android虚拟机:
#adbpushout/target/product/generic/system/lib/libhello_jni.so/system/lib
注意:此时有可能出现OutofMemory的错误提示。当出现如上错误提示时,需要使用#adbremount重新加载一下就可以了。
另外,也有可能直接使用eclipse启动android虚拟机时出现上述错误且使用#adbremount也出现的情况,此时需要手动启动android虚拟机,如:#emulator-avdxxx-partition-size128,之后在使用#adbpush就可以了。
原链接:http://www.open-open.com/lib/view/open1324909652374.html