Category Archives: Android NDK

Android NDK: A guide to deploying apps with native libraries

Libraries written in C++ and C have long been supported in Android through the Native Development Kit (NDK). Even if you haven’t directly built native code libraries, you may have included pre-built native libraries; they can be identified by the .so file extension. The main drivers for Android developers to include native libraries are:

  • Porting existing code to Android
  • Building a library of functionality
  • Increasing performance for intensive algorithms

Note: The process of building a native library is not covered in this article. Head to the Android NDK site for the tools and information you need to build native libraries for Android.

Android NDK

Most apps won’t benefit from native libraries and most apps should be developed exclusively using Java, which is executed in a virtual machine on the device using the Java ‘Write once, run anywhere’ philosophy. Including native libraries in your app results in you losing the write once, run anywhere benefit. Figure 1 shows a summary of the pros and cons of using native libraries:

Figure 1: Pros and cons of using a native library

Figure 1: Pros and cons of using a native library

Android Architectures and the Application Binary Interface (ABI)

Different Android devices use different CPU architectures, which in turn support different instruction sets. An ABI is different for each combination of CPU and instruction set. If you build with native code you need to compile that native code for each ABI that your app supports.

ABIs supported by Android

Android supports architectures from ARM, Intel and MIPS technologies, each in 32 bit and 64 bit flavors. In figure 2, below, you can see each ABI supported along with example devices.

Figure 1: Android ABI support

Figure 2: Android ABI support

Shared native library example

In this article I will use the SQLCipher project as an example use case for native libraries. SQLCipher is a great example of where using native libraries in Android is a necessity, here’s why:

  1. Performance benefits: SQLCipher has to decrypt/encrypt data, which requires very intensive processing
  2. Ease of reuse: The SQLCipher library was already developed in C/C++, using a native library makes is easier than rewriting and maintaining the library in different languages for different platforms

Performance testing

Building a shared native library can provide significant performance increases compared with implementing the same algorithm in Java. During some basic testing to compare some similar algorithms in native code compared to Java, I found the result ranged from double to a 20 times performance increase, however it should be noted these algorithms were heavy image manipulation processing. On less intensive use cases there will be little, if any, performance benefit.

Native library performance benefits

Figure 3: Native library performance benefits

APK size increase with native libraries

The table in Figure 4 shows the effect on the file size of an Android APK that include the .so libraries for SQLCipher. The universal APK in the table is built with libraries for all the tested ABIs.

Native library size increase table

Figure 4: APK size effect of including SQLCipher native library

For more information take a look at how to set your build.gradle file to build APKs that target different ABIs.

64 bit native libraries

When including native libraries you have to make a decision if you are going to ship with native libraries specifically targeting the 64 bit ABIs. Up until the start of 2015 this was an easy decision as 64 bit devices were only just hitting the market.

Note: It is not mandatory to build 64 bit libraries to support 64 bit Android devices. All 64 bit ABIs are backward compatible to support native libraries built for the equivalent 32 bit ABI. This applies to ARM as well as Intel and MIPS devices.

During 2015 sales of 64 bit Android devices could overtake those of 32 bit devices in some markets. If you provide native libraries specifically for 64 bit devices you should see a small performance increase with these new devices. Intel® have done some tests on Android performance using 64 bit compared to 32 bit and found performance is generally increased by 5-10%[1].

In summary, if you include 64 bit native libraries in you app:

  • You will still need to include 32 bit native libraries
  • You will not support any more devices than if you only include 32 bit libraries
  • You may see a small increase in performance for 64 bit devices[1]
  • You will increase the size of your APK (if building one APK with all native libraries)

Play Store Device support for different ABIs

While I have not been able to source official figures for sales figures of devices running each architecture, the breakdown is pretty clear through casual observation. ARM architectures dominate the Android device marketplace. There is a small percentage of x86 devices and virtually no MIPS devices.

When uploading an app to the Play Store feedback is shown with regards to the number of devices that are able to run your APK. Here is an example of the results:

Native Play Store device support

Figure 5: Play store reported supported devices

Notice in the table shown in Figure 5 that uploading an APK with armeabi native code will target 12 more devices than uploading an APK containing armeabi-v7a native code. The reason for this is that all devices running the armeabi-v7a are also able to execute the armeabi native code.

Multiple APK support on Google Play

It is possible to upload separate APKs to the play store for each ABI you are targeting. The best place to learn about this is by reading the Android documentation about Multiple APK support.
It should be noted that generally using multiple APKs to target different device configurations is discouraged. Here is what the official documentation has to say:

