TestFlight for Xamarin.Android

TestFlightOne of the keys to making good apps great is a solid beta distribution and testing process. The ability to track usage of your app and view crash analytics will result in an improved user experience when it comes time to publish your app.

Enter TestFlight for Android. A huge plus TestFlight now brings to the table is the ability for a team that is creating both Android and iOS apps to have a single tool to manage beta distribution and testing. By the way, I should mention TestFlight’s basic features are free. We all love freebies!

Today you will be shown how to get TestFlight’s Android SDK implemented in an app created using Xamarin.Android (formerly known as MonoDroid). If you are familiar with Xamarin.Android and using Java binding projects then feel free to jump to our Github page and take a look at the sample app.

A quick note. I do not have rights to re-distribute TestFlight’s Android SDK. At this moment it is still in its infant state and only available as a private beta. To get the SDK you will have to go to TestFlight’s site and sign up for the beta.

Get the sample project and bindings library from here.

The Java Bindings Project

In order to use Java libraries in Xamarin.Android projects a Java Bindings Project must be used. This project type is included in the tools provided by Xamarin. The bindings project takes a Java library and creates JNI (Java Native Interface) wrappers for the Java library’s public API. This allows the API to be consumed in Xamarin.Android projects written in C#.

If you are following along using the sample project you will need to open the TestFlightBindings project and add the TestFlightLib.jar file to the Jars folder. Remember you have to get the SDK from TestFlight. You will notice a broken reference in the folder that can be deleted. It may be helpful to rename the jar file to include the SDK version number. This will help you in the future to determine if you need to update the binding project with an updated version of the SDK. After the jar file is added to the Jars folder, right-click on the jar file and select properties. In the properties window change the build action to EmbeddedJar.

Transforms Metadata

Documentation for implementing the API transforms can be found here.

The transform metadata can be found in Transforms/Metadata.xml.

The following line will exclude all packages except com.testflightapp.lib from our binding project.

The next line will rename the com.testflightapp.lib package to a more .NET friendly naming convention. It’s a matter of personal taste what you choose. The managed name will be the namespace used to reference the library in our app project. I prefer to leave it the exact package name and apply Pascal casing.

The remaining transform metadata will rename all the public method parameters. Once again this is not a requirement but helps when using intellisense.

Add Helper Methods

All the generated .NET API wrappers are created as partial classes. This gives us the ability to add extra code to them and make them more user friendly. The following class can be found in Additions/TestFlight.cs.

The first two methods are probably overkill since we really only need the last method that takes a parameter of type Exception.

Now we have helper methods to make implementing the API easier. The native API has a method called SendCrash that takes 3 parameters. The first is a timestamp that is a 64 bit number. The number is calculated as the total milliseconds from the current time to January 1, 1970 UTC. Java has a function to calculate this timestamp named “currentTimeMillis”. Luckily the Xamarin framework includes implementations for many of the native Java libraries. The second parameter is the stacktrace. This parameter name is misleading because the output should actually be the error message and stacktrace. Calling Exception.ToString() provides all the needed details. The last parameter is the thread name. This is another instance where the Xamarin framework’s native Java wrappers come in handy.

That wraps up the java bindings project. Go ahead and build the project. I prefer to build the project in release configuration.

Consume Library In Our App

We will need to add a reference to our bindings project in our Android app project. I have never been able to get a project reference to work correctly with a Java bindings project. We will need to add a reference to the DLL file created after building the bindings project. This can be done by clicking the browse button from the reference manager window. Then navigate to the DLL file in the [project root]\bin\Release folder.

Create a custom class that inherits from Android’s Application class.

First notice the class constructor. It must be implemented this way to allow JNI to consume our class. Next we initialize TestFlight by calling TakeOff. You will need to add your app token provided by TestFlight as the second parameter. Then we add an event handler to catch all unhandled exceptions. In our event handler we call TestFlight.SendCrash and pass the Exception. If that method looks familiar it was one added in the helper methods in Additions/TestFlight.cs.

Next we will create sample activities to test different crash scenarios. If you are unfamiliar with the inner workings of the Xamarin.Android framework, the .Net code runs in a virtual machine (Mono) that runs on top of Android’s native virtual machine (Dalvik). For sake of clarification we will call these the .Net layer and Java layer, respectively. It is possible to have errors in either of these layers. The TestFlight SDK automatically reports errors in the Java layer. The MyApp application class above will pass unhandled exceptions from the .Net layer to TestFlight.

Create an activity that throws an exception in the .Net layer.

Create an activity that throws an exception in the Java layer.

I “found” this example the hard way in a project I’m working on. This activity will not even start before crashing.

The final activity will create a checkpoint in TestFlight. Checkpoints are useful for gathering usage statistics.

Build And Add To TestFlight

To create the APK file to upload to TestFlight, set the project build configuration to Release and deploy to a device or emulator. Deploying in release mode will include the Xamarin runtime in the build. The APK file will be located in the [project root]\bin\Release folder. Be sure to use the signed APK by using the file that ends with “-Signed”.

When you upload the app to TestFlight you should get a warning that the app token was not detected. If you are sure the app token is present in the application class, press “Ignore and Continue”. This is a byproduct of the way apps built with Xamarin.Android are packaged.

Hopefully this will get you up and running using TestFlight and Xamarin.Android. If you have any questions, comments or suggestions drop me a line in the comments below.

You May Also Like

About the Author: Bradley Hall


  1. Thank you, Bradley! I have integrated this SDK into my Xamarin Android App. Crash reporting and checkpoints works well. But I did not find sign of the in-app update feature, in either my app or your sample app. So is this included in your binder and are there any other necessary steps for this feature to work?

    1. JavaYu, it is great to hear that you have implemented the SDK successfully! The Android SDK v1.0 does not currently support the In App Update feature. Android SDK Docs will outline the currently supported features as compared with the iOS SDK Docs. With the iOS SDK nothing is specifically done to implement this feature. The SDK docs state: “If a user is using a beta version of your app, you are setting the UDID, a new beta version is available, and that user has permission to install it; an in app popup will ask them if they would like to install the update. If they tap ‘Install’, the new version is installed from inside the app.”. It is likely to be the same with Android once that feature is provided.

    1. Extend Android’s Application class the same way as in the example above. The class will need to be added to the UI.Droid project in an MvvmCross app. The App class in the Core PCL belongs to the MvvmCross framework and shouldn’t be confused with Android’s Application class. When extending Android’s Application class and decorating it with the attribute [Application] the class will be consumed automagically.

      The following screenshot is of the Tip Calculator app available in the MvvmCross tutorials. I added a class “MyApp” and put a break point in the OnCreate method to confirm the method was called. I did not make any changes to the rest of the sample project.

      MvvmCross Application Screenshot

  2. Hi Bradley. Very nice blog!

    I just discovered this post, and was pleased to also see that TestFlight have now officially released the Android SDK. However it seems to be built against JDK 7, which the bindings project does not seem to like. I get a lot of:

    Unsupported major.minor version 51.0

    errors, which means it ignores all the class files and you end up with an empty dll. Have you come across this problem, and do you know of a way round this?

    1. I haven’t experienced this issue. Confirm the build action for TestFlightLib.jar is set to Embedded Jar in the bindings project.

      As a side note, I have JRE 7 installed on my machine alongside JRE 6 and JDK 1.6. I’m not sure if that would make any difference.

Leave a Reply

Fork me on GitHub