【问题标题】:How to build single APK with Android NDK and Gradle如何使用 Android NDK 和 Gradle 构建单个 APK
【发布时间】:2015-02-12 18:43:54
【问题描述】:

我正在使用 OpenCV(C++ 而不是 Java)开发一个新的 android 应用程序,而且我对 opencv 和 NDK 都是新手。我使用下面的 Gradle 文件成功构建(并运行)它,在 Android Studio 中我可以选择一个变体并点击构建(例如 x86)。

我有两个问题:

  1. 有没有一种方法可以让我构建一个支持所有架构的 APK 的变体? (我知道文件会更大)
  2. 我能否在不为每个变体指定所有相同库的情况下实现构建。有什么办法可以让构建系统每次都拿起库,因为它们都在项目中并按架构名称组织?

    apply plugin: 'com.android.application'
    
    android {
    compileSdkVersion 21
    buildToolsVersion "21.0.0"
    
    defaultConfig {
        applicationId "uk.co.xxx.androidcppimagereader"
        minSdkVersion 17
        targetSdkVersion 21
        versionCode 1
        versionName "1.0"
    }
    
    def libsDir = projectDir.path + "/libs/"
    
    productFlavors {
        x86 {
            versionCode Integer.parseInt("3" + defaultConfig.versionCode)
            ndk {
                abiFilter "x86"
                moduleName "Processing"
                stl "gnustl_static"
                cFlags "-I/opt/local/include/opencv -I/opt/local/include"
                ldLibs libsDir + "x86/libopencv_core.a"
                ldLibs libsDir + "x86/libopencv_ts.a"
                ldLibs libsDir + "x86/libopencv_contrib.a"
                ldLibs libsDir + "x86/libopencv_ml.a"
                ldLibs libsDir + "x86/libopencv_java.so"
                ldLibs "log"
                ldLibs "z", "jnigraphics"
            }
        }
        armv7 {
            versionCode Integer.parseInt("2" + defaultConfig.versionCode)
            ndk {
                abiFilter "armeabi-v7a"
                moduleName "Processing"
                stl "gnustl_static"
                cFlags "-I/opt/local/include/opencv -I/opt/local/include"
                ldLibs libsDir + "armeabi-v7a/libopencv_core.a"
                ldLibs libsDir + "armeabi-v7a/libopencv_ts.a"
                ldLibs libsDir + "armeabi-v7a/libopencv_contrib.a"
                ldLibs libsDir + "armeabi-v7a/libopencv_ml.a"
                ldLibs libsDir + "armeabi-v7a/libopencv_java.so"
                ldLibs "log"
                ldLibs "z", "jnigraphics"
            }
        }
        arm {
            versionCode Integer.parseInt("1" + defaultConfig.versionCode)
            ndk {
                abiFilter "armeabi"
                moduleName "Processing"
                stl "gnustl_static"
                cFlags "-I/opt/local/include/opencv -I/opt/local/include"
                ldLibs libsDir + "armeabi/libopencv_core.a"
                ldLibs libsDir + "armeabi/libopencv_ts.a"
                ldLibs libsDir + "armeabi/libopencv_contrib.a"
                ldLibs libsDir + "armeabi/libopencv_ml.a"
                ldLibs libsDir + "armeabi/libopencv_java.so"
                ldLibs "log"
                ldLibs "z",  "jnigraphics"
            }
        }
    
    }
    
        buildTypes {
             release {
                minifyEnabled false
                proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
            }
        }
    }
    
    dependencies {
        compile fileTree(dir: 'libs', include: ['*.jar'])
        compile 'com.android.support:appcompat-v7:21.0.3'
    }
    

【问题讨论】:

    标签: android gradle android-ndk


    【解决方案1】:

    在 build.gradle 文件中定义了计划包含在 apk 中的所有架构后,请使用关键字“fat”,如下面的代码中突出显示的那样。这将构建一个 FAT 二进制文件。观看此视频了解更多详情https://www.youtube.com/watch?v=kFtxo7rr2HQ

    arm {
        versionCode Integer.parseInt("1" + defaultConfig.versionCode)
        ndk {
            abiFilter "armeabi"
            moduleName "Processing"
            stl "gnustl_static"
            cFlags "-I/opt/local/include/opencv -I/opt/local/include"
            ldLibs libsDir + "armeabi/libopencv_core.a"
            ldLibs libsDir + "armeabi/libopencv_ts.a"
            ldLibs libsDir + "armeabi/libopencv_contrib.a"
            ldLibs libsDir + "armeabi/libopencv_ml.a"
            ldLibs libsDir + "armeabi/libopencv_java.so"
            ldLibs "log"
            ldLibs "z",  "jnigraphics"
        }
        fat // <- HERE
    }
    
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
    

    【讨论】:

    • 好的,谢谢。我之前曾尝试使用“fat”但没有成功,但现在再次尝试干净并重建,它出现在我的构建变体中。关于拆分,您如何在更新 gradle 文件后使其全部构建 - 我以前看不到这个?这也应该出现在“通用”或类似的变体列表中吗?
    【解决方案2】:

    为了正确链接您的库,您必须像当前所做的那样为每个架构声明不同的 ldLib。

    不幸的是,如果您要同时为所有架构构建,则无法使用当前插件从 gradle 执行此操作。

    在我看来,最好的解决方案是停用内置(当前已弃用)的 ndk 支持并改用常规 Android.mk / Application.mk 文件。你的 build.gradle 看起来像这样:

    import org.apache.tools.ant.taskdefs.condition.Os
    
    apply plugin: 'com.android.application'
    
    android {
        compileSdkVersion 21
        buildToolsVersion "21.1"
    
        defaultConfig {
            applicationId "uk.co.xxx.androidcppimagereader"
            minSdkVersion 17
            targetSdkVersion 21
            versionCode 1
            versionName "1.0"
        }
    
        sourceSets.main {
            jniLibs.srcDir 'src/main/libs' //set libs as default directory for .so files inclusion, instead of jniLibs
            jni.srcDirs = [] //disable automatic ndk-build call
        }
    
        // call regular ndk-build(.cmd) script from app directory
        task ndkBuild(type: Exec) {
            if (Os.isFamily(Os.FAMILY_WINDOWS)) {
                commandLine 'ndk-build.cmd', '-C', file('src/main').absolutePath
            } else {
                commandLine 'ndk-build', '-C', file('src/main').absolutePath
            }
        }
    
        tasks.withType(JavaCompile) {
            compileTask -> compileTask.dependsOn ndkBuild
        }
    }
    

    【讨论】:

    • 谢谢。所以..如果我使用makefile,是否应该构建所有架构然后将输出库复制到src/main/libs?我是 NDK 开发的新手,所以我不太清楚 Android.mk 输出结构应该是什么
    • 没错。查看 NDK 中的示例,了解如何编写 Android.mk 和 Application.mk 文件。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-09-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-08-07
    • 2017-02-03
    • 2016-01-19
    相关资源
    最近更新 更多