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版面中会自动添加的。设计

相关文章
相关标签/搜索