Publishing an Android App from Android Studio

What

The documentation on how to publish an Android app to the Google Play store isn’t particularly informative.

This article explains all the tools and concepts involved and why.

Configuring your Application for Release

Removing Log Calls

There are two big reasons that Google demands that Log calls are removed from the release version of an app. The first is security, it is very easy to leak sensitive data via log calls. The second reason is performance, the user has no use for these calls.

Manually removing Log calls is silly and it is not how any good programmer operates. The default project configuration does not automatically remove Log calls but it can easily be done using Proguard.

The Proguard tool is commonly used to shrink, optimise and obfuscate Android apps (and many other Java programs). By default the app build.gradle is set to use Proguard on release build with a config that turns optimisation off. Even with optimisation off Proguard requires plenty the contents of the config to avoid breaking the app during its shrink step.

groovy
buildTypes {
    release {
        minifyEnabled false
        proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
    }
}
groovy
buildTypes {
    release {
        minifyEnabled false
        proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
    }
}

The default file can be found at \android-sdk\tools\proguard\proguard-android.txt.

In order to use Proguard to remove Log calls optimize needs to be enabled, this is done by changing the default file to proguard-android-optimize.txt. Again these default files are important because they have a lot of config that prevents Proguard from breaking the app.

Next step is to open the proguard-rules.pro file in the app directory and add the rules to remove Log calls. The []Proguard manual](https://www.guardsquare.com/en/proguard/manual/examples#logging) has the rules needed to do this as an example with some useful explanation.

plaintext
-assumenosideeffects class android.util.Log {
    public static boolean isLoggable(java.lang.String, int);
    public static int v(...);
    public static int i(...);
    public static int w(...);
    public static int d(...);
    public static int e(...);
}
plaintext
-assumenosideeffects class android.util.Log {
    public static boolean isLoggable(java.lang.String, int);
    public static int v(...);
    public static int i(...);
    public static int w(...);
    public static int d(...);
    public static int e(...);
}

This rule tells Proguard that these methods don’t have side effects. As a result Proguard will see this code as useless and remove it as part of optimisation. The only scenario that proguard would keep the Log call is if the return value is kept and used, however this should never by used.

debuggable versionName and versionCode

The documentation tells you to remove android:debuggable and set andoid:versionName and android:versionCode in the manifest. This is not helpful advice in modern Android apps.

The android:debuggable attribute is no longer set manually, it is automatically added by Android Studio when debugging. This means that the attribute should never be manually set in your manifest. It may need to be removed manually if you are working with old code.

The android:debuggable and set andoid:versionName attributes are now normally set in the build.gradle, which automatically sets it in the manifest, overwriting anything set there manually. So that too should not be manually set in the manifest because it will only lead to confusion.

Building and Signing a Release Version of your Application

Whenever an app is updated, the system will check to see if the app is signed by the same credentials. If the signatures don’t match, the update will be refused.

All builds that are run are signed, including debug builds. The debug builds use a default debug signature ~/.andoid/debug.keystore, which cannot be used for release.

Creating a signature, building and signing is done through a dialog, click on the Build menu in Android Studio and then click on Generate Signed APK…. The documentation on how to make a keys is not bad so read it for instructions on how to make a new key.

Important points:

I personally recommend storing the keystore outside of the project repository (especially if you are planning to open source) but keeping it backed up externally.

I imported a previously used keystore from Xamarin, the keystore password and the key password are the same. This is why Xamarin only asks for one password, but Android studio asks for 2.

Debugging The Release Build

The release build uses Proguard to shrink, optimise and obfuscate the code. Although unlikely to be an issue for small apps, this is a hazardous process and it may break the app.

Editing the debug build to include Proguard is silly, it’ll significantly slow down debug runs. Instead it makes sense to create a new build, specifically for debugging release builds:

plaintext
        release {
            minifyEnabled true
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
        debug_release {
            debuggable true
            minifyEnabled true
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
            signingConfig signingConfigs.debug
        }
plaintext
        release {
            minifyEnabled true
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
        debug_release {
            debuggable true
            minifyEnabled true
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
            signingConfig signingConfigs.debug
        }

The default debug build isn’t specified in the build.gradle but its main features are setting debuggable true and the dbug signing config. The debug signing config is also something that seems to be generated mysteriously automatically.

I only use my debug_release build for verifying that I didn’t do something catastrophically wrong. If you need to do some real debugging you may want to turn Proguard obfuscation off and fiddle with other features.

Whats Next

Next step requires a Google Developer account. Find the official documentation, follow the steps and upload the signed APK that was created.

Most of the rest of the process is mostly boring.

Tips: