Android Studio 中關於NDK編譯及jni header生成的問題

以前因爲工做緣由使用grails這個基於groovy的框架作項目,對groovy感受很好。java

基於groovygradle構建系統對我而言天然也是好的沒得說。android

Android Studio 正式版出來沒多久,不完善的地方天然不少,對於從eclipse轉來的夥伴們而言,不瞭解groovy的話對於gradle android的dsl天然是一頭霧水,其實groovy蠻好,花點時間學學,目前已經支持android開發了。app

最近乾的活設計到NDK開發,在編譯時遇到一些很差搞定的問題。框架

gradle 的NDK編譯

使用gradle編譯ndk後會發現,gradle實際上是本身按dsl生成了android.mk,而後執行ndk-build命令,仔細對比會發現,它沒有生成application.mk。那麼問題來了,對於個人項目而言,使用gradle老是編譯不過去,而本身運行ndk-build則不會出現問題。eclipse

構建系統原本就是解決了這種批處理問題,不想拋開gradle而手動去編譯,乾脆就讓gradle執行本身的ndkbuild Task。gradle

經過不斷試錯,整理以下Task:ui

// 編譯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代碼後執行
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_FOLDERspa

生成JNI頭文件

原本javah的參數就麻煩,有其實classpath的設定,還得指定包名,非常麻煩,若是包含native聲明方法的類中包含了android庫,不指定好android.jar就更麻煩。debug

// 生成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會出現錯誤,這裏使用ant
        // 第一次運行這個task時,會出現錯誤,是android studio致使的,運行兩次既可,忽視第一次執行時的異常
        // 固然,注意觀察第一次的異常,確保不是代碼自身問題。
        ant.javah(class: classesName, destdir: destdir, classpath:"$androidJarPath:$buildDir/intermediates/classes/debug/")
    } catch (def e) {
        println e
    }

}

這兩個task,在android stuido右側gradle tasks版面中會自動添加的。設計

相關文章
相關標籤/搜索