Generating and displaying QR codes on Android Wear devices

Source code to accompany this article:

The introduction of the Android Wear platform created an new challenge for Android developers. In the Android ecosystem developers have long been considering devices with varying form factors, resolutions and screen densities. With Android wear there is now a new form factor unlike those that have come before it, the beautiful circular display that conforms to the traditional watch face and was launched with the Moto 360.

Android wear round

This round form factor throws many curve balls when it comes to UI design, especially with a device small enough to strap to your wrist. This article explains how to dynamically encode data into a square QR code that is optimized for display on either the square or round displays found on Android Wear devices.

If you are not well versed with UI design patterns for Android Wear devices, now is a good time to take a look at building shape aware layouts in the developer documentation.

First a couple of words about QR codes. If you have opened this article and read this far I am assuming you are aware of what QR codes are and and how they are used. What you may not know is that QR codes are resilient, if they are partially obscured or damaged readers can often still decode them successfully. This is due to inbuilt Reed-Solomon error correction. You may have seen customized QR codes that have embedded images and a kaleidoscope of colors and shapes for the data. These work by pushing the boundaries of the error correction and you should be aware that the more changes you make to the QR code data, the more difficult it is for a QR scanner to interpret the data. This article is about generating a QR code that conforms as close as possible to the QR specification to give QR scanners the best possible chance to decode the QR code being displayed on your wearable device.

Optimal QR Code Generation

Below is an example QR code with an overlay of the important elements that make up the data of a QR code.

