1、百度,找到最简单的学习资料,要类似hello world这样的,否则事倍功半,切记!!!
2、还真找到了hello, ^_^
3、
新建一个类,声明native方法。这个类是java与C/C++交互的中介,方法由java声明,由C/C++实现。
不在Activity类里面写是为了避免编译时报错:找不到android.support.v7.app.AppCompatActivity
public class myJNI { //加载so库 static { System.loadLibrary("JniTest"); } //native方法 public static native String sayHello(); }
4、上一步基本不会有错,且看这一步:打开android studio终端,使用javac编译上述文件,生成class文件。
命令:
D:\AndroidStudioProject\testJNI\app\src\main\java\com\example\binbin\testjni>javac myJNI.java
注:这一步就有两问题,首先,要用CD命令(跟DOS命令一个意思)进入到前面所建的类的那个目录。
其次 很容易出现 错误: 编码GBK的不可映射字符,这时就要对javac 命令加参数,变成如下:
javac -encoding UTF-8 myJNI.java
OK,这下不报错了,通过,你会发现那目录下多了一个myJNI.class的文件
5、确认自己类的包名!然后在上一级的位置使用javah生成.h头文件
一定要在上一级哦,不然不会报错:找不到xxx类
这里一定要注意,要用CD.. 命令往回走到包的起始目录,比如我这里就要回到D:\AndroidStudioProject\testJNI\app\src\main\java 目录下,然后执行javah 命令,包名是放在参数中了
D:\AndroidStudioProject\testJNI\app\src\main\java>javah -jni com.example.binbin.testjni.myJNI
OK,现在在java目录下生成了一个 .h 文件,文件名有点长。
第4步是javac, 第5步是javah
6、在java目录下新建目录:jni, 在这新目录下新建main.c文件,同时把上一步生成的.h文件中的内容复制到此文件中
注:这里新建的时候,不要建成c/c++ class, 而是要选c/c++ source file ,开始没留意,死也建不成功。
原.h文件内容:
/* DO NOT EDIT THIS FILE - it is machine generated */ #include <jni.h> /* Header for class com_example_binbin_testjni_myJNI */ #ifndef _Included_com_example_binbin_testjni_myJNI #define _Included_com_example_binbin_testjni_myJNI #ifdef __cplusplus extern "C" { #endif /* * Class: com_example_binbin_testjni_myJNI * Method: sayHello * Signature: ()Ljava/lang/String; */ JNIEXPORT jstring JNICALL Java_com_example_binbin_testjni_myJNI_sayHello (JNIEnv *, jclass); #ifdef __cplusplus } #endif #endif
复制,并修改后的main.c中的代码,就增加了一行 return :
/* DO NOT EDIT THIS FILE - it is machine generated */ #include <jni.h> /* Header for class com_example_binbin_testjni_myJNI */ #ifndef _Included_com_example_binbin_testjni_myJNI #define _Included_com_example_binbin_testjni_myJNI #ifdef __cplusplus extern "C" { #endif /* * Class: com_example_binbin_testjni_myJNI * Method: sayHello * Signature: ()Ljava/lang/String; */ //就实现了个函数 JNIEnv的用法可以自行百度,这里就不展开了 JNIEXPORT jstring JNICALL Java_com_example_binbin_testjni_myJNI_sayHello (JNIEnv *env, jclass jobj){ //返回一句话 return (*env)->NewStringUTF(env,"JNI hahahahahahahaha"); } #ifdef __cplusplus } #endif #endif
7、据说还要jni目录下增加一个util.c的文件,否则会报错,暂不管,等看到报错再说,否则都不知有什么错,不利于学习^_^
8、配置NDK
打开Project的local.properties文件添加NDK路径
到了这里才发现没有NDK,不要紧,按下面的链接,两三分钟就下好了,现在对谷歌的下载界面已经没有屏蔽了,要是几年前,光下这个,估计就不知要到什么时候去了,当然那里网速也慢。^_^
https://dl.google.com/android/repository/android-ndk-r19c-windows-x86_64.zip
打开app Module的build.gradle文件,在defaultConfig节点里添加以下代码 注意这里的moduleName,是我们在之前自己编写的类里面加载的so库名
ndk { moduleName "JniTest" ldLibs "log", "z", "m" abiFilters "armeabi", "armeabi-v7a", "x86" }
这里有个坑的地方是,build.gradle文件不要找错一个了,否则没地方加这一小段,
另外 abiFilters "armeabi", "armeabi-v7a", "x86" 这个好象是指要匹配的CPU类型??
还要在gradle.properties里面加上这么一句话:android.useDeprecatedNdk=true
配置完成
9、生成SO库
完成以上步骤之后,我们rebuild一下就可以生成so库了
在项目的app\build\intermediates\ndk\debug\lib路径下
这一步,死活成功不了,在这intermediates目录下,找不着ndk目录,我倒。。。。然后jniLibs下也没有东西
再百度,发现还需要在build.gradle中增加
sourceSets{ main{ jniLibs.srcDir 'src/main/java/jni'//告知jni源码目录 } }
追加在NDK配置时,那一段NDK的后面即可
但是这到,仍然没有生成SO文件
已经好晚了,先到这儿,改天继续研究,暂时判断的错误是前文关于NDK的配置是有问题的,android.useDeprecatedNdk要取消了:
Error: Flag android.useDeprecatedNdk is no longer supported and will be removed in the next version of Android Studio