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

  • 相关阅读:
    7月15日考试 题解(链表+状压DP+思维题)
    暑假集训日记
    C# .NET 使用 NPOI 生成 .xlsx 格式 Excel
    JavaSE 基础 第42节 局部内部类
    JavaSE 基础 第41节 匿名内部类
    JavaSE 基础 第40节 内部类概述
    JavaSE 基础 第39节 接口的应用
    JavaSE 基础 第38节 接口的实现
    JavaSE 基础 第37节 接口概述
    JavaSE 基础 第36节 抽象类概述与使用
  • 原文地址:https://www.cnblogs.com/hangxin1940/p/4262829.html
Copyright © 2020-2023  润新知