QR Code structure. By Bobmath [CC BY-SA 3.0 (], via Wikimedia Commons

QR Code structure. By Bobmath CC BY-SA 3.0 (, via Wikimedia Commons

Your goal is to create a QR code that will provide the most reliable decoding in a range of lighting conditions using poor quality scanning equipment. Some of the characteristics of optimal QR codes are:

  • Colors: Black for data and white for background and quiet zone
  • Quiet Zone: The more blank area in the margin, or the quiet zone (see QR Code structure image above) as it is known, the better
  • Data: The shorter the string to encode the better
  • Display Size: Recommended minimum physical size of 1″ for the data plus space for the quiet zone
  • Resolution: Generate the image with at least 400 pixels wide and high so it can be displayed without scaling artifacts

The image below shows the ideal display of a QR code running on a square wearable device emulator. Once again I will stress the importance of the quiet zone, always leave a blank section around the data.

Android Wear (Square device)

The next image shows a QR code displayed on a round wearable device. When displaying a square QR code on a round canvas you have to compromise. This does not strictly follow the QR specification as the quiet zone around the image does not match the recommended size for the complete edge of the data. It does however allow the data area of the code to be larger and this offers the best chance for a successful decoding of the QR code. For those that don’t want to read the QR specification, the size of the quiet zone should ideally be 4 times the width of the data modules (seen as thin black data lines).

Android Wear (round device)

Now that you have seen what we are trying the achieve I will walk through generating the QR code as an image and how to display the images on each shape wearable.

Generating a QR Code

Generating a QR code from within any android app is quite simple thanks to the excellent library developed by Zxing.

If you are using Eclipse you can import the zxing jar library. If you are using Android Studio and grade, add the following to the build.gradle for your app module.

repositories {
 maven {
     url ""

dependencies {
 compile ''
 compile 'com.embarkmobile:zxing-android-minimal:1.2.1@aar'

Once you have successfully added the zxing library you can generate a bitmap image in memory using the function shown below. You should note that the EncodeHintType.MARGIN allows the quiet zone of the image to be set. Passing a value of 4 as this margin will set the quiet zone to the recommended 4 times the data module size, passing 0 will create an image without any quiet zone.

 * Allow the zxing engine use the default argument for the margin variable
 static public int MARGIN_AUTOMATIC = -1;

 * Set no margin to be added to the QR code by the zxing engine
 static public int MARGIN_NONE = 0;

 * Encode a string into a QR Code and return a bitmap image of the QR code
 * @param contentsToEncode String to be encoded, this will often be a URL, but could be any string
 * @param imageWidth number of pixels in width for the resultant image
 * @param imageHeight number of pixels in height for the resultant image
 * @param marginSize the EncodeHintType.MARGIN parameter into zxing engine
 * @param color data color for QR code
 * @param colorBack background color for QR code
 * @return bitmap containing QR code image
 * @throws WriterException zxing engine is unable to create QR code data
 * @throws IllegalStateException when executed on the UI thread
 static public Bitmap generateBitmap(@NonNull String contentsToEncode,
     int imageWidth, int imageHeight,
     int marginSize, int color, int colorBack)
         throws WriterException, IllegalStateException {

     if (Looper.myLooper() == Looper.getMainLooper()) {
         throw new IllegalStateException("Should not be invoked from the UI thread");

     Map<EncodeHintType, Object> hints = null;
     if (marginSize != MARGIN_AUTOMATIC) {
         hints = new EnumMap<>(EncodeHintType.class);
         // We want to generate with a custom margin size
         hints.put(EncodeHintType.MARGIN, marginSize);

     MultiFormatWriter writer = new MultiFormatWriter();
     BitMatrix result = writer.encode(contentsToEncode, BarcodeFormat.QR_CODE, imageWidth, imageHeight, hints);

     final int width = result.getWidth();
     final int height = result.getHeight();
     int[] pixels = new int[width * height];
     for (int y = 0; y < height; y++) {
         int offset = y * width;
         for (int x = 0; x < width; x++) {
             pixels[offset + x] = result.get(x, y) ? color : colorBack;

     Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
     bitmap.setPixels(pixels, 0, width, 0, 0, width, height);
     return bitmap;

Now call the generateBitmap() function and then set the bitmap generated into an ImageView.

Tip: Never generate the QR code on the UI thread, use an AsyncTask, or your android threading method of choice.

final int colorQR = Color.BLACK;
final int colorBackQR = Color.WHITE;
final int width = 400;
final int height = 400;

Bitmap bitmapQR = generateBitmap(mEncodeString, width, height,
                        MARGIN_AUTOMATIC, colorQR, colorBackQR);

Add a layout for displaying the QR code on round wearable devices.

<?xml version="1.0" encoding="utf-8"?>
 tools:context=".MainActivity" tools:deviceIds="wear_round">


         android:visibility="gone" />

The key items in the layout are the BoxInsetLayout and the app:layout_box="all" entry. These may be unfamiliar to developers new to Android Wear. BoxInsetLayout places its child view on round screens after applying the required window insets to be placed inside the viewable area of the device, while app:layout_box allows you to set which window insets will be applied.

You could use exactly the same BoxInsetLayout on a square device and it would work as the insets would all be 0. In the example here I have used a different layout simply to show you how to specify a different layout for each device type.

Here is the layout for the rectangular device with a regular relative layout as the base and the image filling the available layout.

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android=""
 xmlns:tools="" android:layout_width="match_parent"
 android:layout_height="match_parent" android:orientation="vertical"
 tools:context=".MainActivity" tools:deviceIds="wear_square">

     android:visibility="gone" />


Source Code for this article

Source code for this example can be cloned from the GitHub repository below. You will need an Android Studio development environment set up and the Android Wear SDK installed.


Android Wear Development

Android Wear layouts

Zxing GitHub home

QR Code reference

1 Comment

Filed under Android SDK, Android UI Patterns, Android Wear

Creating a Google Fit style circular animated view

Google’s health tracking platform, Google Fit, provides data visualization using a circular view to display feedback to users. This circular view is smoothly animated and presents a variety of data about the current status of the users fitness goals.

This article takes you through the steps required to build the chart shown in the clip below and add it into your Android App.


DecoView was designed as a fully configurable library for animating arc based charts. Continue reading this article to find out how to reproduce the Google Fit user experience in your app with DecoView. DecoView is open source and available on GitHub.

DecoView is subclassed from the Android View class. Just like other View subclasses, such as TextView and ImageView, it can be added and configured from your layout XML then controlled in your Activity code.

Faux Fit: DecoView sample project

The source code is available from the Faux Fit project on GitHub.

Step 1: Include the DecoView library in your project

DecoView is hosted on the repository. The first step is to add the required repository into your build.gradle file

repositories {
    // ...
    maven { url "" }

Next, add the gradle dependency for DecoView

dependencies {
    compile 'com.github.bmarrdev:android-DecoView-charting:v0.9.3'

Step 2: Add a DecoView to your XML layout

Open your Activity layout file and add a DecoView by inserting the following declaration.

    android:layout_height="match_parent" />

Note the use of the custom:dv_lineWidth attribute to set the default width of the arcs. You can always override this value for any of the data series you add later.

Step 3: Configure the DecoView by adding a data series

After adding a DecoView to your XML layout you will not see anything in your app unless you add one or more data series.

The first data series we are adding is going to be used as a background track to show the path where the other data series will follow as they are animated. To add this background arc add the following code to your Activity source file. Note how we set the color to a very light gray (hex code #FFE2E2E2).

DecoView decoView = (DecoView) findViewById(;

SeriesItem seriesItem = new SeriesItem.Builder(Color.parseColor("#FFE2E2E2"))
    .setRange(0, 50, 0)

int backIndex = decoView.addSeries(seriesItem);

Tip: While we are setting the color to be fully opaque here, DecoView supports alpha transparency in all functions that take a Color value

Next you need to add an actual data series in your Activity code. This may be used to visualize a data value such as the number of calories the user has burnt or number of minutes spent walking.

final SeriesItem seriesItem = new SeriesItem.Builder(Color.parseColor("#FFFF8800"))
        .setRange(0, 50, 0)

int series1Index = decoView.addSeries(seriesItem);

Step 4: Add a listener to monitor value changes

First you need to add a TextView to your XML layout. Then you can attach a new SeriesItem.SeriesItemListener() that will be called whenever the current position of the data series is changed. If you issue an event to move the series this callback will be called multiple times for the one event.

We will calculate the percentage the data series is filled and update our TextView with this percentage value.

final TextView textPercentage = (TextView) findViewById(;
seriesItem.addArcSeriesItemListener(new SeriesItem.SeriesItemListener() {
    public void onSeriesItemAnimationProgress(float percentComplete, float currentPosition) {
        float percentFilled = ((currentPosition - seriesItem.getMinValue()) / (seriesItem.getMaxValue() - seriesItem.getMinValue()));
        textPercentage.setText(String.format("%.0f%%", percentFilled * 100f));

    public void onSeriesItemDisplayProgress(float percentComplete) {


Tip: When implementing the DecoView progress listeners be aware that they will be called many times for each event. Avoid heavy processing in the listener to prevent jank, and avoid new allocations to prevent memory churn.

Step 5: Create timed events to animate the DecoView data series

We need to set the background track to be at the maximum value, this enables it to be drawn as a complete circle. We could have set this as the initial position for the track when it was constructed, however we want to see an animation filling the background track so we use an event to reveal the background track. While it is possible to fully customize this animation we will keep it simple and just set the minimum information required; that is the position to move the value and the index of the data series to execute the event.

decoView.addEvent(new DecoEvent.Builder(50)

It is possible to animate the DecoView at any time in response to a user action, such as pressing a button or using a swipe gesture. This is what we have just created with an event to be executed immediately.

It is also possible to delay events to happen at a future time. We will construct then event using setDelay(5000) to delay the animation of the main data series. We need to set the current value between the minimum (0) and maximum (50) values specified on creation of the data series.

Here is how to move the current position to 16.3f (out of 50) and delay the event to start after 5 seconds. After 10 seconds we will then move the position to 30.

decoView.addEvent(new DecoEvent.Builder(16.3f)

decoView.addEvent(new DecoEvent.Builder(30f)

Note: All time values in DecoView are specified in Milliseconds, 5000ms == 5 seconds

Step 6. Run your app to test your DecoView

You should now have the DecoView animating and looking similar to the image below when you run your app.

DecoView basic sample

Step 7. Add more data series, custom reveal animations and event listeners

To finish off building the Faux Fit sample you need to:

  • Add two more data series. This can be done using the same method used to create the existing series
  • Add custom reveal and hide effects
  • Create a animation loop by adding a listener to recreate all the events when the last one has completed

The code required to complete these final tasks can be viewed in the Faux Fit Activity found within the GitHub project. You should end up with an Activity something like the snapshot below.

Faux Fit DecoView Sample


Copyright 2015 Brent Marriott

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
See the License for the specific language governing permissions and
limitations under the License.


DecoView on GitHub:

Faux Fit sample on GitHub:


Filed under Android Libraries, Android Studio, Animation, Charting

Animating numerical change using Android Interpolators

Count von Count kneeling

I recently completed a financial charting tool with several user controlled variables, such as interest rate, term, loan amount. One client request was on the reset to default values there should be an animation while incrementing/decrementing rather than the value jumping instantly. I decided a non-linear animation algorithm would give the best visual result by adjusting the values quickly before decelerating as the target value approached. The graph below shows the required deceleration over time.

Decelerate graph

You may recognize this as a common interpolation pattern used in Android for animating movement of views. With this in mind I decided the most flexible design was to utilize the built-in Android Interpolator classes to control the rate of increment/decrement while using ValueAnimator. I have packaged the end result into an easy to use class, AnimateCounter.


AnimateCounter is a simple to use class to animate a numerical count on any TextView derived object. Full source code is available here.

The animation below shows an example of AnimateCounter being used to animate four TextViews from 0 to 100. Notice how the rate of numerical change for each view is influenced by the use of the different Interpolators.

Android Interpolation examples

Features of AnimateCounter

  • Ascending or descending value animation
  • Supports standard Android Interpolator classes
  • Supports custom Interpolator classes
  • Decimal and floating point number support
  • Numerical precision support
  • Optional callback on completion

AnimateCounter Usage

An AnimateCounter object is constructed using the builder design pattern. At a minimum a TextView is required for construction, then use the builder functions to optionally set initial and final values, precision, total duration and the interpolator required for animation. If no interpolator is provided the ValueAnimator default, AccelerateDecelerateInterpolator, is used.

Example 1: Count from 0 to 100 in two seconds using the default AccelerateDecelerateInterpolator interpolation.

AnimateCounter animateCounter = new AnimateCounter.Builder(textView)
        .setCount(0, 100)


Example 2: Count from 0.00 to 1.00 (floating point number with 2 decimal places) in 10 seconds using LinearInterpolator.

AnimateCounter animateCounter = new AnimateCounter.Builder(textView)
        .setCount(0f, 1f, 2)
        .setInterpolator(new LinearInterpolator())


Example 3: Perform an action after counting from 10 to 0 using the OvershootInterpolator.

AnimateCounter animateCounter = new AnimateCounter.Builder(textView)
        .setCount(10, 0)
        .setInterpolator(new OvershootInterpolator())

animateCounter.setAnimateCounterListener(new AnimateCounter.AnimateCounterListener() {
    public void onAnimateCounterEnd() {
        // Add action here!


Built-in Interpolators

Here are some of the Interpolators that you may like to use to animate the numerical change. These are all provided as part of the Android SDK:

Roll your own: Custom Interpolators

If none of the built in Interpolators fit your needs it is simple to create your own. The following class shows how to create an acceleration deceleration interpolation result. You could replace the mathematical formula in this class as required to produce your desired result.

import android.view.animation.Interpolator;
public class CustomAccelerateDecelerateInterpolator implements Interpolator {
  * Maps a value representing the elapsed fraction of an animation to a value that represents
  * the interpolated fraction. This interpolated value is then multiplied by the change in value
  * of an animation to derive the animated value at the current elapsed animation time.
  * @param input A value between 0 and 1.0 indicating our current point in the animation
  *              where 0 represents the start and 1.0 represents the end
  * @return The interpolation value. This value can be more than 1.0 for interpolators 
  * which overshoot their targets, or less than 0 for interpolators that undershoot their targets. 
  public float getInterpolation(float input) {
    return (float)(Math.cos((input + 1) * Math.PI) / 2.0f) + 0.5f;

Graphing tools can be used to visualize the interpolation algorithms and are the best place to start if you want to build our own custom interpolator. Here is an example.

Step 1. Find a mathematical equation for interpolation. The following equation shows a formula used in the Android accelerate/decelerate interpolator, where time is represented by t.

aceleration deceleration function

Step 2. Graph your equation. Visit or any graphing site and enter in the formula. When using it is required in this format:


The generated graph should confirm if the output from the formula is going to meet your needs. Using the above example the following graph is produced. Note the acceleration during the first half of the duration and the deceleration during the final half.

Accelerate decelerate graph

Step 3. Convert into Java. To use in your custom interpolator you need to convert your equation into Java code, for example:

(float)(Math.cos((input + 1) * Math.PI) / 2.0f) + 0.5f;

Source Code

Source for AnimateCounter available on GitHub


“Count von Count kneeling” by Source. Licensed under Fair use via Wikipedia –

1 Comment

Filed under Android SDK, Animation

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

Disable Android ART ahead-of-time compilation to optimize debug deployment

Android ART

With the introduction of the ART runtime came ahead-of-time (AOT) compilation to replace the Dalvik just-in-time (JIT) compilation. This is achieved on app installation when a one time process is executed to convert the APKs DEX files into a compiled app optimized for the device it is running on. Devices running the old Dalvik VM use JIT compilation that is performed at run time and only on frequently executed parts of apps. This change is designed to increase execution performance of apps on the new ART runtime.

For developers AOT compilation can cause frustration as every time an app is changed it has to be reinstalled on the target device. The AOT compilation process can take anything from a second to well over 10 seconds, the more code in an app the longer the device compilation process takes.

The good news is that it is possible to disable this AOT compilation for your debug builds, although this will cause your app to revert to being interpreted as it is executed. Disabling AOT compilation reduces the total time taken to deploy the app to the device and as a developer if you are modifying code and executing the app time after time, any increase in deployment speed is a welcome improvement. The tradeoff is a reduction in performance, although you are not likely to notice this performance hit for most types of applications. You should also consider that if you are writing an app that performs intensive computations then you may find saving a couple of seconds on installation for a compromised runtime performance is a counter-productive optimization.

Disabling ART ahead-of-time compilation

Disabling the AOT compilation is as simple as adding the application attribute android:vmSafeMode in your AndroidManifest.xml. Here is an example:



It is important to understand that this is not an attribute that we want to override on our release builds. It is possible to apply the attribute to debug builds only by creating a new …/app/src/debug/AndroidManifest.xml file. In this new manifest file you don’t need to replicate your existing manifest and can simply include the attribute you wish to add:

 <application android:vmSafeMode="true" />

Note: It is only possible to disable AOT compilation if you have a targetSdkVersion of 22+ and you’re running a device using the ART runtime.

Execution timing of ART ahead-of-time compilation

Before you make this change you should first identify that AOT is causing a significant delay to your deployment times. For small apps it is likely that you will save less than a second of installation time and this optimization is probably not required.

The device process that performs the ahead-of-time compilation is called dex2oat and outputs logging information that allows us to see the execution time elapsed. Filter your logcat for items containing dex2oat and you will see the execution time for the process.

Here is example output with AOT compilation enabled:

07-03 10:19:02.650  21326-21326/? I/dex2oat﹕ /system/bin/dex2oat --zip-fd=6 --zip-location=/data/app/com.testing.sample.myapp/base.apk --oat-fd=7 --oat-location=/data/dalvik-cache/arm/data@app@com.testing.sample.myapp-2@base.apk@classes.dex --instruction-set=arm --instruction-set-features=div --runtime-arg -Xms64m --runtime-arg -Xmx512m --swap-fd=8
07-03 10:19:03.989  21326-21326/? I/dex2oat﹕ dex2oat took 3.338s (threads: 4) arena alloc=107KB java alloc=2MB native alloc=4MB free=3MB

Output with AOT compilation disabled:

07-03 10:17:33.934  19031-19031/? I/dex2oat﹕ /system/bin/dex2oat --zip-fd=6 --zip-location=/data/app/com.testing.sample.myapp-1/base.apk --oat-fd=7 --oat-location=/data/dalvik-cache/arm/data@app@com.testing.sample.myapp-1@base.apk@classes.dex --instruction-set=arm --instruction-set-features=div --runtime-arg -Xms64m --runtime-arg -Xmx512m --compiler-filter=interpret-only --swap-fd=8
07-03 10:17:34.693  19031-19031/? I/dex2oat﹕ dex2oat took 1.258ms (threads: 4) arena alloc=0B java alloc=2MB native alloc=502KB free=7MB

Checking if manifest includes vmSafeMode

The logcat output of the dex2oat process also lets you check that the vmSafeMode attribute has been correctly applied. When vmSafeMode is set to true this process will be executed with the following argument:

/system/bin/dex2oat ... --compiler-filter=interpret-only

If you are seeing this option when installing your release APK then it is likely you have included vmSafeMode in your apps main AndroidManifest.apk rather than the debug only manifest.

Another method I found for determining if vmSafeMode is set for a given APK is to use the aapt.exe tool. You will find the aapt tool in the build-tools folder of the Android SDK, which differs in location based on your chosen OS. You will probably have several different versions installed and will find it in a location such as:


Execute the list command:

aapt list -a myapkfile.apk

This should produce output including:

Android manifest:
N: android=
  E: manifest (line=17)
    A: android:versionCode(0x0101021b)=(type 0x10)0x1
    A: android:versionName(0x0101021c)="1.0" (Raw: "1.0")
    A: package="com.testing.sample.myapp" (Raw: "com.testing.sample.myapp")
    A: platformBuildVersionCode=(type 0x10)0x16 (Raw: "22")
    A: platformBuildVersionName="5.1.1-1819727" (Raw: "5.1.1-1819727")
    E: uses-sdk (line=22)
      A: android:minSdkVersion(0x0101020c)=(type 0x10)0x15
      A: android:targetSdkVersion(0x01010270)=(type 0x10)0x16
    E: application (line=26)
      A: android:label(0x01010001)=@0x7f0b0001
      A: android:icon(0x01010002)=@0x7f030000
      A: android:debuggable(0x0101000f)=(type 0x12)0xffffffff
      A: android:vmSafeMode(0x010102b8)=(type 0x12)0xffffffff

Side effects of disabling AOT compilation

Without ahead-of-time compilation your app is going to run slower, it probably won’t be noticeable, but the runtime will have more work to do during execution. I have heard some developers have had major performance problems, such as execution of intensive processing experiencing a 10x increase in execution time. So keep an eye out for any performance problems.

So far I am happy to report that I have not run into any execution issues or unexpected behavior while testing this optimization.


Android ART:

Android Manifest vmSafeMode attribute:

1 Comment

Filed under Android SDK, Performance

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

Google Cloud Test Lab for Android

While it was not the most exciting announcement at Google I/O, one of the most useful services announced was that of the upcoming Cloud Test Lab. Cloud Test Lab allows Android developers to have their apps automatically tested on real physical devices. Sounds pretty cool eh? Well it gets better, on launch it will have 20+ Android devices and it’s free! Well some features will be free anyway. Here is how Google describe the service:

For comprehensive testing before releasing your app, Cloud Test Lab gives you access to physical devices so you can see what’s going on for your users in the real world. Plus, you can run all of your tests across all devices, all at the same time—giving you access to massively parallel testing, bringing you deep and scaled insight.

Cloud Test Lab

What you need to know

Google Cloud Test Lab


Current Status: Early Access sign up is now open

Estimated Release Date: September 2015

Device support: 20+ devices on launch

Cost: Free for basic functionality

Sign Up: Follow the links from your Google Play Developer Console account, as shown below.

Link to signup to Cloud Test Lab

Figure 1: Signup to Cloud Test Lab from the Developer Console

The Early Access Form is simply a few questions as shown below. You will need to have an app published though the Developer Console to apply.

Cloud Test Lab signup

Figure 2: Early Access Form for Cloud Test Lab

Cloud Test Lab functionality

The Google Cloud Test Lab is based on technology from Appurify, which Google acquired back in June 2014. Appurify have some pretty awesome technology, so this is a service that is packed with potential.

As this is a yet to launch service, details from Google are a bit vague at the moment. Here are a couple of important statements that give a bit more of a hint of what we can expect.

Every APK submitted to Play Store’s Alpha and Beta channels will be automatically scanned on more than 20 physical devices and get a free launch performance report. Developers who want to run customized testing can eventually purchase it through Cloud Test Lab.

My hope is that Google’s strategy won’t be to focus on making money directly from this venture but use the service to drive an improvement in the quality of apps. The service has the potential to make it faster and easier for developers to deal with the issues associated with the fragmentation of Android devices. I see this playing out with a subset of functionality on a subset of devices being provided for free. This will be fantastic for indie developers and small companies that do not make enough money from their apps to spend $1000’s on testing. This free functionality is likely to be the use of basic app crawlers to provide unscripted pseudo-random testing. It will probably be more advanced than letting monkey loose on the app and most likely built from the Appurify robot app crawler functionality.

A much larger set of functionality from a much larger pool of devices is not a cheap service to provide and will come at a cost for developers. This will target the top 1% of apps and provide a method for supplementing the apps existing internal testing. The sort of extra functionality likely to be included would be features such as:

  • Support of automated testing frameworks such as Espresso and UIAutomator
  • Full control of device environment, such as network connection, signal strength, memory, language and location
  • Comprehensive network traffic, memory, CPU, battery and FPS performance profiling
  • Comprehensive device library

Devices I want to be included

Now I don’t ask much, but I want the physical devices to be a range of devices that covers the following:

  • Devices from each manufacturer
  • Flagship devices for each of the past several years
  • Each released CPU architecture
  • Each Android API, including preview APIs
  • Combinations of Feature Sets
  • Android One devices
  • Various physical screen size
  • Various screen densities
  • Various screen resolutions
  • Range of languages
  • Languages with RTL layouts
  • Android Wear devices
  • Android TV devices
  • Android Auto devices

When do we find out more?

More details and a test run of the service is still a month or two away. Stay tuned to the Cloud Test Lab site for updates.

Leave a comment

Filed under Android SDK, Cloud Test Lab, Testing

Material Design Snackbar using the design support library

A Snackbar is a lightweight material design method for providing feedback to a user, while optionally providing an action to the user. They are displayed on the screen until a specified interval has passed, the user swipes to dismiss them, or when the user interacts with another part of the screen. Think of it as a modern take on the Android Toast.

This week at Google I/O 2015 the Android Design Support Library was released including a Snackbar implementation. Before now implementing and following the material guidelines for a Snackbar was left to the developer. A few third party libraries were released to make developers lives easier, but now official support for Snackbar has been introduced to make it easier than ever to add a Snackbar to your Android app.

Support for Snackbar pre-lollipop

While the Snackbar concept was introduced with the material design guidelines, the newly released Android Design Support Library works with devices right back to Android 2.1 (API 7). That is over 99% of active Android devices.

Material design specification for Snackbars

Many of the design rules for Snackbars are automatically enforced by the new support library. For example, if you provide lower case text for the action button it will automatically be displayed in upper case. However you still should brush up on the exact guidelines to know the best practices and what you can and can not do with a Snackbar. Take a look at the specification for full details.

A summary of the guidelines are:

  • Content: Keep text short
  • Icons: Do not add icons
  • Core functionality: Do not place core app functionality into a Snackbar
  • Multiple Actions: Use a dialog if you have multiple actions
  • Input: Snackbar does not block input, use a dialog for this
  • FAB: Don’t block the floating action button (FAB)
  • Consecutive: Only one can be displayed on the screen at any time
  • Single-line height: 48dp
  • Multi-line height: 80dp
  • Font: Roboto Regular 14sp
  • Action button: Roboto Medium 14sp, all-caps text
  • Default background fill: #323232 100%
  • Width on Tablets: Minimum 288dp, maximum 568dp

Adding a Snackbar to your app

Firstly you will need to add the Android Design Support Library dependency to your gradle build script:

compile ''

Next, you need to add a CoordinatorLayout to your xml layout. More details about what new features this new layout class bring are included later in this blog. Here is one that will position itself centered at the bottom of the screen:


In your AppCompatActivity class you need to configure the Snackbar object using the Builder design pattern. The most useful functions will be to create the Snackbar with make(), optionally set an action that the user can perform using setAction(), and finally to display the Snackbar to the user, show().

Snackbar will only work in Activities that are AppCompatActivity. If your activity extends a standard Activity or ActionBarActivity then you will need to either change your base class or use a third party implementation of a Snackbar.

Here is an example of a Snackbar that displays a message and allows an action to be executed by the user:


public class MainActivity extends AppCompatActivity...

final View.OnClickListener clickListener = new View.OnClickListener() {
    public void onClick(View v) {

final View coordinatorLayoutView = findViewById(;

    .make(coordinatorLayoutView, R.string.snackbar_text, Snackbar.LENGTH_LONG)
    .setAction(R.string.snackbar_action_undo, clickListener)

The result should be a Snackbar displayed on the device as shown in the image below. Note how the Snackbar in this image conforms to the specification. The text is kept short and the action text is all upper case. It is displayed on a tablet, so you will see rounded corners of 2dp and that a minimum width is enforced.

Snackbar displayed on tablet

Snackbar displayed on pre-lollipop tablet

Processing the Action button

The Snackbar action button should present an action related to the information being presented to the user. The most common type of actions are UNDO and RETRY.

Remember in the Material Design Snackbar specification that you can only show one action on a Snackbar, and that action must be short text composed entirely of uppercase text, no icons.

In the previous Snackbar example you can see that creating a View.OnClickListener() and adding it with an action is quite simple. The only work left is how you handle a click on the action button. Let’s take a look at an example, it is one of the most common use cases for a Snackbar. You have a list of items that are loaded from a database. With a swipe of the finger the user removes an item from the list and you display a Snackbar to confirm to the user that the item has been deleted and provide a action button to UNDO the delete and restore the item.

There may be a temptation to think that the easiest solution here is to remove the item from the list and wait until the Snackbar has completed being displayed and then do the actual delete from the database. If the user has hit the UNDO action button then add the item back into the list and don’t do the delete from the database.

The Snackbar implementation in Android does not encourage this type of implementation and in fact it doesn’t provide a callback to signal when the Snackbar view is no longer visible. The design pattern that Android wants you to follow for the example I have given is when the item is swiped from the display the item should be removed from the database immediately. You should keep the data needed to re-insert this item in the case that the user selects the UNDO action.

Positioning of the Snackbar

The Material Design specification of a Snackbar only stipulates that it is shown at the bottom of the screen. The example images in the specification show the Snackbar being horizontally centered, however the default position of the Snackbar in the Android design support library is the bottom left of the device if you do not use a CoordinatorLayout (see below). It is only possible to control the position of the Snackbar if you are using a CoordinatorLayout.

On smaller screen devices the Snackbar will take up the entire width of the screen, while on larger tablets sized screens the Snackbar will hit the maximum allowed width and not take up the entire width of the device.

Introducing CoordinatorLayout

When using many of the new elements introduced in the support library you will need to get to know the CoordinatorLayout.

CoordinatorLayout is a ViewGroup derived component that allows you to specify behaviors for child views to control how they interact with one another. If you recall one of the design rules for Snackbars was that they should not block the floating action button (FAB). With the newly released FloatingActionButton class blocking of the button is prevented by controlling the behaviors of the child views in the CoordinatorLayout.

By using a CoordinatorLayout you are also able to add padding or margins in order to move the Snackbar display position from the bottom of the screen.

Swipe to dismiss

Swipe to dismiss functionality is baked into the new Snackbar class when used in conjunction with a CoordinatorLayout. If you are finding that swiping on your Snackbar has no effect then check the type of View you are passing to the Snackbar.make() function. You don’t have to pass the CoordinatorLayout directly, passing a child view of a CoordinatorLayout is sufficient.

Duration of the Snackbar display

The Snackbar is not designed to be displayed indefinitely, but you are able to set the duration it is displayed before it is once again animated to hide it from the interface.

There are two standard lengths Snackbar.LENGTH_LONG, which is currently 2750 ms and Snackbar.LENGTH_SHORT which is currently 1500ms. It is possible to pass a custom display length in ms to the Snackbar.setDuration(int) function, and with the 22.2.1 release Snackbar.LENGTH_INDEFINITE is also a valid argument.

Adding bold text to your Snackbar message

You can add formatting such as bold to your Snackbar text using the Android Html class. The Html.fromHtml() function will generate a Spanned object that can be passed to the Snackbar.make() function:

Snackbar.make(view, Html.fromHtml("Add <b>bold</b> to Snackbar text"), Snackbar.LENGTH_LONG).show();

Adding multicolored text to your Snackbar message

You are able to add color combinations to the Snackbar text using the SpannableStringBuilder class. Using this class is also an alternative method for applying formatting such as bold to the Snackbar text.

Here is an example:

SpannableStringBuilder snackbarText = new SpannableStringBuilder();
snackbarText.append("Add ");
int boldStart = snackbarText.length();
snackbarText.append("bold color");
snackbarText.setSpan(new ForegroundColorSpan(0xFFFF0000), boldStart, snackbarText.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
snackbarText.setSpan(new StyleSpan(, boldStart, snackbarText.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
snackbarText.append(" to Snackbar text");

Snackbar.make(view, snackbarText, Snackbar.LENGTH_LONG).show();
Snackbar colored text

Snackbar colored text

Using the Design Support Library with ProGuard

In the initial release of the Design Support Library (22.2.0) you may hit issues with ProGuard. At this stage I would recommend you exclude all the design support library from the effects of ProGuard. This will cause some unnecessary bloat and once an update of the design support library is released you should revisit this issue and look for some official documentation. For now you can add the following to your ProGuard rules:

-keep class** { *; }
-keep interface** { *; }
-keep public class$* { *; }

Bigger is not always better

In the case of a Snackbar minimizing your text length is vital. Be succinct when writing text on the Snackbar, especially the action text. While the text must contain enough information that the user understands the meaning, it can’t be so verbose that layout problems are caused on small devices.

Ensure you test the layout of the text on a range of devices. While your text may look good on your shiny new 10″ tablet, spare a thought for those on the smallest devices your app is targeting.

If it is a possibility that you may localize your app in the future then think about the size of the text now to prevent more work down the track. Consider doing some pseudo-localization testing for your app, remembering that this text could possibly be twice as long after being translated from your apps native language. I have previously blogged about how to test localization using pseudo-localization on Android.


Snackbar specification:

Snackbar class:

CoordinatorLayout class:


Filed under Android SDK, Android Studio, Material Design