Note: You should generally use multiple APKs to support different device configurations only when your APK is too large (greater than 50MB) due to the alternative resources needed for different device configurations. Using a single APK to support different configurations is always the best practice, because it makes the path for application updates simple and clear for users (and also makes your life simpler by avoiding development and publishing complexity).

Verifying native libraries included in APK

It is possible to visually inspect the contents of any APK; remember that an APK is just a standard zip archive, so opening this archive you should find your native libraries in the folders for the ABIs you are targeting. For example, if you are building an APK that includes the SQLCipher native libraries for the x86 ABI, the file structure within the APK will look like:


Uploading multiple APKs to the Developer Console

In the Google Play developer console you can set your app to have multiple APKs that target different devices while all being part of the one application. This means that all download counts and reviews for the different APKs still apply to the one listing in the Google Play store.

There are some rules the must be followed in order to have ABI specific APKs active for the same app. The developer documentation describes some of these rules as:

  • All APKs you publish for the same application must have the same package name and be signed with the same certificate key.
  • Each APK must have a different version code, specified by the android:versionCode attribute.
  • Each APK must not exactly match the configuration support of another APK.

The image below shows the Google Play website for the Android Maps app. Note how the Size for the app is listed as Varies with device. This is as a result of uploading multiple APKs for the one application.

Example of Play Store variation per device

Figure 7: Play store entry for multiple APK app

Setting the versionCode

If you decide you need to deliver multiple APKs for the one app you will need to implement a version scheme for each APK. In a previous blog I have suggested extending a scheme suggested in the Android documentation, as shown below.

versionCode format

Figure 6: Android versionCode suggested format reference

Read more about this version scheme and how to automate the generation of different versionCodes for different target ABIs in this article:

Uploading your APKs

The Google Play Developer Console allows you to upload multiple APKs for the same application through the Advanced Mode in the APK management section.

  1. Go to the Developer Console
  2. Select the APK management menu
  3. Select Switch to Advanced Mode button
  4. Select Upload new APK button for each APK that targets different ABI

Your developer console should look similar to Figure 8, below, once you have uploaded multiple APKs.

Developer Console multiple native versions

Figure 8: Developer console uploading multiple APKs

You will notice in figure 8 the warning message:

Some devices are eligible to run multiple APKs. In such a scenario, the device will receive the APK with the higher version code.

You may think each version uploaded is targeting a different ABI Native platform, so why is this message being shown? Remember that some ABIs can support code targeting more than one different ABI. In this example the armeabi-v7a devices also are backwards compatible to support armeabi, but the reverse is not true.


The most pertinent points that must be considered when deciding to deploy your app with native libraries are:

  • Don’t use native libraries if you don’t need to
  • Consider which ABIs you need to target
  • Consider if specific 64 bit libraries to maximize performance are worthwhile
  • Avoid producing multiple APKs for one app unless APK size is an issue


Multiple APK support in Android:

Android apk-splits user-guide:

[1]How to Develop and Evaluate 64-bit Android Apps on Intel® x86 Platforms

1 Comment

Filed under Android NDK, Android Studio, Gradle

Android NDK: Version code scheme for publishing APKs per architecture

Distributing native libraries with your APK adds complexity to your build process and can bloat the size of your APK. You have to include a specific build of native libraries for every architecture you want to target, or to be more technically correct every ABI (Application Binary Interface) you are targeting. Different Android devices use different CPU’s architecture, which have support for different instruction sets. An ABI is different for each combination of CPU and the instruction set supported.

The recommended distribution method for your APK is to distribute one APK that contains all the static native libraries for all the ABIs being targeted. This article does not follow that path and discusses how to build, upload and manage separate APKs for your app. Each APK will include only the native libraries for a specific ABI. The following assumptions are made:

  • You are using Android Studio 1.2+ and using the Android gradle plugin build system
  • You are distributing your app through the Google Play store
  • You already have static native libraries (.so) built with the Android NDK
  • You are concerned about APK bloat caused by these native libraries

Universal APK or Multiple APKs

You need to make an educated and considered decision about if you distribute one APK that includes all native libraries or multiple APKs. The advantage of one universal APK is that it is simple to deploy and maintain your app, the disadvantage is that you potentially could have a substantial increase in APK size. I have previously described how to use SQLCipher in an Android app which discussed this tradeoff. Figure 1, below, shows the impact on size when shipping SQLCipher native libraries in a basic APK.

Figure 1: Size increase when including SQLCipher

