如何在 Android Studio 中包含 *.so library,并使用库中定义的方法?

EloBock 9年前
   <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>