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