Android studio下的DNK开发JNI详解流程

来源:互联网 发布:淘宝旺旺买家 编辑:程序博客网 时间:2024/06/03 22:56

什么是NDK(android native develop kits ):android 本地开发工具集 ,可以把c/c++ ->编译成一个 linux下可以执行的二进制文件 java代码里面就可以通过jni 调用执行二进制的文件.

        什么是JNI :java本地开发接口,JNI是一个协议这个协议用来沟通java代码和外部的本地代码(c/c++).通过这个协议,java代码就可以调用外部的c/c++,代码外部的c/c++代码也可以调用java代码。

  JNI开发用途:驱动开发 (wifi-hotspot) 2.3无线热点共享  ,Native code效率高,数学运算,实时渲染的游戏上,音视频处理(极品飞车,opengl,ffmpeg),复用代码(文件压缩,人脸识别…)等。

第一步

1、为了使用studio的Terminal需要把NDK的根目录放到环境变量中,然后重启studio
查看File-->Project Structure-->SDK Location 中第三行 Android NDK location 例如(D:\sdk\ndk-bundle)
可以在local.properties中看到
  1. ndk.dir=D\:\\sdk\\ndk-bundle
  2. sdk.dir=D\:\\sdk

第二步

然后build--Make Project 可以在app/build/intermediates/classes/debug/com/ontim/hellojni/看到MainActivity.class文件)

3、生成头文件,我们要用的命令是javah -d <dir> -classpath <path>
javah是生成jni头文件的命令;    -d是生成的头文件存放的目录(这个目录如果事先没有建立,那么运行成功会自动新建);   <dir>是前面-d选项的目录名称,如果目录是src的话,不要写成<src>!!,直接写src就好;   -classpath从中加载类的路径命令;    <path>是需要生成头文件的class文件的目录。


打开studio的Terminal  --》  cd app/src/main中执行如下

javah -d jni -classpath D:\sdk\platforms\android-24\android.jar;..\..\build\intermediates\classes\debug com.ontim.hellojni.MainActivity
如果提示缺少指定类,缺少v4包,缺少v7包,则用下边最全的(把sdk路径换成自己的,最后的class文件报名改为自己的..\..\build\intermediates\classes\debug com.ontim.hellojni.MainActivity指的是你的class文件);


javah -d jni -classpath D:\sdk\platforms\android-24\android.jar;D:\sdk\extras\extras\android\support\v4\android-support-v4.jar;D:\sdk\extras\extras\android\support\v7\appcompat\libs\android-support-v4.jar;D:\sdk\extras\extras\android\support\v7\appcompat\libs\android-support-v7-appcompat.jar;..\..\build\intermediates\classes\debug com.ontim.hellojni.MainActivity
如果出现以下错误(不出现的话最好加上)

Error:Execution failed for task ':app:compileDebugNdk'.> Error: NDK integration is deprecated in the current plugin.  Consider trying the new experimental plugin.  For details, see http://tools.android.com/tech-docs/new-build-system/gradle-experimental.  Set "android.useDeprecatedNdk=true" in gradle.properties to continue using the current NDK integration.
则在fradle.properties中增加

android.useDeprecatedNdk=true
然后就可以在main目录下看到jni文件夹,里面包含.h文件,包含声明方法

4、创建.c文件,用以实现.h头文件中的声明方法
例,一个简单的返回字符串操作方法


  • JNIEXPORT jstring JNICALL Java_com_ontim_hellojni_MainActivity_helloFromC
  • (JNIEnv *env, jobject onj)
  • {
  • return (*env)->NewStringUTF(env,"Hello JNI");
  • }
  • 5  在 jni下创建Android.mk文件

    #指定编译的文件夹  指定当前文件目录LOCAL_PATH := $(call my-dir)#编译器会定义很多的临时变量,中间变量,最好清空所有的中间变量。include $(CLEAR_VARS)#编译出来模块的名称LOCAL_MODULE    := MyLib# 编译的源代码的名称LOCAL_SRC_FILES := hello.c#编译一个动态库,静态库#静态库 文件名.a   包含所有的函数并且函数运行的依赖,体积大,包含所有的API#动态库 文件名.so  包含函数,不包含函数运行的依赖,体积小,运行的时候,去操作系统寻找需要的APIinclude $(BUILD_SHARED_LIBRARY)<pre name="code" class="html">

    6   cd 到jni 目录执行ndk-build.cmd会出现

        D:\code\HelloJNI\app\src\main\jni>ndk-build.cmd    [arm64-v8a] Compile        : MyLib <= hello.c    [arm64-v8a] SharedLibrary  : libMyLib.so    [arm64-v8a] Install        : libMyLib.so => libs/arm64-v8a/libMyLib.so    [x86_64] Compile        : MyLib <= hello.c    [x86_64] SharedLibrary  : libMyLib.so    [x86_64] Install        : libMyLib.so => libs/x86_64/libMyLib.so    [mips64] Compile        : MyLib <= hello.c    [mips64] SharedLibrary  : libMyLib.so    [mips64] Install        : libMyLib.so => libs/mips64/libMyLib.so    [armeabi-v7a] Compile thumb  : MyLib <= hello.c    [armeabi-v7a] SharedLibrary  : libMyLib.so    [armeabi-v7a] Install        : libMyLib.so => libs/armeabi-v7a/libMyLib.so    [armeabi] Compile thumb  : MyLib <= hello.c    [armeabi] SharedLibrary  : libMyLib.so    [armeabi] Install        : libMyLib.so => libs/armeabi/libMyLib.so    [x86] Compile        : MyLib <= hello.c    [x86] SharedLibrary  : libMyLib.so    [x86] Install        : libMyLib.so => libs/x86/libMyLib.so    [mips] Compile        : MyLib <= hello.c    [mips] SharedLibrary  : libMyLib.so    [mips] Install        : libMyLib.so => libs/mips/libMyLib.so

    在app buid.gradle中增加

        android {        ...        defaultConfig {            ...            ndk {             moduleName "MyLib"  //指定生成动态库的名称           }        }       ...    }
    在mainactivity中使用

    static{            System.loadLibrary("MyLib");//不要前缀        }


        public class MainActivity extends Activity {        static{            System.loadLibrary("MyLib");        }        @Override        protected void onCreate(Bundle savedInstanceState) {            super.onCreate(savedInstanceState);            setContentView(R.layout.activity_main);        }        public native String helloFromC();        public void click(View view){            String str = helloFromC();            Toast.makeText(this, str, Toast.LENGTH_SHORT).show();        }    }
















    2 0
    原创粉丝点击