Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>I don't have a gradle answer, but I think I now have a generic answer for any Android build tool. Here is my idea on how to create separate APK files for each supported processor architecture:</p> <ol> <li><p>Build your APK with any tools you use, containing all native code libraries you support, e.g. armeabi, armeabi-v7a, x86 and mips. I'll call it the 'original' APK file.</p></li> <li><p>Unzip your original APK into an empty folder, with any zip/unzip utility, best use command line tools, so that you could automate it with a shell script or batch file later.</p></li> <li><p>In the folder where original APK was uncompressed to, delete META-INF sub-folder (this contains the signatures, we'll need to re-sign the APK after all the modifications, so the original META-INF must be deleted).</p></li> <li><p>Change to lib sub-folder, and delete the sub-folders for any processor architectures you don't want in the new APK file. For example, leave only 'x86' sub-folder to make an APK for Intel Atom processors.</p></li> <li><p>Important: each APK for a different architecture, must have a different 'versionCode' number in AndroidManifest.xml, and the version code for e.g. armeabi-v7a must be slightly higher than the one for armeabi (read Google directions for creating multiple APKs here: <a href="http://developer.android.com/google/play/publishing/multiple-apks.html" rel="nofollow">http://developer.android.com/google/play/publishing/multiple-apks.html</a> ). Unfortunately, the manifest file is in a compiled binary form inside the APK. We need a special tool for modifying the versionCode there. See below.</p></li> <li><p>Once the manifest is modified with a new version code, and unnecessary directories and files deleted, re-zip, sign and align your smaller APK (use jarsigner and zipalign tools from Android SDK).</p></li> <li><p>Repeat the process for all other architectures you need to support, creating smaller APK files with slightly different version codes (but the same version name).</p></li> </ol> <p>The only outstanding issue is the way to modify ‘versionCode’ in binary manifest file. I could not find a solution for this for a long time, so finally had to sit down and crank my own code to do this. As the starting point, I took APKExtractor by Prasanta Paul, <a href="http://code.google.com/p/apk-extractor/" rel="nofollow">http://code.google.com/p/apk-extractor/</a>, written in Java. I’m the old school and still more comfortable with C++, so my little utility program 'aminc' written in C++ is now on GitHub at:</p> <p><a href="https://github.com/gregko/aminc" rel="nofollow">https://github.com/gregko/aminc</a></p> <p>I posted the entire Visual Studio 2012 solution, but the whole program is a single .cpp file which probably can be compiled on any platform. And here is a sample Windows .bat file I use to split my "fat" apk named atVoice.apk into 4 smaller files named atVoice_armeabi.apk, atVoice_armeabi-v7a.apk, atVoice_x86.apk and atVoice_mips.apk. I actually submit these files to Google Play (see my app at <a href="https://play.google.com/store/apps/details?id=com.hyperionics.avar" rel="nofollow">https://play.google.com/store/apps/details?id=com.hyperionics.avar</a>) and all works perfectly. Please also see <a href="https://github.com/gentakojima/apk-slice-by-arch" rel="nofollow">this Github project by Jorge Suárez de Lis</a>, who posts a similar script for Linux.</p> <pre><code>@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 here for 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 </code></pre> <p>Greg</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload