Gradle android构建用于不同的处理器架构

Blu*_*kee 32 android opencv multiprocessor gradle android-gradle-plugin

我想使用Gradle为4种不同的Android CPU处理器架构(armeabi armeabi-v7a x86 mips)构建4个独立的apks.

我在libs文件夹中为4个CPU架构构建了本机OpenCV库.

libs
    -armeabi
    -armeabi-v7a
    -x86
    -mips
Run Code Online (Sandbox Code Playgroud)

我想每个apk只包含对应正确CPU架构的OpenCV库.

当前的构建脚本如下:

apply plugin: 'android'

dependencies {
    compile fileTree(dir: 'libs', include: '*.jar')
    compile project(':workspace:OpenCV4Android:sdk:java')
}

android {
    compileSdkVersion 11
    buildToolsVersion "18.1.0"

    sourceSets {
        main {
            manifest.srcFile 'AndroidManifest.xml'
            java.srcDirs = ['src']
            resources.srcDirs = ['src']
            aidl.srcDirs = ['src']
            renderscript.srcDirs = ['src']
            res.srcDirs = ['res']
            assets.srcDirs = ['assets']
        }

        // Move the tests to tests/java, tests/res, etc...
        instrumentTest.setRoot('tests')

        debug.setRoot('build-types/debug')
        release.setRoot('build-types/release')

        flavorGroups "abi", "version"
        productFlavors {
            x86 {
                flavorGroup "abi"
            }
            arm {
                flavorGroup "abi"
            }
            mips {
                flavorGroup "abi"
            }
        }

    }
}
Run Code Online (Sandbox Code Playgroud)

有人可以帮我解决这个问题吗?

干杯,

wit*_*ass 25

从Android Gradle Plugin版本13开始,您现在可以使用新的"拆分"机制生成单独的APK.你可以在这里阅读它.

放置.so文件的默认文件结构是:

src
-main
  -jniLibs
    -armeabi
      -arm.so
    -armeabi-v7a
      -armv7.so
    -x86
      -x86.so
    -mips
      -mips.so
Run Code Online (Sandbox Code Playgroud)

请注意,只要具有.so扩展名,.so文件的名称就不重要了.

然后在Gradle构建文件中:

android {
...
splits {
abi {
  enable true
  reset()
  include 'x86', 'armeabi-v7a', 'mips', 'armeabi'
  universalApk false
  }
 }
}
Run Code Online (Sandbox Code Playgroud)

// map for the version code
ext.versionCodes = ['armeabi-v7a':1, mips:2, x86:3]

import com.android.build.OutputFile

android.applicationVariants.all { variant ->
    // assign different version code for each output
    variant.outputs.each { output ->
        output.versionCodeOverride =
            project.ext.versionCodes.get(output.getFilter(OutputFile.ABI)) * 1000000 + android.defaultConfig.versionCode
    }
}
Run Code Online (Sandbox Code Playgroud)

请注意,ext.versionCodes上面的版本代码在很大程度上是无关紧要的,这是为每个ABI类型添加一个唯一的偏移量,因此版本代码不会发生冲突.

  • 这些修改到哪个build.gradle文件?项目一个或主要模块"app"一个?还有我们在哪里添加第二批代码?在哪个街区?你能告诉我们一个完整的build.gradle示例代码吗? (3认同)
  • 谢谢你的详细信息.我收到错误'无法在null上执行mulitply()因为output.getFilter(OutputFile.ABI)返回'armabi'并且在versionCodes映射中没有该条目.我添加了值为1并增加了所有其他值,它现在可以工作了.你有没有试过密度分裂?这是否需要进一步的版本代码技巧才能成功地通过abi和密度分割apk? (2认同)

Seb*_*ese 14

用于gradle的拆分ABI APK解决方案是迄今为止我发现的最简单的解决方案.@withoutclass在这里写得很好:https://stackoverflow.com/a/26129447/254573 我不得不参考Android文档,因为这是一个新功能,仍然可以改变:http://tools.android.com/tech -docs /新制造的系统/用户引导/ APK-分裂

但是,我最终不得不放弃这个简单的实现,因为我需要支持胖构建和体系结构特定的构建.如果您同时支持Google Play商店(支持特定于架构的APK)和Amazon Appstore(仅支持胖版APK),则可能会遇到同样的问题.

如果您可以添加风味组件,则可以使用拆分APK执行此操作,但目前尚不支持split + flavor:https://code.google.com/p/android/issues/detail?id = 76469

我最终使用了abiFilter,请参阅下面的示例代码:

android {
    flavorDimensions "abi"

    productFlavors {
        fat {
            flavorDimension "abi"
            ndk {
                abiFilters "x86", "armeabi-v7a", "armeabi"
                versionCode = 0;
            }
        }
        arm {
            flavorDimension "abi"
            ndk {
                abiFilter "armeabi"
                versionCode = 1;
            }
        }
        armv7a {
            flavorDimension "abi"
            ndk {
                abiFilter "armeabi-v7a"
                versionCode = 3;
            }
        }
        x86 {
            flavorDimension "abi"
            ndk {
                abiFilter "x86"
                versionCode = 6;
            }
        }
    }
}

// Each APK needs a different version code when submitted to Google,
// bump the versionCode we set in defaultConfig
android.applicationVariants.all { variant ->
    // Ugly hard coded flavorDimensions position
    // If you have more than one flavorDimension, make sure to target the position for "abi"
    def abiVersion = variant.productFlavors.get(0).versionCode

    variant.mergedFlavor.versionCode = abiVersion * 1000 + android.defaultConfig.versionCode
}
Run Code Online (Sandbox Code Playgroud)

更新 使用universalApk设置为true解决此解决方案,只需添加时间来构建每个apk.

android {
    // Rest of Gradle file
        splits {
            abi {
            enable true
            reset()
            include 'armeabi', 'armeabi-v7a', 'x86'
            universalApk true
        }
    }
}

//Ensures architecture specific APKs have a higher version code
//(otherwise an x86 build would end up using the arm build, which x86 devices can run)
ext.versionCodes = [armeabi:1, 'armeabi-v7a':3, x86:6]

android.applicationVariants.all { variant ->
    // assign different version code for each output
    variant.outputs.each { output ->
        int abiVersionCode = project.ext.versionCodes.get(output.getFilter(OutputFile.ABI)) ?: 0
        output.versionCodeOverride = (abiVersionCode * 1000) + android.defaultConfig.versionCode
    }
}
Run Code Online (Sandbox Code Playgroud)


gre*_*gko 3

我没有 gradle 答案,但我想我现在对任何 Android 构建工具都有一个通用答案。以下是我关于如何为每个支持的处理器架构创建单独的 APK 文件的想法:

\n\n
    \n
  1. 使用您使用的任何工具构建您的APK,其中包含您支持的所有本机代码库,例如armeabi、armeabi-v7a、x86 和mips。我将其称为“原始”APK 文件。

  2. \n
  3. 使用任何 zip/unzip 实用程序将原始 APK 解压到一个空文件夹中,最好使用命令行工具,以便稍后可以使用 shell 脚本或批处理文件将其自动化。

  4. \n
  5. 在原APK解压到的文件夹中,删除META-INF子文件夹(该子文件夹包含签名,所有修改后我们需要对APK重新签名,因此必须删除原来的META-INF)。

  6. \n
  7. 更改为 lib 子文件夹,并删除新 APK 文件中不需要的任何处理器架构的子文件夹。例如,仅保留“x86”子文件夹来为 Intel Atom 处理器制作 APK。

  8. \n
  9. 重要提示:针对不同架构的每个 APK,在 AndroidManifest.xml 中必须具有不同的“versionCode”编号,并且例如armeabi-v7a的版本代码必须略高于armeabi的版本代码(请阅读Google关于创建多个APK的说明)这里: http: //developer.android.com/google/play/publishing/multiple-apks.html)。不幸的是,清单文件在 APK 内是编译后的二进制形式。我们需要一个特殊的工具来修改那里的版本代码。见下文。

  10. \n
  11. 使用新版本代码修改清单并删除不必要的目录和文件后,重新压缩、签名并对齐较小的 APK(使用 Android SDK 中的 jarsigner 和 zipalign 工具)。

  12. \n
  13. 对您需要支持的所有其他架构重复此过程,创建版本代码略有不同(但版本名称相同)的较小 APK 文件。

  14. \n
\n\n

唯一突出的问题是修改二进制清单文件中的 \xe2\x80\x98versionCode\xe2\x80\x99 的方法。我很长一段时间都找不到解决方案,所以最后不得不坐下来编写自己的代码来做到这一点。作为起点,我采用了 Prasanta Paul 的 APKExtractor,http://code.google.com/p/apk-extractor/,用 Java 编写。我\xe2\x80\x99m 是老派,对 C++ 更熟悉,所以我用 C++ 编写的小实用程序“aminc”现在在 GitHub 上:

\n\n

https://github.com/gregko/aminc

\n\n

我发布了整个 Visual Studio 2012 解决方案,但整个程序是一个 .cpp 文件,可能可以在任何平台上编译。这里是一个示例 Windows .bat 文件,我用它来将名为 atVoice.apk 的“胖”apk 拆分为 4 个较小的文件,分别命名为 atVoice_armeabi.apk、atVoice_armeabi-v7a.apk、atVoice_x86.apk 和 atVoice_mips.apk。我实际上将这些文件提交到 Google Play(请参阅我的应用程序,网址为https://play.google.com/store/apps/details?id=com.hyperionics.avar),并且一切正常。另请参阅Jorge Su\xc3\xa1rez de Lis 的 Github 项目,他发布了适用于 Linux 的类似脚本。

\n\n
@echo off\nREM    My "fat" apk is named atVoice.apk. Change below to whatever or set from %1\nset apkfile=atVoice\ndel *.apk\n\nREM    My tools build atVoice-release.apk in bin project sub-dir. \nREM    Copy it here for splitting.\ncopy ..\\bin\\%apkfile%-release.apk %apkfile%.apk\n\nzip -d %apkfile%.apk META-INF/*\n\nREM ------------------- armeabi ------------------------\nunzip %apkfile%.apk AndroidManifest.xml\ncopy/y %apkfile%.apk %apkfile%.zip\nzip -d %apkfile%.zip lib/armeabi-v7a/* lib/x86/* lib/mips/*\naminc AndroidManifest.xml 1\nzip -f %apkfile%.zip\nren %apkfile%.zip %apkfile%_armeabi.apk\njarsigner -verbose -sigalg SHA1withRSA -digestalg SHA1 -keystore d:\\users\\greg\\.android\\Hyperionics.keystore -storepass MyPass %apkfile%_armeabi.apk MyKeyName\nzipalign 4 %apkfile%_armeabi.apk %apkfile%_armeabi-aligned.apk\ndel %apkfile%_armeabi.apk\nren %apkfile%_armeabi-aligned.apk %apkfile%_armeabi.apk\n\nREM ------------------- armeabi-v7a ---------------------\ncopy/y %apkfile%.apk %apkfile%.zip\nzip -d %apkfile%.zip lib/armeabi/* lib/x86/* lib/mips/*\naminc AndroidManifest.xml 1\nzip -f %apkfile%.zip\nren %apkfile%.zip %apkfile%_armeabi-v7a.apk\njarsigner -verbose -sigalg SHA1withRSA -digestalg SHA1 -keystore d:\\users\\greg\\.android\\Hyperionics.keystore -storepass MyPass %apkfile%_armeabi-v7a.apk MyKeyName\nzipalign 4 %apkfile%_armeabi-v7a.apk %apkfile%_armeabi-v7a-aligned.apk\ndel %apkfile%_armeabi-v7a.apk\nren %apkfile%_armeabi-v7a-aligned.apk %apkfile%_armeabi-v7a.apk\n\nREM ------------------- x86 ---------------------\ncopy/y %apkfile%.apk %apkfile%.zip\nzip -d %apkfile%.zip lib/armeabi/* lib/armeabi-v7a/* lib/mips/*\naminc AndroidManifest.xml 9\nzip -f %apkfile%.zip\nren %apkfile%.zip %apkfile%_x86.apk\njarsigner -verbose -sigalg SHA1withRSA -digestalg SHA1 -keystore d:\\users\\greg\\.android\\Hyperionics.keystore -storepass MyPass %apkfile%_x86.apk MyKeyName\nzipalign 4 %apkfile%_x86.apk %apkfile%_x86-aligned.apk\ndel %apkfile%_x86.apk\nren %apkfile%_x86-aligned.apk %apkfile%_x86.apk\n\nREM ------------------- MIPS ---------------------\ncopy/y %apkfile%.apk %apkfile%.zip\nzip -d %apkfile%.zip lib/armeabi/* lib/armeabi-v7a/* lib/x86/*\naminc AndroidManifest.xml 10\nzip -f %apkfile%.zip\nren %apkfile%.zip %apkfile%_mips.apk\njarsigner -verbose -sigalg SHA1withRSA -digestalg SHA1 -keystore d:\\users\\greg\\.android\\Hyperionics.keystore -storepass MyPass %apkfile%_mips.apk MyKeyName\nzipalign 4 %apkfile%_mips.apk %apkfile%_mips-aligned.apk\ndel %apkfile%_mips.apk\nren %apkfile%_mips-aligned.apk %apkfile%_mips.apk\n\n\ndel AndroidManifest.xml\ndel %apkfile%.apk\n:done\n
Run Code Online (Sandbox Code Playgroud)\n\n

格雷格

\n