Build ABI Specific APKs
How to Build an APK Targetting One ABI
- PDF for offline use:
- Sample Code:
- Related Articles:
- Related Links:
Let us know how you feel about this.
This document will discuss how to build an APK that will target a single ABI using Xamarin.Android.
In some situations it may be advantageous for an application to have multiple APKs - each APK is signed with the same keystore and shares the same package name but it is compiled for a specific device or Android configuration. This is not the recommended approach - it is much simpler to have one APK that can support multiple devices and configurations. There are some situations where creating multiple APKs can be useful, such as:
- Reduce the size of the APK - Google Play imposes a 100MB size limit on APK files. Creating device specific APK's can reduce the size of the APK as you only need to supply a subset of assets and resources for the application.
- Support different CPU architectures - If your application has shared libraries for specific CPU's, you can distribute only the shared libraries for that CPU.
Multiple APKs can complicate distribution - a problem that is addressed by Google Play. Google Play will ensure that the correct APK is delivered to a device based on the application's version code and other metadata contained with AndroidManifest.XML. For specific details and restrictions on how Google Play supports multiple APKs for an application, consult Google's documentation on multiple APK support.
This guide will address how to script the building multiple APKs for a Xamarin.Android application, each APK targeting a specific ABI. It will cover the following topics:
- Create a unique version code for the APK.
- Create a temporary version of
AndroidManifest.XMLthat will be used for this APK.
- Build the application using the
AndroidManifest.XMLfrom the previous step.
- Prepare the APK for release by signing and zip-aligning it.
At the end of this guide is a walkthrough that will demonstrate how to script these steps using Rake.
Creating the Version Code for the APK
Google recommends a particular algorithm for the version code that uses a seven digit version code (please see the section Using a version code scheme in the Multiple APK support document). By expanding this version code scheme to eight digits, it is possible to include some ABI information into the version code that will ensure that Google Play will distribute the correct APK to a device. The following image and table explain this eight digit version code format:
(Left to Right)
|0||Red||An integer for the ABI:
|1 & 2||Orange||The minimum API level supported by the application.|
|3 & 4||Blue||The screen sizes supported:
|5, 6, & 7||Green||A unique number for the version code. This is set by the developer. It should increase for each public release of the application.|
Google Play will ensure that the correct APK is delivered to the device based on the
versionCode and APK configuration. The APK with the highest version code will be delivered to the device. As an example, an application could have three APKs with the following version codes:
- 11413456 - The ABI is
armeabi; targetting API level 14; small to large screens; with a version number of 456.
- 21423456 - The ABI is
armeabi-v7a; targetting API level 14; normal & large screens; with a version number of 456.
- 61423456 - The ABI is
x86; targetting API level 14; normal & large screens; with a version number of 456.
To continue on with this example, imagine that a bug was fixed which was specific to
armeabi-v7a. The app version increases to 457, and an new APK is built with the
android:versionCode set to 21423457. The versionCodes for the
x86 versions would remain the same.
Now imagine that the x86 version receives some updates or bug fixes that target a newer API (API level 19), making this version 500 of the app. The new
versionCode would change to 61923500 while the armeabi/armeabi-v7a remain unchanged. At this point in time, the version codes would be:
- 11413456 - The ABI is
armeabi; targetting API level 14; small to large screens; with a version name of 456.
- 21423457 - The ABI is
armeabi-v7a; targetting API level 14; normal & large screens; with a version name of 457.
- 61923500 - The ABI is
x86; targetting API level 19; normal & large screens; with a version name of 500.
Maintaining these version codes manually can be a significant burden on the developer. The process of calculating the correct
android:versionCode and then building the APK's should be automated. An example of how to do so will be covered in the walkthrough at the end of this document.
Create A Temporary AndroidManifest.XML
Although not strictly necessary, creating an temporary AndroidManifest.XML for each ABI can help prevent issues that might arise with information leaking from one APK to the other. For example, it is crucial that the
android:versionCode attribute is unique for each APK.
How this is done depends on the scripting system involved, but typically involves taking a copy of the Android manifest used during development, modifying it, and then using that modify manifest during the build process.
Compiling the APK
Building the APK per ABI is best accomplished by using either
msbuild as shown in the following sample command line:
/Library/Frameworks/Mono.framework/Commands/xbuild /t:Package /p:AndroidSupportedAbis=<TARGET_ABI> /p:IntermediateOutputPath=obj.<TARGET_ABI>/ /p:AndroidManifest=<PATH_TO_ANDROIDMANIFEST.XML> /p:OutputPath=bin.<TARGET_ABI> /p:Configuration=Release <CSPROJ FILE>
The following table explains each of the parameters in this command line:
|Command Line Parameter||Description|
||Creates an Android APK that is signed using the debug keystore|
||This the ABI to target. Must one of
||This is the directory that will hold the intermediate files that are created as a part of the build. If necessary, Xamarin.Android will create a directory named after the ABI, such as
||This property specifies the path to the
||This is the directory that will house the final APK. Xamarin.Android will create a directory named after the ABI, for example
||Perform a Release build of the APK. Debug builds may not be uploaded to Google Play.|
||This is the path to the
Sign and Zipalign The APK
It is necessary to sign the APK before it can be distributed via Google Play. This can be performed by using the
jarsigner application that is a part of the Java Developer's Kit. The following command line demonstrats how to use
jarsigner at the command line:
jarsigner -verbose -sigalg SHA1withRSA -digestalg SHA1 -keystore <PATH/TO/KEYSTORE> -storepass <PASSWORD> -signedjar <PATH/FOR/SIGNED_JAR> <PATH/FOR/JAR/TO/SIGN> <NAME_OF_KEY_IN_KEYSTORE>
All Xamarin.Android applications must be zip-aligned before they can be run on a device. This is the format of the command line to use:
zipalign -f -v 4 <SIGNED_APK_TO_ZIPALIGN> <PATH/TO/ZIP_ALIGNED.APK>
Automating APK Creation With Rake
The sample project OneABIPerAPK is a simple Android project that will demonstrate how to calculate an ABI specific version number and build three seperate APK's for each of the following ABI's:
The rakefile in the sample project performs each of the steps that were described in the previous sections :
- Create a
android:versionCodefor the APK.
- Write the
android:versionCodeto a custom
AndroidManifest.XMLfor that APK.
- Compile a release build of the Xamarin.Android project that will singularly target the ABI and using the
AndroidManifest.XMLthat was created in the previous step.
- Sign the APK with a production keystore.
- Zipalign the APK.
To build all of the APKs for the application, run the
build Rake task from the command line:
$ rake build ==> Building an APK for ABI armeabi with ./Properties/AndroidManifest.xml.armeabi, android:versionCode = 10814120. ==> Building an APK for ABI x86 with ./Properties/AndroidManifest.xml.x86, android:versionCode = 60814120. ==> Building an APK for ABI armeabi-v7a with ./Properties/AndroidManifest.xml.armeabi-v7a, android:versionCode = 20814120.
Once the rake task has completed, there will be three
bin folders with the file
xamarin.helloworld.apk. The next screenshot shows each of these folders with their contents:
The build process outlined in this guide may be implemented in one of many different build systems. Although we don't have a pre-written example, it should also be possible with Powershell / psake or Fake.
This guide provided some suggestions with how to create Android APK's that target a specify ABI. It also discussed one possible scheme for creating
android:versionCodes that will identify the CPU architecture that the APK is intended for. The walkthrough included a sample project that has it's build scripted using Rake.