Use MSBuild to Define Advanced Android VersionCode

Dean Ellis

With the introduction of Xamarin.Android v7.2, two new MSBuild properties were also introduced in order to make maintaining Android VersionCode for Android apps even easier:

  • AndroidVersionCodePattern
  • AndroidVersionCodeProperties

Advanced Android VersionCode

Typically, to change the version number on an Android application you need to edit the AndroidManifest.xml file and update the android:versionCode. Alternatively, you could implement your own system for generating the code and updating the XML file. With these two properties in place, you will be able to define the versionCode within your MSBuild project. All this is built right into the build system.

AndroidVersionCodePattern

This property allows you to define the pattern desired for your versionCode and inputs in a similar way to string.Format work. You provide a number of {token} values which are replaced at build time. Out of the box we support of a number of default {tokens}:

  • ABI – Inserts the targeted ABI for the app
    1. armeabi
    2. armeabi-v7a
    3. x86
    4. arm64-v8a
    5. x86_64
  • MinSDK – Inserts the minimum supported Sdk value from the AndroidManifest.xml or 11 if none is defined.
  • VersionCode – Uses the version code directly from Properties\AndroidManifest.xml.

By default the value of $(AndroidVersionCodePattern) will be set to {abi}{versionCode:D6}. So as an example, if you are splitting your APK’s by ABI and your versionCode in the AndroidManifest.xml is currently 1, the following should result:

  • 2000001 for armeabi-v7a
  • 4000001 for armeabi-v8a

This can be broken down like so:

2 000001
{abi} {versionCode:D8}

 

Notice the {token} supports the same zero padding definition that string.Format supports. In this example, the D6 means “left pad the result so that it is 6 digits long”. Another example might be {abi}{minSDK:D2}{versionCode:D4}. If the minSdk was API-9 and your versionCode in the AndroidManifest.xml is currently 21, you will see the following result.

  • 2090021 for armeabi-v7a
  • 4090021 for armeabi-v8a

This can be broken down like so:

2 09 0021
{abi} {minSDK:D2} {versionCode:D4}

AndroidVersionCodeProperties

Support for allowing you to define your own {token} has also been added. This is done via the $(AndroidVersionCodeProperties). This is a comma-separated token=value pair string which defines the new {token} and its value. The value can be hard-coded for any one of the many MSBuild properties which are available.

For example: screen=23;target=$(_SupportedApiLevel). This defines two new tokens {screen} and {target}. One of which is derived from a Xamarin.Android MSBuild property. With this in mind, you can now define a $(AndroidVersionCodePattern) of:

{abi}{minSDK:D2}{screen:D2}{target:D2}{versionCode:D4}

Which will make use of your custom {token} values in the final APK versionCode

Getting VersionCode from your Assembly

Information for the AndroidManifest.xml can be useful if your project is setup to auto increment your assembly version for each build.

Use the MSBuild Task GetAssemblyIdentity to retrieve the compiled assembly’s version information. Then use some MSBuild:Foo to split that into a usable format. Finally, create a set of {token}={value} items in the $(AndroidVersionCodeProperties) property.

<Target Name="CalculateVersionCodeProperties" AfterTargets="CoreCompile">
    <GetAssemblyIdentity AssemblyFiles="$(OutputPath)$(AssemblyName).dll">
      <Output TaskParameter="Assemblies" ItemName="AssemblyVersionInfo" />
    </GetAssemblyIdentity>
    <PropertyGroup>
      <BuildNumber>$([System.Version]::Parse(%(AssemblyVersionInfo.Version)).ToString(4))</BuildNumber>
      <Major>$(BuildNumber.Split('.')[0])</Major>
      <Minor>$(BuildNumber.Split('.')[1])</Minor>
      <Build>$(BuildNumber.Split('.')[2])</Build>
      <Revision>$(BuildNumber.Split('.')[3])</Revision>
      <Year>$([System.DateTime]::Now.ToString ('yyyy'))</Year>
      <Month>$([System.DateTime]::Now.ToString ('MM'))</Month>
      <Day>$([System.DateTime]::Now.ToString ('dd'))</Day>
    </PropertyGroup>
    <PropertyGroup>
     <AndroidVersionCodeProperties>year=$(Year);month=$(Month);day=$(Day);major=$(Major);minor=$(Minor);build=$(Build);revision=$(Revision)</AndroidVersionCodeProperties>
    </PropertyGroup>
  </Target>

With $(AndroidVersionCodeProperties) in place we can now define our $(AndroidVersionCodePattern).

{abi}{major:D2}{minor:D2}{build:D2}{revision:D4}

 

Wrapping Up

Once this is all in place, there is no need to update the Android VersionCode in the AndroidManifest.xml as it can all be done programmatically. Just remember to update the versionName when themajor build version updates.

To discuss this article, head on over to our Xamarin Forums!

0 comments

Discussion is closed.

Feedback usabilla icon