Get an APK’s manifest versionName and versionCode using Gradle

Jason Feinstein
2 min readAug 2, 2017

--

I recently needed to create a gradle task which will archive release APK files, and rather than relying on the defaultConfig values in build.gradle to know what to call the archive file I thought it would be better to directly inspect the APK itself for the correct values. This would avoid situations where the defaultConfig values may have been updated already for development.

aapt For The Win

The Android SDK’s build-tools come with a handy tool you can use to extract information from an APK: aapt. To get a bunch of information about the APK, just run it with dump badging /path/to/yourbuild.apk as the arguments.

> $ANDROID_HOME/build-tools/26.0.1/aapt dump badging app-release.apk

In what follows, you’ll see the first line of output has exactly what we need:

package: name='example.myapp' versionCode='123' versionName='1.0'...

But how do we create a gradle method which is capable of extracting this information?

The Gradle Code

We’re going to make a gradle function called getVersionInfo which takes one argument: a File object which points at an APK and returns a VersionInfo object we can use however we want.

Define VersionInfo

As you can see, the constructor accepts two parameters: apkFile and aaptOutput. The first parameter is only used to make toString() provide the location of the file. The second is the output we will receive from calling aapt.

The two regular expression Pattern objects look for the version name and code within that output, so we create matchers for each and execute them. The first group from each matcher is then used to determine the values of the versionName and versionCode fields.

Find aapt in the sdk build-tools directory

Before we can actually call aapt we need to know where it is!

Let’s create a simple helper method to find the exact location of the latest version of aapt to use in an exec call later:

The getAaptPath function simply drills-down into android.sdkDirectory to “build-tools”, then gets the last (latest) subdirectory, and appends “aapt” to it before returning the absolute path.

Put it together: Call aapt and returning VersionInfo

Now that we’re able to find aapt and have a way to represent version info using VersionInfo, we are finally ready to run aapt and construct what we’ve been trying to construct. Create getVersionInfo as a gradle function that accepts a File object pointing to our APK:

This function does two things:

  1. It creates a ByteArrayOutputStream and uses it to capture stdout from an exec call that runs a command using the location of aapt from getAaptPath(), passing it “dump”, “badging”, and the absolute location of the APK.
  2. It creates and returns a new instance of VersionInfo by passing the output from the exec call.

Wrapping Up

You can use the lessons learned from this post to create custom gradle tasks to perform actions based on built APKs which need to use their versionName and versionCode values. I’ve created a gist which puts all the code together. You can find it here.

Thanks for reading! If you found this post helpful, please tap the heart and recommend it to your friends.

--

--