I love automating processes and making things consistently repeatable. Continuous integration is your friend, yes it can take time to setup but if you take that effort hit upfront it will pay off in an immeasurable way through your development process and during the entire lifetime of the your development.
For my continuous integration I use JetBrains TeamCity. I love this CI system, granted I’ve not used them all but comparing them to TFS and Jenkins it is like an oasis of calm in comparison and without doubt the cleanest UX design by a very long margin. Anyway … I digress. If you want to automate the process of producing your ready to distribute Xamarin .apk Android application packages, this is the basic process you need to follow:
Creating Your Keystore
The first step is to create your own personal keystore that will contain the information used to digitally sign your Android package files. You can do this with the following command:
"C:\Program Files (x86)\Java\jre1.8.0_45\bin\keytool.exe" -genkey -v -keystore myandroid.keystore" -alias myaliasdroidpub -keyalg RSA -keysize 2048 -validity 30000
Before you run this command make a note a few parameters first. I did all of this in a batch file so I can refer to it later, this does include some sensitive data so beware what you do with this file. The 30000 at the end of the command denote the length of validity of the certificates and Google require this to be past 2033. You’ll need the following info:
REM — Password – <yourpassword>
REM — name —– <yourname>
REM — OU ——- <organisationunit> eg: JamSoft
REM — Orgname — <organisationame> eg: JamSoft
REM — Local —- <locality> eg: Frome
REM — State —- <state> eg: Somerset
REM — Country — <2lettercountrycode> eg: UK
Visual Studio Android Project
Now that we have our Java keystore ready and prepped for use we can look at the Visual Studio project. In order to make this automated in the build system we need to configure the project to use our keystore credentials. This is spreading sensitive information around but since our keystore is probably going to be checked into our repository it’s most likely going to spend it’s life being treated in a sensitive fashion anyway, so no real concerns. I personally make lots of backups of things in large .RAR files and store these in various places but these are also password protected and treated as confidential.
In Visual Studio edit the Android application .csproj file and add another PropertyGroup element as per the code below:
<PropertyGroup Condition="'$(Configuration)' == 'Release'"> <AndroidKeyStore>True</AndroidKeyStore> <AndroidSigningKeyStore>myandroid.keystore</AndroidSigningKeyStore> <AndroidSigningStorePass>yourpassword</AndroidSigningStorePass> <AndroidSigningKeyAlias>myaliasdroidpub</AndroidSigningKeyAlias> <AndroidSigningKeyPass>yourpassword</AndroidSigningKeyPass> </PropertyGroup>
Now our .csproj file knows how to use our keystore unattended. We can tie into the Xamarin build process from within our automated builds and produce the base Android package.
You can test that this is working using the following command:
msbuild.exe HelloWorld.csproj /p:Configuration=Release /t:PackageForAndroid
This will execute MSBuild against your Android project file and you’ll now find your .apk file in your bin\Release directory.
Signing The Package
Now that we have our packaged application we can apply the signing processes. To sign the package created in the previous step we need to execute the following command:
"C:\Program Files (x86)\Java\jdk1.7.0_71\bin\jarsigner.exe" -verbose -sigalg SHA1withRSA -digestalg SHA1 -keystore myandroid.keystore -storepass yourpassword -keypass yourpassword -signedjar \bin\Release\packagename-signed.apk \bin\Release\packagename.apk myaliasdroidpub
This package is now digitally signed using your certificate from the keystore we made earlier. Personally I still have a couple of questions around why this needs to be done again considering that the details for this keystore are in the csproj file but I’m still waiting on a response from Xamarin on this.
ZipAligning the Signed Android Package
Now that we have a signed package we can zip align this package and then publish this as an artifact of our TeamCity build process. This command makes use of the Android SDK zipalign.exe program. You’ll have to find where this is on your machine as there are many potential locations. The command you need will look something like this:
“C:\Users\<name>\AppData\Local\Android\android-sdk\build-tools\<version>\zipalign.exe” -f -v 4 packagename-signed.apk packagename-zipaligned.apk
You don’t need to follow this naming convention used here this is just for illustration purposes.
You can now set this as a published artifact of your TeamCity build configuration. Yay!
To kick off the process in your MSBuild project you can add TeamCity Step that executes an additional Target in your build script like this:
<Target Name="PackageAndroidApk"> <MSBuild Projects="$(MSBuildProjectDirectory)\..\src\path\MyProject.Droid.csproj" Targets="PackageForAndroid" Properties="Configuration=Release"> </MSBuild> </Target>
This target will create the base APK package that you can sign and zipalign.
Once you have all these commands working you can add all the required build steps.
And voila! Automated. Nice 🙂