需要 3 步:
需要新建一个名为 jniLibs
文件夹,根据目标机器的 CPU-ABI 类型,把 .so file 放入对应的路径下:
weiyi$ cd app/src/main/ weiyi$ tree -L 2 . ├── AndroidManifest.xml ├── java ├── jniLibs │ ├── armeabi │ │ └── libhello-jni.so │ └── armeabi-v7a │ └── libhello-jni.so └── res
至于在其它编译器(eclipse等)中的路径,以及 armeabi
和 armeabi-v7a
的解释,参考 StackOverflow - System.loadLibrary(…) couldn’t find native library in my case
.so file 需要通过 NDK tool 编译 c/c++ 得到,可以从 android.googlesource.com 下载 libhello-jni.so
。
Java 端实现加载 .so library:(HelloJni.java)
package com.example.hellojni; public class HelloJni { public native String stringFromJNI(); static { System.loadLibrary("hello-jni"); } }
这篇开发文档 Developer - Sample: hello-jni 解释了 native
关键字。
类似调用任何一个类的方法:
HelloJni helloJni = new HelloJni(); LOGD(TAG, helloJni.stringFromJNI());
可以看到 log: Hello from JNI !
。而整个工程目录应该是这样:
weiyiWorkCell:main weiyi$ tree -L 5 . ├── AndroidManifest.xml ├── java │ └── com │ ├── example │ │ └── hellojni │ │ └── HelloJni.java ├── jniLibs │ ├── armeabi │ │ ├── libhello-jni.so │ └── armeabi-v7a │ ├── libhello-jni.so └── res
在 step2 时,假如把 native method 声明在了一个 随意命名 的 package 或者随意命名的 java file 内,比如 com.example.hellojni21.HelloJni
,你会遇到如下 exception:
java.lang.UnsatisfiedLinkError: No implementation found for java.lang.String com.example.hellojni21.HelloJni.stringFromJNI() tried Java_com_example_hellojni21_HelloJni_stringFromJNI and Java_com_example_hellojni21_HelloJni_stringFromJNI__
这是因为命名存在一个默认的规则。.so file 需要通过 NDK tool 编译 c/c++ 得到,c/c++ 实现 native method 时,要按如下规则命名,以 libhello-jni.so 为例:
jstring Java_com_example_hellojni_HelloJni_stringFromJNI( JNIEnv* env, jobject thiz ) 规则如下: Java_package_file_method(...)
所以,Java 端的包名、文件名、方法名就被规定好了,包名必须是 com_example_hellojni
,文件名必须是 HelloJni
,native method 声明必须是 String stringFromJNI()
。
这篇开发文档 Developer - Sample: hello-jni 描述了命名规则。
我们还可以通过命令行列出 shared library 中的方法:
weiyi$ nm -D libhello-jni.so 00000b90 T Java_com_example_hellojni_HelloJni_stringFromJNI
参考: