Simplifying Android app distribution with Beta by Crashlytics

Followup Post

I wrote a follow up to this post in which I describe a more straightforward version the approach detailed here.

 

 

 

Lately, I’ve been really enjoying using Beta by Crashlytics to distribute test builds of our application to different groups and users. It makes it easy to manage who has access to, and who has installed, a new test build, and our testers can easily access the history of builds from their mobile device to qa whichever version they need.

My only complaint with distributing our builds this way has been that it has never felt very streamlined or connected with my normal development cycle.

To improve this we’ve made use of several methods of simplifying/automating the build distribution process which in turn makes our usage of the tooling much more enjoyable.

Distributing with Gradle

When I first started using Beta by Crashlytics, we were using the following Gradle command to create a release build of our app and push it to Fabric.

// distribute via gradle command
gradle clean assembleRelease crashlyticsUploadDistributionRelease

This command was stored in a file so we could copy and paste it into the terminal window. This isn’t much work on it’s own, but before the build could actually be released to testers we then had to go into the Fabric console and add release notes to the new version and then finally assign testers and/or test groups to send the app to.

This workflow works, but quickly began to feel too clunky and we started looking for ways to improve this process.

Configuring distribution properties

As it turns out, you can configure distribution properties such as release notes and testers by defining the following properties to your BuildType or Flavors in your app’s build.gradle file.

// release notes
ext.betaDistributionReleaseNotes="Release Notes for this build."
// add testers
ext.betaDistributionEmails="BetaUser@yourcompany.com, BetaUser2@yourcompany.com"
// add group aliases
ext.betaDistributionGroupAliases="my-best-testers"

By defining these properties in our Gradle file, we removed the need to open the Fabric console and configure our app before it was released to testers.

That definitely simplified our process. At this point we just had to copy a line of Gradle tasks in to the terminal, hit ‘enter’, and our new app was delivered to testers. This was pretty good, but I started wondering if there might be other ways to simplify the process even further.

* For documentaion on distributing your build with Gradle, see here

IDE Plugin

When investigating other means of simplification, I came across this documentation on how to use the Fabric plugin for Android Studio. The plugin allows you to upload an apk, assign testers, and create release notes all from within Android Studio.

Click ‘Upload File’ to select an apk to distribute to testers
Select testers and groups to receive the beta application
Create your release notes before distributing the build

I really like the power this workflow gives me to control who receives the update. All the registered testers and managed groups are visible which removes the need to remember emails addresses or group aliases when modifying distribution properties in your build.gradle file.

The thing I don’t like about this approach is that it still feels like a lot of steps. This is especially true if I’m releasing an update to the same people with the same release notes as a previous build. I now have to navigate and select the new apk, track down the notes and reenter them again, and verify the selected testers. This is more work than I want to do when iterating over release candidates quickly throughout a certification process.

A more streamlined workflow

To achieve the level of simplicity that I was looking for (at the sacrifice of some power), I turned to custom Gradle tasks. I created a task that would execute the Gradle commands we used to copy and paste into the terminal.

def GROUP_NAME = "custom_group_name"
task buildReleaseCandidate() {
    group = GROUP_NAME
    dependsOn 'app:clean'
    finalizedBy 'app:assembleRelease'
}
task sendReleaseCandidateToCrashlytics() {
    group = GROUP_NAME
    dependsOn buildReleaseCandidate
    finalizedBy ':app:crashlyticsUploadDistributionRelease'
}

By having this task, we can execute these commands through the Gradle tool window without having to both with any copy and paste.

The new tasks as they appear in the Gradle tool window

When using this approach we still pull the testers/groups and the release notes from the properties defined in our build.gradle file, and we avoid the need to manually select our apk. For instances where we make a quick fix, bump the version number, and then want to re-distribute the build this workflow is great because none of the configuration needs to be repeated. We can just click on the Gradle task and it will be delivered to our testers.

Takeaways

Beta by Crashlytics is a great tool for managing and distributing test builds, but it can be a bit difficult to work with. To simplify your distribution process, its usage can be made much more enjoyable in several ways:

Leave a Reply