Figure 1: Size increase when including SQLCipher

Play Store requirement for unique versionCode per ABI

The only way for a developer to distribute an app, with different APKs, to users on different devices is to have a unique versionCode and to ensure each APK is targeting different devices. The versionCode needs to be unique as it is possible that a users device is compatible with more than one APK, when this happens they will receive the version with the highest versionCode.

When I mention the version I am not referring to the version that is visible to the user, which is specified as the versionName, I am talking about the internal version which is a numerical versionCode that indicates an ascending order of releases. The snippet from a build.grade script below shows the default versionCode and versionName that Android Studio will apply to a new project.

defaultConfig {
 applicationId "com.hookedonplay.androidbycode.mynewapp"
 minSdkVersion 15
 targetSdkVersion 21
 versionCode 1
 versionName "1.0"

It is possible that you are maintaining existing apps which only specify the version in the AndroidManifest.xml. While this works well for static version information we need to use the new Android Gradle build system to be able to dynamically generate version information. Here is an example of version information added directly into the AndroidManifest.xml.

<manifest xmlns:android=""

Format for individual versionCodes per ABI

Each ABI needs to have an unique versionCode before it can be uploaded to the play store. We are going alter the build.gradle file to automatically generate a unique version number for each ABI. Assuming we want to build our app with versionCode 101, Our aim is to produce the following results:

ABI versionCode table

Figure 2: Example versionCode values for each ABI

The order of the ABI numbers are important as is the length of the 8 digit versionCode.

The order is based on way the Play store works with multiple APKs. Remember, if a users device is compatible with more than one APK for an application the device will receive the version with the highest version code. This is why an armeabi build will be given a prefix of 1 as this build will also be able to run a armeabi-v7a device (2) and in some cases a x86 device (8) due to a proprietary ARM translation layer called libhoudini.

The versionCode we are going to generate is 8 digits long to cater for multiple APKs that differ not only by target ABI, but also different Android SDK versions and screen sizes. An example of how to incorporate all these details into the 8 digit versionCode is shown in Figure 3 below. This is an extension of a numbering scheme suggested in the Android developer documentation where we prefix the number with the ABI id value that was listed in Figure 2.

versionCode format

Figure 3: Android versionCode suggested format reference

You should be aware that this is only a suggested method for generating version information. It is not mandatory and it can be tailored to me your needs. For example, if you know that you are not going to distribute different APKs based on Android SDK API level then you could drop those two digits from the version.

Automating unique versionCode generation

Before continuing and changing your versionCode naming convention you need to understand the following:

If you are distributing one APK containing all flavors of native libraries then you do not need to worry about implementing the following version scheme.

To automate the version process we need to customize the build process. The build.gradle script for your app is where you can configure the build to produce a separate APK for each ABI type and also set the versionCode to conform with the desired 8 digit format discussed earlier.

Here is an example of a complete build.gradle that will achieve this:

apply plugin: ''
 android {
    compileSdkVersion 22
    buildToolsVersion "22.0.1"
    defaultConfig {
        applicationId "com.hookedonplay.androidbycode.androiddatabaseencryption"
        minSdkVersion 15
        targetSdkVersion 22
        versionCode 101
        versionName "1.0"
    splits {
        abi {
            enable true
            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 =
          , 0) * 10000000 + android.defaultConfig.versionCode
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), ''
 dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    compile ''

Building separate APK files

The splits mechanism for the Android Gradle Plugin allows you to generate multiple files as shown by the example below. You can include only the ABI types you want to build and it is also possible to build an APK that includes all possible native libraries through the command universalApk true.

splits {
        abi {
            enable true
            include 'x86', 'armeabi', 'armeabi-v7a'
            universalApk true

Generate versionCode per APK

The section of the build script that sets the versionCode of each APK to a unique number is shown in the code snippet below. Note the project.ext.versionCodes which sets the first digit of the versionCode when multiplied by 10000000 we generate the 8 digit number we require. Finally the initial versionCode of the app, accessed with android.defaultConfig.versionCode, is added to complete the full numerical version for each APK.

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 =
          , 0) * 10000000 + android.defaultConfig.versionCode

Verify the versionCode included in each APK

The Android Asset Packaging Tool (aapt) is part of the Android build tools and is required to build APK files. You can also use it to verify the contents of the APK files you have generated.

You will find the aapt executable in your latest version of the build tools, for example ..\sdk\build-tools\22.0.1

Execute the following command on each of the APKs you have produced:

 aapt dump badging AndroidApp.apk

You will find a wealth of information about the APK but the following items in the output will be of most interest:

native-code: 'armeabi-v7a'

Below is a more detailed, but still trimmed sample output from the aapt badging request:

package: name='com.hookedonplay.androidbycode.androiddatabaseencryption' 
versionCode='2000101' versionName='1.0' platformBuildVersionName='5.0.1-1624448'
application-label:'Android Database Encryption'
application: label='Android Database Encryption' icon='res/mipmap-mdpi-v4/ic_launcher.png'
uses-feature: name='android.hardware.touchscreen'
uses-implied-feature: name='android.hardware.touchscreen' reason='default feature for all apps'
supports-screens: 'small' 'normal' 'large' 'xlarge'
supports-any-density: 'true'
locales: '--_--' 'ca' 'da' 'fa' 'ja' 'nb' 'de' 'af' 'bg' 'th' 'fi' 'hi' 'vi' 'sk' 'uk' 'el' 'nl' 'pl' 'sl' 'tl' 'am' 'in' 'ko' 'ro' 'ar' 'fr' 'hr' 'sr' 'tr' 'cs' 'es' 'it' 'lt' 'pt' 'hu' 'ru' 'zu' 'lv' 'sv' 'iw' 'sw' 'fr-CA' 'lo-LA' 'en-GB' 'bn-BD' 'et-EE' 'ka-GE' 'ky-KG' 'km-KH' 'zh-HK' 'si-LK' 'mk-MK' 'ur-PK' 'hy-AM' 'my-MM' 'zh-CN' 'ta-IN' 'te-IN' 'ml-IN' 'en-IN' 'kn-IN' 'mr-IN' 'mn-MN' 'ne-NP' 'gl-ES' 'eu-ES' 'is-IS' 'es-US' 'pt-PT' 'zh-TW' 'ms-MY' 'kk-KZ' 'uz-UZ'
densities: '160' '240' '320' '480' '640'
native-code: 'armeabi-v7a'

This same dump can be also used to verify other attributes of your APK, such as the build SDK version, locales and supported screen densities.

You will also be able to verify the targeted ABI and versionCode once you upload to the Play Store via the developer console.

Distribution of multiple APKs via alternative app stores

This article has assumed that you are distributing your app through the Google Play Store. It may be possible that you are using multiple distribution methods, such as promoting your app on the Amazon Appstore. According to the documentation the same version methodology will work for the multiple APK support within the Amazon Appstore. There are also a number of smaller app marketplaces that may automatically add your app. Each of these app store may or may not handle multiple APKs correctly which may result in some users downloading an APK that is incompatible with their device.


Multiple APK support in Android

Android apk-splits user-guide

Amazon Device Targeting


Filed under Android NDK, Android Studio, Automation, Google Play, Gradle

Android Database Encryption using SQLCipher

Clone or fork this project from GitHub:

Data security is a hot topic that will only intensify under the weight of the petabytes of information accumulating in data centres around the world. Securing your users data is no longer a bolt on afterthought, but a non-negotiable in any system that deals with sensitive data. It is not just the data centres that hold this sensitive data, those ever increasingly powerful computers we carry in our pockets or strap to our wrists are a treasure trove of personal information that others would love to get their hands on. As an app developer it is your responsibility to do everything in your power to protect the users of your product. In doing so you are not only protecting those users but the reputation of your company. Wherever possible you must avoid storing sensitive data within your app. This article discusses the pros and cons of encrypting your Android database with SQLCipher for the cases where you have no choice other than to store sensitive data.


SQLCipher is often the go to choice for Android apps for the following reasons:

  • Strong encryption (256-bit AES)
  • Mature technology
  • Maintained and supported by its developers and the open source community
  • Supports virtually the same API as standard Android database functions

Unfortunately there is no such thing as a free lunch, it is important to understand not only the benefits but also the consequences of switching to an encrypted database. Here are a few to consider:

  • APK size will be increased substantially
  • Database performance will decrease
  • Secure management of the encryption key (or password) is required
  • Use of strong encryption has legal considerations in some jurisdictions

APK Size

Firstly there is APK size to consider. Using the sample project that accompanies this article as an example, a release build (without proguard enabled) of the APK expands from 1MB to over 9MB. This equates to 2-3MB for each architecture you want to support.

It is possible to build different APK files to support each architecture. When including SQLCipher this can lead to a significant reduction in the size of your app. For example, it reduces the size of the sample app included with this project by more than half if you build a separate app for each of armeabi, armeabi-v7a and x86. You can read more about distributing your app with multiple APK’s.


Any layer of encryption is going to come with a performance hit. SQLCipher is no different. If a 10-20% performance hit is going to impact the user experience of your app then you may want to look at different options. For most purposes the database in your app in unlikely to be big enough for this to cause an issue.

Key Management

To encrypt and decrypt you need a key. SQLCipher does some of the hard work for you, encrypting a password into a key using PBKDF2. This password however still needs to be managed and should not be stored within your source code.

Legal issues

Apps that use strong cryptography, such as the algorithms used in SQLCipher, have obligations for compliance to the strict United States export requirements. You should not add any encryption without understanding what these export requirements are and what your obligations are. This will not be discussed further in the article, you should seek your own clarification.

Before you can publish your app on the Google Play Store you must acknowledge that your software application may be subject to United States export laws regardless of your location or nationality and you certify that your app is authorized for export under these laws.

Partial database encryption

SQLCipher is applied to a complete database. It does not support encryption of specific columns in your database.

SECTION 2: Add SQLCipher library to your app

Update August 2015: Commonsguy has released an unofficial GitHub repository that packages the SQLCipher for Android distribution in a standard Android library module. You can use this as an alternative to following the steps in this section to unpack the official version from Zetetic.

If, after careful consideration, you have decided that you just have to store that sensitive data, this is how to use SQLCipher to do it. These instructions are for Android Studio 1.0+, if you are an Eclipse user you should visit the SQLCipher project home for details about how to add the SQLCipher library to your Eclipse project. When developing in Android Studio your first port of call for including libraries should be through the Maven repository via your Gradle script. Unfortunately at this time SQLCipher is not available officially through Maven so we will have to get the libraries and import them manually.

Step 1: Download the SQLCipher for Android binaries from here:

What are these libraries? SQLCipher is written in C code. These libraries (.so) have been build using the Android NDK, which allows native languages such as C and C++ to be compiled and used by your Android app. Unlike the Java code in your app which is compiled to bytecode to run in Androids VM (Dalvik or ART), this library contains native code that is architecture dependent. This means there is a library for will support each possible architecture that the target device may use.

Step 2: In your app\src\main directory create two new child folders named jniLibs and assets.

Step 3: From the binaries you downloaded in step 1, copy the contents of the assets folder into your newly created assets folder and copy the sub-folders from the libs folder into your newly created jniLibs folder. Be sure that you have named the folder correctly and copied all the files as well as the sub-folder for each architecture type you wish to support.

Step 4: From the binaries archive you downloaded in step 1 you now need to copy the jar files from the libs folder into app/libs. In addition to these jars you also need to copy guava-r09.jar and commons-codec.jar into this folder. Currently these are not included in the binaries archive above. If you download the sample project attached to this article you can find the jar files there.

Step 5: To ensure your project can find the libraries add an include in your gradle script for your app module, this should go in the dependencies section. (This may already be present in your gradle script)

compile fileTree(dir: 'libs', include: ['*.jar'])

SECTION 3: Replacing your Sqlite database with SQLCipher database

Now the SQLCipher library is added for your project you need to do a clean and rebuild. Follow the steps below to switch your sqlite database across to a SQLCipher database. This will work even if your sqlite database is within a content provider.

Step 1: Replace imports that reference standard Android sqlite database classes with SQLCipher classes. To do this look for any import from the standard database classes, for example:

import android.database.Cursor; 
import android.database.DatabaseUtils; 
import android.database.SQLException; 
import android.database.sqlite.SQLiteDatabase;

Replace these with calls to the equivalent SQLCipher classes:

import net.sqlcipher.Cursor; 
import net.sqlcipher.DatabaseUtils; 
import net.sqlcipher.SQLException; 
import net.sqlcipher.database.SQLiteDatabase;

Step 2: Replace calls to open or create the database passing the password as an argument. For example:


Needs to be replaced with:


Step 3: Add the initialization call to SQLCipher. This must be called before any call the SQLCipher classes and you should ensure that this is only called once.

import net.sqlcipher.database.SQLiteDatabase;

Step 4: That’s it, build your app and run!

Remember to head over to GitHub to clone or fork the sample project:

SECTION 4: Distributing an App with native libraries

Since this article was initially release I have described in detail the considerations of distributing apps that include native libraries, such as those required by SQLCipher.

To learn more I recommend reviewing these articles:

Android NDK: A guide to deploying apps with native libraries

Android NDK: Version code scheme for publishing APKs per architecture



Filed under Android NDK, Android SDK, Database, Security