Android Studio 中關于NDK編譯及jni header生成的問題
之前由于工作原因使用grails這個基于groovy的框架做項目,對groovy感覺很好。
基于groovy的gradle構建系統(tǒng)對我而言自然也是好的沒得說。
Android Studio 正式版出來沒多久,不完善的地方自然很多,對于從eclipse轉來的伙伴們而言,不了解groovy的話對于gradle android的dsl自然是一頭霧水,其實groovy蠻好,花點時間學學,目前已經(jīng)支持android開發(fā)了。
最近干的活設計到NDK開發(fā),在編譯時遇到一些不好搞定的問題。
gradle 的NDK編譯
使用gradle編譯ndk后會發(fā)現(xiàn),gradle其實是自己按dsl生成了android.mk,然后執(zhí)行ndk-build命令,仔細對比會發(fā)現(xiàn),它沒有生成application.mk。那么問題來了,對于我的項目而言,使用gradle總是編譯不過去,而自己運行ndk-build則不會出現(xiàn)問題。
構建系統(tǒng)本來就是解決了這種批處理問題,不想拋開gradle而手動去編譯,干脆就讓gradle執(zhí)行自己的ndkbuild Task。
通過不斷試錯,整理如下Task:
// 編譯NDK代碼
task ndkBuild(type: Exec, description: 'Compile JNI source via NDK') {
// android.mk 地址 ,自行更改
def androidMK = "$projectDir/src/main/jni/Android.mk"
// application.mk 地址, 自行更改
def applicationMK = "$projectDir/src/main/jni/Application.mk"
def ndkDir = project.plugins.findPlugin('com.android.application').getNdkFolder()
def cmd = ["$ndkDir/ndk-build", "NDK_PROJECT_PATH=$buildDir",
"APP_BUILD_SCRIPT=$androidMK", "NDK_APPLICATION_MK=$applicationMK"]
commandLine cmd
}
// 打包native庫, 會在編譯java代碼后執(zhí)行
task ndkLibsToJar(type: Zip, dependsOn: ["compileDebugJava", ndkBuild],
description: 'Create a JAR file of the native libs') {
destinationDir new File(projectDir, 'libs')
baseName 'ndk-libs'
extension 'jar'
from(new File(buildDir, 'libs')) { include '**/*.so' }
into 'lib/'
}
dependencies {
compile fileTree(dir: new File(projectDir, 'libs'), include: ['*.jar'])
}
當然,首先要確保項目根目錄下 local.properties 中有ndk的目錄位置的設定 ndk.dir=/YOUR_NDK_FOLDER
生成JNI頭文件
本來javah的參數(shù)就麻煩,有其實classpath的設定,還得指定包名,很是麻煩,如果包含native聲明方法的類中包含了android庫,不指定好android.jar就更麻煩。
// 生成jni頭文件,在編譯java后運行
task generateJNI(dependsOn: "compileDebugJava",
description: 'Create jni header'){
//要生成的類名, 可以多個
def classes = ["org.jcuraengine.JCuraEngine"]
//jni生成到哪里
def destdir = "$projectDir/src/main/jni/jcuraengine"
// 獲取android jar
def rootDir = project.rootDir
def localProperties = new File(rootDir, "local.properties")
Properties properties = new Properties()
localProperties.withInputStream { instr ->
properties.load(instr)
}
def sdkDir = properties.getProperty('sdk.dir')
def androidJarPath = sdkDir + "/platforms/" + android.compileSdkVersion + "/android.jar"
def classesName = ""
classes.each{
classesName += " $it"
}
// 調用 javah
try {
// exec會出現(xiàn)錯誤,這里使用ant
// 第一次運行這個task時,會出現(xiàn)錯誤,是android studio導致的,運行兩次既可,忽視第一次執(zhí)行時的異常
// 當然,注意觀察第一次的異常,確保不是代碼自身問題。
ant.javah(class: classesName, destdir: destdir, classpath:"$androidJarPath:$buildDir/intermediates/classes/debug/")
} catch (def e) {
println e
}
}
這兩個task,在android stuido右側gradle tasks版面中會自動添加的。
浙公網(wǎng)安備 33010602011771號