android studio 進行ndk/jni開發
一、前言:之前用eclipse開發ndk的時候大家是不是很痛苦,要做的事情很多:
//NDK開發流程:
1、在java程式碼中 宣告本地方法(native)
2、通過javah工具完成jni樣式的標頭檔案(.h檔案)的生成
3、在工程中 建立jni目錄,在jni目錄中編寫 與java本地方法對應的C方法
jstring Java_包名_類名_方法名(){...}
4、編寫Android.mk檔案,來指定如何編譯C程式碼
5、通過ndk-build工具來完成交叉編譯 ,生成Anroid 中可以呼叫的2進位制檔案(連結庫檔案)
6、在Java程式碼中引用System.loadLibrary("hello-jni");
這個過程是非常的繁瑣,執行ndk-build命令還需要裝cgwin
但是現在Android Studio集成了ndk開發環境(ndk如何配置就不說了),我們只需要走這麼幾步就可以了:
二、Android Studio進行ndk開發
1、建立工程的時候需要勾上支援ndk開發
2、預設選擇支援標準c++就可以了
C++ Standard:使用下拉列表選擇使用哪種 C++ 標準。選擇 Toolchain Default 會使用預設的 CMake 設定。
Exceptions Support:如果希望啟用對 C++ 異常處理的支援,請選中此複選框。如果啟用此複選框,Android Studio 會將 -fexceptions 標 志新增到模組級 build.gradle檔案的 cppFlags中,Gradle 會將其傳遞到 CMake。
Runtime Type Information Support:如果希望支援 RTTI,請選中此複選框。如果啟用此複選框,Android Studio 會將 -frtti 標誌新增到模 塊級 build.gradle檔案的 cppFlags中,Gradle 會將其傳遞到 CMake。
3、建立好的工程
建立好的工程多了cpp目錄,這是寫c++的包,還多了CMakeLists.txt,這是編譯程式碼,makefile都幫我們寫好了,我們用的時候只需要修改裡面的程式碼即可:
看一下build.gradle:
android {
compileSdkVersion 28
defaultConfig {
applicationId "com.jni.jnidemo"
minSdkVersion 26
targetSdkVersion 28
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
externalNativeBuild {
cmake {
// 預設是 "cppFlags" "" ,如果要修改 Customize C++ Support 部分,可在這裡加入cppFlags "-frtti -fexceptions"
cppFlags ""
}
}
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
// 指定c++編譯程式碼的路徑
externalNativeBuild {
cmake {
path "CMakeLists.txt"
}
}
}
三、總結
進行ndk開發要掌握的步驟:
1、在cpp包下建立自己的.cpp或者.c檔案,編寫自己的c語言程式
2、在CMakeLists.txt中新增add_library,可以生成多個library,所以add_library可以自己在後面加
在CMakeLists.txt中新增target_link_libraries,它也是一樣,可以在後面自己加,不過這個不是必須的
3、在介面中引用一個庫:
static {
System.loadLibrary("native-lib");
}
4、把用c/c++寫的方法用native來宣告:
public native String stringFromJNI();
5、經過以上步驟就可以像普通的方法一樣來呼叫了
四、注意
1、在Activity或者fragment裡面新加的native方法如果.cpp檔案裡面沒有就會報錯,這時候只需要在native方法上Alt + Enter就會自動在cpp檔案裡面生成
2、不同廠商的 Android 手機支援的 CPU 架構不同,我們可以這樣來限制我們支援的架構
defaultConfig {
applicationId "com.jni.jnidemo"
minSdkVersion 26
targetSdkVersion 28
versionCode 1
versionName "1.0"
externalNativeBuild {
cmake {
cppFlags ""
}
}
ndk {
abiFilters 'armeabi'//,'armeabi-v7a','arm64-v8a','x86','x86_64','mips','mips64'
}
}
3、常用工具類:把Java字串轉化成c語言字串
// 把Java字串轉化為C語言字串 char* Jstring2CStr(JNIEnv* env, jstring jstr) { char* rtn = NULL; jclass clsstring = (*env)->FindClass(env,"java/lang/String"); jstring strencode = (*env)->NewStringUTF(env,"GB2312"); jmethodID mid = (*env)->GetMethodID(env,clsstring, "getBytes", "(Ljava/lang/String;)[B"); jbyteArray barr= (jbyteArray)(*env)->CallObjectMethod(env,jstr,mid,strencode); // String .getByte("GB2312"); jsize alen = (*env)->GetArrayLength(env,barr); jbyte* ba = (*env)->GetByteArrayElements(env,barr,JNI_FALSE); if(alen > 0) { rtn = (char*)malloc(alen+1); //"\0" memcpy(rtn,ba,alen); rtn[alen]=0; } (*env)->ReleaseByteArrayElements(env,barr,ba,0); // return rtn; }