详细的NDK使用教程

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_31588719/article/details/79105426

     由于忙于公司项目,许久未写博客,而且项目中许久未用到ndk,最近项目要用上,于是今天就重温下ndk的使用教程,加深印象,也给一些未接触过ndk的同学提供涓埃之力。网上的ndk资料也是有很多,但有些还是不全或者有些问题的,其实还是需要自己亲自动手摸索,踩踩雷,总结经验。 

1.先要去下载好NDK,有很多版本,现在最新的版本好像是r16了,用老点的版本也行。我这里用的是r10e,其实就是一个压缩文件,双击运行就会自动解压缩生成一个文件夹,我们要用的就是这个文件夹。


 2.编写native方法,放在一个类中,这个类就放native方法,只是申明出来,具体方法逻辑待会用c/c++去实现的,这个类仅仅充当一个桥梁,让java和c/c++进行混合调用。我这里就申明一个native方法,名字叫test_jni,修饰符,返回值该有的都用,就没方法体。其中还有个static静态块,里面System.loadLibrary(),用来装载库文件,不论是JNI库文件还是非JNI库文件。在任何本地方法被调用之前必须先用这个两个方法之一把相应的JNI库文件装载。我这里随便取个名字就叫Jnilib。

public class TestJni {

    static {
        System.loadLibrary("Jnilib");
    }

    public static native String test_jni();
}


3.用Android Studio自带的命令窗Terminal来编译刚才那个类,生成class文件,Terminal一般默认在Android Studio下面,如果找不到可以在这里面打开。

Terminal命令窗里面把路径指到那个放有native方法的那个类所在的文件夹下。因为我就放在java文件夹目录下于路劲就是:E:\android_project\Test1\app\src\main\java>

然后用javah命令来编译那个有native的java类,当然,还要带上-jni,而且这个类是全类名,也就是说包含前面包名,后面不需要后缀。于是总体就是这样:

E:\android_project\Test1\app\src\main\java>javah -jni com.tencent.test1.TestJni

回车编译之后就会生成一个.h的文件

然后新建jni文件夹,我在里面创建一个test.c的文件,名字我随便取的,然后就把刚才生成的.h文件里的内容全部复制到test.c里面去。然后我们再来修改test.c里面的东西,也就是实现刚才的空方法,别的都不动,就是给了方法体,里面返回一个字符串"Hellp Jni!!!!",还在参数列表中加了 env 和jclass。这里又有知识点了,JNIEnv的用法,你们自己搜索相关资料,这个我也不太懂,反正这个方法就是返回一个字符串。

 
 
 
 
JNIEXPORT jstring JNICALL Java_com_tencent_test1_TestJni_test_1jni
        (JNIEnv *env, jclass jclass){

    return (*env)->NewStringUTF(env,"Hello JNI!!!!!");

}
 
 

4.把NDk配置一下,也就是在Project的local.properties文件添加刚才解压出来的NDK文夹路径:

然后再配置下module的build.gradle,在defaultConfig节点里面添加代码,其中里面的mudoleName就是走来loadLibrary方法里面的字符串,也就是Jnilib,abiFilter是的要生成的不同架构对应的so文件

 System.loadLibrary("Jnilib");
 
 
ndk{
    moduleName "Jnilib"
    abiFilters "armeabi","armeabi-v7a","x86"
}
最后还要在gradle.properties里面加上 android.useDeprecatedNdk=true ,在最下面加即可。

5.配置so文件,通过rebuild Project把son文件生成出来,so文件在项目的app\build\intermediates\ndk\debug\lib路径下。里面生成出了三种不同手机架构的so文件。

我们在main文件夹下面新建jniLIB文件夹,把这so来库拷贝过去

最后我们就能使用刚才那个native方法了,因为native方法是申明为静态的,所以可以直接用类名.方法名即可调用。比如:

 
 
TextView  tv_ndk = ((TextView) findViewById(R.id.tv_ndk));
tv_ndk.setText(TestJni.test_jni());
 
 

界面就会显示这个TextView里面的文本,Hello JNI!!!!!。

好了,这就结束了,还是比较简单吧,只要细心做好每一步就行,ndk可能会出现一些莫名其妙的问题,但是网上都会有解决方法。

 
 
 
 
 

猜你喜欢

转载自blog.csdn.net/qq_31588719/article/details/79105426