zoukankan      html  css  js  c++  java
  • AndroidStudio 开发JNI

    Android版本不断更新,发现网上很多JNI的教程,都不太适用了,会遇到各种问题,今天自己来总结一个。

    NDK下载

    我们下载NDK,有两种下载方式:

      

      点击SDK Manger -> SDK Tools -> NDK -> 点击Apply

      OK,NDK下载完成

    NDK配置

      我们先创建一个项目,里面只有一个MainActivity

    右键项目 -> Open Module settings-> Android NDK Location -> OK -> 等待编译

    我们发现根目录local.properties里面多了NDK路径如下图:

    示例代码

    1. 在MainActivity的包下,新建一个类,声明native方法。这个类是java与C/C++交互的中介,方法由java声明,由C/C++实现。

    public class myJNI {
    
      //加载so库
        static {
            System.loadLibrary("JniTest");
        }
    
      //native方法
        public static native String sayHello();
    
    }

    2. 打开android studio终端,使用javac编译上述文件,生成class文件。

    yuany@Mobile238:~/workspace/DemoJNI2$ cd app/src/main/java/com/example/scarecrow/demojni/
    yuany@Mobile238:~/workspace/DemoJNI2/app/src/main/java/com/example/scarecrow/demojni$ javac myJNI.java

    3. 确认自己类的包名!然后在上一级的位置使用javah生成.h头文件

    一定要在上一级哦,不然不会报错:找不到xxx类

    yuany@Mobile238:~/workspace/DemoJNI2/app/src/main/java/com/example/scarecrow/demojni$ cd ~/workspace/DemoJNI2/app/src/main/java/
    yuany@Mobile238:~/workspace/DemoJNI2/app/src/main/java$ javah -jni com.example.scarecrow.demojni.myJNI

    然后就能看到生成了一个h文件。

     4. 接下来在项目中创建一个jni目录,并将刚生成的.h文件剪切至这个目录下

    5. 在jni目录下新建MyJNI.cpp文件,实现com_example_scarecrow_demojni_myJNI.h中的方法,返回一句话"This is my first JNI test"。

    #include "com_example_scarecrow_demojni_myJNI.h"
    
    JNIEXPORT jstring JNICALL Java_com_example_scarecrow_demojni_myJNI_sayHello
      (JNIEnv * env, jclass jobj)
      {
        //返回一句话
        return env->NewStringUTF("This is my first JNI test");
      }

    6. 打开app Module的build.gradle文件,在defaultConfig节点里添加以下代码, 注意这里的moduleName,是我们在之前自己编写的类里面加载的so库名。 abiFilters 对应不同的操作系统版本。
            ndk {
                moduleName "JniTest"
                ldLibs "log", "z", "m"
                abiFilters "armeabi", "armeabi-v7a", "x86"
            }

    7. 编译代码 Build -> Make Project. 这时候会看到报错如下。

    Error: Your project contains C++ files but it is not using a supported native build system.
    Consider using CMake or ndk-build integration. For more information, go to:
     https://d.android.com/r/studio-ui/add-native-code.html
    Alternatively, you can use the experimental plugin:
     https://developer.android.com/r/tools/experimental-plugin.html

    意思是要把我们的native c++代码编译到库里面,需要Android.mk文件,而且这个文件在我们尝试make的时候, 已经帮我们生成好了(真是暖心)。。 位置就在

    project-root/module-root/build/intermediates/ndk/debug/Android.mk.

    OK, 接下来我们要做的就是把这个Android.mk文件移动到build.gradle的同级目录。官方说法是This makes sure that Gradle doesn't delete the script file when running the clean task.

    8. Link Gradle to the Android.mk file .

    在Module(app)上右键Link C++ Project with Gradle, Build System选择ndk-build,然后查找到 Android.mk文件,提示Path to be saved into the build.gradle file: "Android.mk", 点OK.

    9. rebuild project.

    在项目的appuildintermediates dkBuilddebugobjlocal 路径下, 会看到为不同的系统生成的so库。

    10.在MainActivity中调用JNI方法。

    修改MainActivity代码,设置TextView, (Layout的修改并没有写在这里),在emulator上运行app, 可以看到显示出在c++代码中返回的话。

    public class MainActivity extends AppCompatActivity {
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            //invoke jni function
            TextView view = findViewById(R.id.text);
            view.setText(myJNI.sayHello());
        }
    }

    至此通过静态注册的方法,编写JNI代码的流程已经介绍完了。关于如何通过动态注册的方式调用JNI方法,请参考后续的介绍。

  • 相关阅读:
    团队作业(三)
    第四章学习笔记
    2.3.1测试
    缓冲区溢出漏洞实验
    第三章学习笔记
    团队作业(二)
    第十一章学习笔记
    第7,8章自学笔记
    stat命令实现—mystat
    第五章学习笔记
  • 原文地址:https://www.cnblogs.com/scarecrow-blog/p/9144698.html
Copyright © 2011-2022 走看看