我觉得这个也是我们Android开发者必须掌握的,所以在这里mark下,我们比较熟悉的是android的SDK开发,一般的开发中我们很少去接触NDK,其实就是我们常说的jni。已经有SDK了,为什么android支持NDK呢,google就是为了让android支持直接去调用c/c++的一些东西,我们都知道c/c++是比Java效率更高的,java是牺牲运行效率,提高编译效果,而c/c++则反之。那么SDK和NDK是什么关系呢,我直接在网上找了一张图来看下
通过上图我们可以知道NDK最终生成的是so文件,然后通过SDK去调用。下面我们就直接来写第一个NDK程序。写之前我们先来准备好环境。
我们在AS直接配置路径就好了,ctr+alt+shift+s,如下图配置!
我们来到local.properties配置下,在最后一行添加
ndk.dir=D:\ProgramData\android-ndk-r9b,这个路径要填你自己ndk的路径。
配置好之后,然后再src目录下的build.gradle的defaultConfig配置下
defaultConfig { .......... ndk{ moduleName "LisnJniLibName" //生成的so名字 abiFilters "armeabi", "armeabi-v7a", "x86" //输出指定三种abi体系结构下的so库。目前可有可无。 } }
android.useDeprecatedNdk=true
在AS中新建一个Project,然后再新建一个class为NdkJniUtils,在内部声明native方法
package com.test.lisn.my_jni; public class NdkJniUtils { public native String getCLanguageString(); }
public class MainActivity extends AppCompatActivity { private TextView mTextView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mTextView = (TextView) this.findViewById(R.id.test); NdkJniUtils jni = new NdkJniUtils(); mTextView.setText(jni.getCLanguageString()); } }
然后build project得到其中中间文件,我们关注的是.class文件。编译OK以后生成的class文件在AS工程的如下目录:
NDKApplication\app\build\intermediates\classes\debug
然后接下来的步骤就是根据生成的class文件,利用javah生成对应的 .h头文件。
点开AS的Terminal标签,默认进入到该项目的app文件夹下。我在windows平台下输入如下命令跳转到class中间文件生成路径:
xxxxx\app> cd build\intermediates\classes\debug
然后执行如下javah命令生成h文件。
xxxxx\debug> javah -jni com.test.lisn.my_jni.NdkJniUtils
执行完之后你可以在文件夹 my_jni/app/build/intermediates/classes/debug下看见生成的 .h头文件为:
com_test_lisn_my_jni_NdkJniUtils.h
里边内容如下:
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_test_lisn_my_jni_NdkJniUtils */
#ifndef _Included_com_test_lisn_my_jni_NdkJniUtils
#define _Included_com_test_lisn_my_jni_NdkJniUtils
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: com_test_lisn_my_jni_NdkJniUtils
* Method: getCLanguageString
* Signature: ()Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_com_test_lisn_my_1jni_NdkJniUtils_getCLanguageString
(JNIEnv *, jobject);
#ifdef __cplusplus
}
#endif
#endif
在工程的main目录下新建一个名字为jni的目录,然后将刚才的 .h文件剪切过来。在jni目录下新建一个c文件,随意取名,我的叫jnitest.c 。然后编辑代码如下(后面会解释啥意思,这里重在工具使用):
接下来在工程的local.properties文件中添加NDK路径(上面下载好的那个NDK),类似其中的SDK路径一样,我的添加后如下:
ndk.dir=D\:\\ProgramData\\android-ndk-r9b sdk.dir=D\:\\ProgramData\\Android\\sdk
现在生成的so库名字也有了,那就去代码的NdkJniUtils Java文件添加静态初始化load代码,添加如下: