使用旧的ANT或新的Gradle构建流程,是否有一种简单的方法可以为不同的处理器架构为Android构建单独的APK文件?我这样做的方法是构建一个包含所有支持的本机库的“胖”APK,然后将它们拆分为单独的APK explained here。但是,似乎应该有一种更直接的方法来做到这一点......
答案 0 :(得分:5)
我决定在此处重新发布我的answer from elsewhere,以便所有这些都在一个页面上以便于访问。如果这违反SO政策,请告诉我并从此处删除此帖。
以下是关于如何为每个支持的处理器架构创建单独的APK文件的想法:
使用您使用的任何工具构建一个“胖”APK,其中包含您支持的所有本机代码库,例如armeabi,armeabi-v7a,x86和mips。我将其称为“原始”APK文件。
将原始APK解压缩到一个空文件夹中,使用任何zip / unzip实用程序,最好使用命令行工具,以便以后可以使用shell脚本或批处理文件自动执行。实际上,正如我在下面发布的示例批处理脚本所示,我只是使用命令行zip / unzip工具直接操作APK,而不是完全解压缩,但效果是一样的。
在原始APK未压缩到的文件夹中(或在原始.apk / .zip中),删除META-INF子文件夹(这包含签名,我们需要重新签名APK在所有修改之后,必须删除原始的META-INF。
更改为lib子文件夹,并删除新APK文件中不需要的任何处理器体系结构的子文件夹。例如,只留下'x86'子文件夹为Intel Atom处理器制作APK。
重要提示:每个APK适用于不同的架构,必须在AndroidManifest.xml中具有不同的“versionCode”编号,以及例如armeabi-v7a必须略高于armeabi的版本(请阅读Google在此处创建多个APK的说明:http://developer.android.com/google/play/publishing/multiple-apks.html)。不幸的是,清单文件在APK中以编译的二进制形式存在。我们需要一个特殊的工具来修改那里的versionCode。见下文。
使用新版本代码修改清单后,删除不必要的目录和文件,重新压缩,签名并对齐较小的APK(使用Android SDK中的jarsigner和zipalign工具)。
< / LI>对您需要支持的所有其他体系结构重复此过程,创建版本较小的APK文件(但版本名称略有不同)。
唯一突出的问题是在二进制清单文件中修改'versionCode'的方法。很长一段时间我找不到解决方案,所以最后不得不坐下来动摇我自己的代码来做到这一点。作为起点,我采用了用Java编写的Prasanta Paul http://code.google.com/p/apk-extractor/的APKExtractor。我是旧学校,对C ++更加满意,所以用C ++编写的小实用程序'aminc'现在在GitHub上:
https://github.com/gregko/aminc
我在那里发布了整个Visual Studio 2012解决方案,但整个程序是一个.cpp文件,可能可以在任何平台上编译。这是一个示例Windows批处理脚本文件,用于将名为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的应用程序)并且完美无误:
@echo off
REM My "fat" apk is named atVoice.apk. Change below to whatever or set from %1
set apkfile=atVoice
del *.apk
REM My tools build atVoice-release.apk in bin project sub-dir.
REM Copy it herefor splitting.
copy ..\bin\%apkfile%-release.apk %apkfile%.apk
zip -d %apkfile%.apk META-INF/*
REM ------------------- armeabi ------------------------
unzip %apkfile%.apk AndroidManifest.xml
copy/y %apkfile%.apk %apkfile%.zip
zip -d %apkfile%.zip lib/armeabi-v7a/* lib/x86/* lib/mips/*
aminc AndroidManifest.xml 1
zip -f %apkfile%.zip
ren %apkfile%.zip %apkfile%_armeabi.apk
jarsigner -verbose -sigalg SHA1withRSA -digestalg SHA1 -keystore d:\users\greg\.android\Hyperionics.keystore -storepass MyPass %apkfile%_armeabi.apk MyKeyName
zipalign 4 %apkfile%_armeabi.apk %apkfile%_armeabi-aligned.apk
del %apkfile%_armeabi.apk
ren %apkfile%_armeabi-aligned.apk %apkfile%_armeabi.apk
REM ------------------- armeabi-v7a ---------------------
copy/y %apkfile%.apk %apkfile%.zip
zip -d %apkfile%.zip lib/armeabi/* lib/x86/* lib/mips/*
aminc AndroidManifest.xml 1
zip -f %apkfile%.zip
ren %apkfile%.zip %apkfile%_armeabi-v7a.apk
jarsigner -verbose -sigalg SHA1withRSA -digestalg SHA1 -keystore d:\users\greg\.android\Hyperionics.keystore -storepass MyPass %apkfile%_armeabi-v7a.apk MyKeyName
zipalign 4 %apkfile%_armeabi-v7a.apk %apkfile%_armeabi-v7a-aligned.apk
del %apkfile%_armeabi-v7a.apk
ren %apkfile%_armeabi-v7a-aligned.apk %apkfile%_armeabi-v7a.apk
REM ------------------- x86 ---------------------
copy/y %apkfile%.apk %apkfile%.zip
zip -d %apkfile%.zip lib/armeabi/* lib/armeabi-v7a/* lib/mips/*
aminc AndroidManifest.xml 9
zip -f %apkfile%.zip
ren %apkfile%.zip %apkfile%_x86.apk
jarsigner -verbose -sigalg SHA1withRSA -digestalg SHA1 -keystore d:\users\greg\.android\Hyperionics.keystore -storepass MyPass %apkfile%_x86.apk MyKeyName
zipalign 4 %apkfile%_x86.apk %apkfile%_x86-aligned.apk
del %apkfile%_x86.apk
ren %apkfile%_x86-aligned.apk %apkfile%_x86.apk
REM ------------------- MIPS ---------------------
copy/y %apkfile%.apk %apkfile%.zip
zip -d %apkfile%.zip lib/armeabi/* lib/armeabi-v7a/* lib/x86/*
aminc AndroidManifest.xml 10
zip -f %apkfile%.zip
ren %apkfile%.zip %apkfile%_mips.apk
jarsigner -verbose -sigalg SHA1withRSA -digestalg SHA1 -keystore d:\users\greg\.android\Hyperionics.keystore -storepass MyPass %apkfile%_mips.apk MyKeyName
zipalign 4 %apkfile%_mips.apk %apkfile%_mips-aligned.apk
del %apkfile%_mips.apk
ren %apkfile%_mips-aligned.apk %apkfile%_mips.apk
del AndroidManifest.xml
del %apkfile%.apk
:done
我在Google Play开发者控制台上收到了一些错误报告,指出无法找到本机方法。最有可能的原因是用户安装了错误的APK,例如ARM设备上的Intel或MIPS APK。为我的应用添加了额外的代码,针对Build.CPU_ABI检查VersionCode编号,然后在出现不匹配的情况下显示错误消息,要求用户从Google Play(或我自己的网站,我发布“胖”APK)重新安装在这种情况下。
格雷格
答案 1 :(得分:4)
在本文Android NDK: Version code scheme for publishing APKs per architecture中,我找到了解决此问题的一个很好的解决方案。它包括添加以下代码
splits {
abi {
enable true
reset()
include 'x86', 'armeabi', 'armeabi-v7a'
universalApk true
}
}
project.ext.versionCodes = ['armeabi': 1, 'armeabi-v7a': 2, 'arm64-v8a': 3, 'mips': 5, 'mips64': 6, 'x86': 8, 'x86_64': 9]
android.applicationVariants.all { variant ->
variant.outputs.each { output ->
output.versionCodeOverride =
project.ext.versionCodes.get(output.getFilter(
com.android.build.OutputFile.ABI), 0) * 10000000 + android.defaultConfig.versionCode
}
}
到build.gradle脚本的android{...}
部分。如果你想了解细节,我强烈建议阅读那篇文章,这真的值得一读。
答案 2 :(得分:-1)
从Android NDK build with ANT script开始,变化很小:
<target name="-pre-build">
<exec executable="${ndk.dir}/ndk-build" failonerror="true"/>
<arg value="APP_ABI=${abi}"/>
</target>
并使用批处理文件来运行循环(我使用简单的sed
脚本; sed可在%NDK_ROOT%\prebuilt\windows\bin\
和所有其他平台上使用):
sed -i -e "s/versionCode=\"\([0-9]*\).]\"/versionCode=\"\11\"/" AndroidManifest.xml
ant -Dsdk.dir=%SDK_ROOT% -Dndk.dir=%NDK_ROOT% -Dabi=armeabi release
ren %apkfile%.apk %apkfile%_armeabi.apk
sed -i -e "s/versionCode=\"\([0-9]*\).\"/versionCode=\"\12\"/" AndroidManifest.xml
ant -Dsdk.dir=%SDK_ROOT% -Dndk.dir=%NDK_ROOT% -Dabi=mips release
ren %apkfile%.apk %apkfile%_mips.apk
sed -i -e "s/versionCode=\"\([0-9]*\).\"/versionCode=\"\13\"/" AndroidManifest.xml
ant -Dsdk.dir=%SDK_ROOT% -Dndk.dir=%NDK_ROOT% -Dabi=armeabi-v7a release
ren %apkfile%.apk %apkfile%_armeabi-v7a.apk
sed -i -e "s/versionCode=\"\([0-9]*\).\"/versionCode=\"\14\"/" AndroidManifest.xml
ant -Dsdk.dir=%SDK_ROOT% -Dndk.dir=%NDK_ROOT% -Dabi=x86 release
ren %apkfile%.apk %apkfile%_x86.apk
这假设清单文件中的 android.verisonCode 作为最后一位数为零,例如android:versionCode="40260"
。
请注意,技术上没有理由更改 armeabi 和 mips 变体的versionCode,但保持 armeabi&lt; armeabi-v7a&lt; 86 强>
更新感谢Ashwin S Ashok提出了更好的编号方案:VERSION+10000*CPU
。