如何在 Android Studio 中包含 *.so library,并使用库中定义的方法?
EloBock
8年前
<h2>Step1 把 .so file 放到 Android Studio project 正确的路径中</h2> <p>需要新建一个名为 jniLibs 文件夹,根据目标机器的 CPU-ABI 类型,把 .so file 放入对应的路径下:</p> <pre> weiyi$ cd app/src/main/ weiyi$ tree -L 2 . ├── AndroidManifest.xml ├── java ├── jniLibs │ ├── armeabi │ │ └── libhello-jni.so │ └── armeabi-v7a │ └── libhello-jni.so └── res </pre> <p>至于在其它编译器(eclipse等)中的路径,以及 armeabi 和 armeabi-v7a 的解释,参考 <a href="/misc/goto?guid=4959670589071828133" rel="nofollow,noindex">StackOverflow - System.loadLibrary(…) couldn’t find native library in my case</a></p> <p>.so file 需要通过 NDK tool 编译 c/c++ 得到,可以从 <a href="/misc/goto?guid=4959670589156203672" rel="nofollow,noindex">android.googlesource.com</a> 下载 libhello-jni.so 。</p> <h2>Step2 加载 .so library 并声明 native method</h2> <p>Java 端实现加载 .so library:(HelloJni.java)</p> <pre> package com.example.hellojni; public class HelloJni { public native String stringFromJNI(); static { System.loadLibrary("hello-jni"); } } </pre> <p>这篇开发文档 <a href="/misc/goto?guid=4959670589243941092" rel="nofollow,noindex">Developer - Sample: hello-jni</a> 解释了 native 关键字。</p> <h2>Step3 最后就可以调用 .so library native method 了</h2> <p>类似调用任何一个类的方法:</p> <pre> HelloJni helloJni = new HelloJni(); LOGD(TAG, helloJni.stringFromJNI()); </pre> <p>可以看到 log: Hello from JNI ! 。而整个工程目录应该是这样:</p> <pre> 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 </pre> <h2>UnsatisfiedLinkError: No implementation found</h2> <p>在 step2 时,假如把 native method 声明在了一个 <strong>随意命名</strong> 的 package 或者随意命名的 java file 内,比如 com.example.hellojni21.HelloJni ,你会遇到如下 exception:</p> <pre> 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__ </pre> <p>这是因为命名存在一个默认的规则。.so file 需要通过 NDK tool 编译 c/c++ 得到,c/c++ 实现 native method 时,要按如下规则命名,以 libhello-jni.so 为例:</p> <pre> jstring Java_com_example_hellojni_HelloJni_stringFromJNI( JNIEnv* env, jobject thiz ) 规则如下: Java_package_file_method(...) </pre> <p>所以,Java 端的包名、文件名、方法名就被规定好了,包名必须是 com_example_hellojni ,文件名必须是 HelloJni ,native method 声明必须是 String stringFromJNI() 。</p> <p>这篇开发文档 <a href="/misc/goto?guid=4959670589326305865" rel="nofollow,noindex">Developer - Sample: hello-jni</a> 描述了命名规则。</p> <p>我们还可以通过命令行列出 shared library 中的方法:</p> <pre> weiyi$ nm -D libhello-jni.so 00000b90 T Java_com_example_hellojni_HelloJni_stringFromJNI </pre> <p>参考:</p> <ul> <li><a href="/misc/goto?guid=4958963946620288000" rel="nofollow,noindex">Develper - Android NDK Preview</a></li> <li><a href="/misc/goto?guid=4959670589433981782" rel="nofollow,noindex">Developer - NDK Setup</a></li> <li><a href="/misc/goto?guid=4959670589513841148" rel="nofollow,noindex">Developer - JNI Tips</a></li> <li><a href="/misc/goto?guid=4959670589590823360" rel="nofollow,noindex">Developer - Create Hello-JNI with Android studio</a></li> <li><a href="/misc/goto?guid=4959670589326305865" rel="nofollow,noindex">Developer - Sample: hello-jni</a></li> <li><a href="/misc/goto?guid=4959643834154861717" rel="nofollow,noindex">GitHub - googlesamples/android-ndk</a></li> <li><a href="/misc/goto?guid=4959670589724598368" rel="nofollow,noindex">StackOverflow - How to include *.so library in Android Studio?</a></li> <li><a href="/misc/goto?guid=4959670589798826109" rel="nofollow,noindex">StackOverflow - Using existing shared library (.so) in Android application</a></li> <li><a href="/misc/goto?guid=4959670589071828133" rel="nofollow,noindex">StackOverflow - System.loadLibrary(…) couldn’t find native library in my case</a></li> <li><a href="/misc/goto?guid=4959670589885732916" rel="nofollow,noindex">StackOverflow - How do I view the list of functions a Linux shared library is exporting?</a></li> <li><a href="/misc/goto?guid=4959670589970955885" rel="nofollow,noindex">blog - The new NDK support in Android Studio</a></li> <li><a href="/misc/goto?guid=4959670590050175580" rel="nofollow,noindex">blog - java.lang.UnsatisfiedLinkError: Native method not found 三种可能解决方案</a></li> <li><a href="/misc/goto?guid=4959670590128530479" rel="nofollow,noindex">blog - Android动态加载补充 加载SD卡中的SO库 by kaede</a></li> </ul> <p>来自: <a href="/misc/goto?guid=4959670590204201616" rel="nofollow">http://li2.me/2016/04/how-to-include-and-use-so-library-in-android-studio.html</a> </p>