zoukankan      html  css  js  c++  java
  • Android Studio 中关于NDK编译及jni header生成的问题

    之前由于工作原因使用grails这个基于groovy的框架做项目,对groovy感觉很好。

    基于groovygradle构建系统对我而言自然也是好的没得说。

    Android Studio 正式版出来没多久,不完善的地方自然很多,对于从eclipse转来的伙伴们而言,不了解groovy的话对于gradle android的dsl自然是一头雾水,其实groovy蛮好,花点时间学学,目前已经支持android开发了。

    最近干的活设计到NDK开发,在编译时遇到一些不好搞定的问题。

    gradle 的NDK编译

    使用gradle编译ndk后会发现,gradle其实是自己按dsl生成了android.mk,然后执行ndk-build命令,仔细对比会发现,它没有生成application.mk。那么问题来了,对于我的项目而言,使用gradle总是编译不过去,而自己运行ndk-build则不会出现问题。

    构建系统本来就是解决了这种批处理问题,不想抛开gradle而手动去编译,干脆就让gradle执行自己的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代码后执行
    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的参数就麻烦,有其实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会出现错误,这里使用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版面中会自动添加的。

  • 相关阅读:
    成都磨子桥技工学校 / 数据结构 Challenge 4
    圆桌问题(网络流24题)
    试题库问题(网络流24题)
    [AHOI2005]航线规划
    [AMPPZ2014]The Prices
    方格取数(网络流24题)
    太空飞行计划问题(网络流24题)
    Linux 学习3
    Linux 学习2
    Linux 学习1
  • 原文地址:https://www.cnblogs.com/hangxin1940/p/4262829.html
Copyright © 2011-2022 走看看