在AndroidStudio中使用NDK配置方法
配置Gradle生成so
在AndroidStudio2.1及以前我是通過下面的方式配置NDK的,不知道是從哪個版本開始的,我第一次在AS上使用NDK的時候用的就是AndroidStudio2.1了。
首先在gradle.properties裡面新增 Android.useDeprecatedNDK = true
android{}下的defaultconfig{}程式碼塊中新增ndk{}
ndk{
moduleName = "xxx"
//abiFilters("armeabi", "armeabi-v7a"..)
//ldLibs = ["log"]
//cFlags
//stl(ie:gnustl_shared,stlport_static..)
}
預設在src/main/jni目錄下面找c/c++檔案編譯,也可以在android{}下新增sourceSet{}
sourceSet{
main{
jni.srcDirs=['src/main/cpp']
}
}
就能將指定目錄下的c/c++檔案編譯成指定的模組名.so。
編譯多個模組
上面這種方式通過gradle無法編譯成多個模組,編譯多個模組還是要自己寫Android.mk檔案實現,通過手動執行ndk-build編譯成的*.so檔案預設在src/main/libs下面。
打包APK時,預設是尋找so的目錄是/build/intermediates/ndk和/build/intermediates/jniLibs,前者是使用原始碼由Gradle編譯成的so所處的位置,後者一般是一些第三方的so或者自己手動使用ndk編譯生成的so檔案所生成的,這個位置在src/main/jniLibs。
因此手動編譯好so檔案後,將其複製到jniLibs下面,或者在此放置第三方so,或者在build.gradle檔案裡面的android下面新增jniLib.srcDir定義了Gradle在哪裡尋找生成的so庫檔案
sourceSets{
main{
jniLib.srcDirs=['src/main/libs'] // jniLib.srcDirs定義了Gradle在哪裡尋找生成的so庫檔案
}
}
上面就是使用ndk-build通過自己定義Android.mk生成so的方式,但是分析apk檔案(build->Analyze APK)發現打包進去來了兩個so,下面libnative-lib.so是我在Android.mk中設定的模組名。上面這個其實是Gradle構建的,Gradle構建so的時候預設模組名字就是app,並且預設的編譯c/c++的路徑是src/main/jni,要修改這兩個預設設定就需要像上面配置Gradle構建so的方式修改。
為了在我們自己構建so的時候禁用Gradle需要做的是配置jni.srcDirs設定成一個空的陣列,這樣就可以禁用通過Gradle來編譯本地c/c++程式碼。
sourceSets{
main{
jni.srcDirs=[] // jni.srcDirs禁用通過Gradle來編譯本地c/c++程式碼
}
}
再看apk結構,由Gradle構建的so就不見了。
關聯Android.mk到Gradle
AndroidStudio2.2以後的另一種使用Android.mk的方式,可以不用ndk-build手動構建。
不需要手動使用ndk-build編譯,只需要將其關聯到Gradle上,Gradle 會將 ndk-build作為一個依賴執行,然後將so打包到 apk 中,編譯好的so在目錄/build/intermediates/ndkBuild下面。
滑鼠右鍵要連結的本地庫所在的模組,選擇Link C++ Project with Gradle,在彈出的對話方塊中選擇Build System為ndk-build,再指定Amdroid.mk的路徑點選ok即可
這樣就不用在命令列中手動執行ndk-build編譯了,Gradle就會自動的構建寫好的Android.mk。
上面的操作實際是也可以直接在該模組的build.gradle中的android下面新增
android {
...
defaultConfig {...}
buildTypes {...}
// add manually
externalNativeBuild {
ndkBuild {
path "Android.mk"
// arguments "-DCMAKE_VERBOSE_MAKEFILE=TRUE"
// Sets optional flags for the C compiler.
// cFlags "-D_EXAMPLE_C_FLAG1", "-D_EXAMPLE_C_FLAG2"
// Sets a flag to enable format macro constants for the C++ compiler.
// cppFlags "-D__STDC_FORMAT_MACROS"
}
}
}
使用cmake
AndroidStudio2.2以後還推出了使用cmake指令碼來構建so,方式為在模組根目錄下建立CMakeLists.txt# Sets the minimum version of CMake required to build your native library.
# This ensures that a certain set of CMake features is available to
# your build.
cmake_minimum_required(VERSION 3.4.1)
# Specifies a library name, specifies whether the library is STATIC or
# SHARED, and provides relative paths to the source code. You can
# define multiple libraries by adding multiple add.library() commands,
# and CMake builds them for you. When you build your app, Gradle
# automatically packages shared libraries with your APK.
add_library( # Specifies the name of the library.
native-lib
# Sets the library as a shared library.
SHARED
# Provides a relative path to your source file(s).
src/main/jni/native-lib.c )
然後和上面關聯ndk-build指令碼的方式類似,在彈出的對話方塊中選擇Build System為cmake,再指定CMakeLists.txt的位置。這樣操作類似與直接在該模組的build.gradle中的android下面新增
android {
...
defaultConfig {...}
buildTypes {...}
// add manually
externalNativeBuild {
cmake {
path "CMakeLists.txt"
}
}
}