Play Licensing in Xamarin.Android

Google Play offers a licensing service that lets us enforce licensing policies for applications that us publish on Google Play. With Google Play Licensing, our application can query Google Play at runtime to obtain the licensing status for the current user, then allow or disallow further use as appropriate.

The Google Play Licensing service is primarily intended for paid applications that wish to verify that the current user did in fact pay for the application on Google Play. However, any app (including free apps) may use the licensing service to initiate the download of an APK expansion file.

Getting Things Ready

In order to add licensing to our app, all we will need is the licensing verification library. We can get this from NuGet.org or the Component Store (coming soon), or, we can build the source using the GitHub repository.

After adding the library, we need to get hold of our API key for this app:

  1. Browse to the Google Play Developer Console
  2. Select “All Applications” from the sidebar
  3. Select the app we want to implement licensing for
    • If we are going to create a new app, select “Add new application”
    • Enter a name for the app
    • Select “Prepare store listing”
    • Enter the required details for publishing
  4. Select “Services & APIs” from the left menu
  5. Scroll to the “Licensing & In-app billing” section
  6. Under the “Your license key for this application” heading, copy the base64-encoded RSA public key
  7. Paste it into a string constant in the app code:
    const string ApiKey = "XXX";

All Applications in Play
Public Key

Adding the License Handlers

Once we have installed the library and have our key, we need to ensure that the app has the appropriate permissions to access Play and the licensing service:

    [assembly: UsesPermission("com.android.vending.CHECK_LICENSE")] 

Once we have permission, We can then implement the ILicenseCheckerCallback interface. This can be implemented on the activity, but does not have to:

    public class MainActivity : Activity, ILicenseCheckerCallback
    {
      public void Allow(PolicyServerResponse response)
      {
        // Play has determined that the app is owned,
        // either purchased or free
      }
      public void DontAllow(PolicyServerResponse response)
      {
        // Play has determined that the app should not be available to the user,
        // either because they haven't paid for it or it is not a valid app

        // However, there may have been a problem when Play tried to connect,
        // so if this is the case, allow the user to try again
        if (response == PolicyServerResponse.Retry)
        {
          // try the check again
        }
      }
      public void ApplicationError(CallbackErrorCode errorCode)
      {
        // There was an error accessing the license
      }
    }

Starting the Check

Once we have implemented the interface, all we need to do now is start the check. There are two basic methods provided in order do this, one with caching and one without.

Using StrictPolicy

To make things easier to start off with, I will first demonstrate the one without caching, the StrictPolicy:

    // create the policy we want to use
    var policy = new StrictPolicy();
    // instantiate a checker, passing a Context, an IPolicy and the Public Key
    var checker = new LicenseChecker(this, policy, "Base64 Public Key");
    // start the actual check, passing the callback
    checker.CheckAccess(this);

As soon as the check has completed, either with an error or successfully, one of the methods on the callback will be called, either Allow, DontAllow or ApplicationError.

Allow will receive a Licensed response
DontAllow will receive a NotLicensed response
ApplicationError will have the reason for the error, such as NotMarketManaged, InvalidPublicKey or some other reason.

Using ServerManagedPolicy

Although checking with Play each time the app launches is not a problem, doing so requires additional time and resources before the app can start. Usually, we can use the one with caching, the ServerManagedPolicy policy. This is very much the same as the StrictPolicy, but with an additional step to provide an IObfuscator to store the response:

    // create a device-unique identifier to prevent other devices from decrypting the responses
    string deviceId = Settings.Secure.GetString(ContentResolver, Settings.Secure.AndroidId);
    // create a app-unique identifer to prevent other apps from decrypting the responses
    var appId = this.PackageName;
    // create a random salt to be used by the AES encryption process
    byte[] salt = new byte[] { 46, 65, 30, 128, 103, 57, 74, 64, 51, 88, 95, 45, 77, 117, 36, 113, 11, 32, 64, 89 };

    // create the obfuscator that will read and write the saved responses, 
    // passing the salt, the package name and the device identifier
    var obfuscator = new AesObfuscator(salt, appId, deviceId);
    // create the policy, passing a Context and the obfuscator
    var policy = new ServerManagedPolicy(this, obfuscator);
    // create the checker
    var checker = new LicenseChecker(this, policy, Base64PublicKey);
    // start the actual check, passing the callback
    checker.CheckAccess(this); 

As soon as the checker has returned and we know that we can start the application, we should destroy the cecker in order to free up resources and close connections:

    // free resources and close connections
    checker.OnDestroy();

Testing the Licensing

The last thing that is needed is testing. To do this, we have to be sure that we have uploaded and published the app to Play. Publishing to any of the channels, including Alpha and Beta, will work.
In order for the Alpha or Beta channels to be used on devices other than the publisher’s device, those people have to be added to the Alph or Beta testers group.
If we want to test different responses that our app may receive from Play, we can select the desired response from the settings:

  1. Select “Settings” from the sidebar
  2. Select “Account details” from the left menu
  3. Scroll dow to the “License Testing” section
  4. Select the desired response from the drop down titled “License Test Response”
    • For other testers, make sure we enter their Google account email address in the text area above titled “Gmail accounts with testing access”

Custom License Responses

Important Things to Remember

Testing licensing is easy to do, provided we have all the required bits in place. Here are some common things that we may have to check:

The Play Store

  1. The app version on the device must be the same as the app that is on the store
  2. Provide enough time for the app to appear on the store, this can be determined by a little exclamation sign next to the app title when viewing the app details
  3. Make sure that the app is indeed published, and not in draft

For Other Testers

  1. Ensure that the testers have been added to the Alpha or Beta testers group
  2. If we are testing custom responses, make sure that their emails are added to the “Gmail accounts with testing access” text area in “Settings”

For The App

  1. Make sure we have the Android permission
    com.android.vending.CHECK_LICENSE
  2. Ensure that the app has the same version code/number and package name as that which is on the store

Xamarin Insights for Older Androids

Recently, Xamarin announced a real-time crash reporting and analytics solution for mobile apps, Xamarin Insights.

This is an awesome tool with many great features. They support all the major platforms, iOS Android Windows Phone, Windows RT and traditional desktop applications. Support for Xamarin.Mac is coming soon.

Some of the major features:

  • Report details about the device statistics such as operating system and screen resolution
  • Gather and report any uncaught native or managed exceptions
  • Report any caught exception, along with any additional data
  • Track both past and active sessions
  • Track any event that occurs in your application, including the time it takes to execute
  • Cross-platform across almost all devices, including support for PCL libraries

Old Androids

Recently they added support for Android versions below API level 14 (Android Version 4.0 – Ice Cream Sandwich). To use Xamarin Insights in an Android app below API level 14, such as API Level 8 (Android Version 2.3 – Gingerbread), there are a few things that need to happen:

  1. Set your ‘Compile using Android version’ or ‘Target framework’ value to be API level 14 or higher, such as API level 19
  2. Set the ‘Minimum Android to target’ or ‘Minimum Android version’ to be the value you are wanting to support, such as API level 8.

This will result in your app building against the higher API level, but can run on earlier devices.

However, even after all this, there is still a limitation, namely the inability to record sessions. This may not be a deal breaker for you, but for some, this is. The reason for this is that Xamarin Insights is using the IActivityLifecycleCallbacks interface. This is a relatively new addition to the Android API and is very useful in that it allows you to hook into the Activity lifecycle without having to use the Activity itself. As this interface is not available for the older versions, they simple can’t record the Activity sessions.

The Code

I am here to give you that solution that you always wanted: Manually starting and stopping sessions from within the activity. To do this I have created a simple class InsightsCompat:

    public static class InsightsCompat
    {
        public static void Initialize(string apiKey)
        {
            Insights.Initialize(apiKey, Application.Context);
        }

        public static void StartSession()
        {
            EmitBackgroundChange(false);
        }

        public static void StopSession()
        {
            EmitBackgroundChange(true);
        }

        private static void EmitBackgroundChange(bool backgroundState)
        {
            try
            {
                var status = backgroundState ? "Background" : "Resumed";
                var table = new Dictionary<string, string> {{"Status", status}};
                Insights.Track("X-App-State", table);
            }
            catch (Exception ex)
            {
                Insights.Report(ex);
            }
        }
    }

The Usage

This simple class can do all the work that is needed, plus there is an additional method, Initialize, that allows you to start up Xamarin Insights without having to find the context:

    // from anywhere in your code
    InsightsCompat.Initialize("your API key");

To start and stop sessions, you can override the OnResume and OnPause methods:

    protected override void OnPause()
    {
        InsightsCompat.StopSession();
        base.OnPause();
    }

    protected override void OnResume()
    {
        base.OnResume();        
        InsightsCompat.StartSession();
    }

We only have to override these two methods as android will always call these methods, no matter where the Activity came from or where it is going.

There’s More

Even though Xamarin Insights has many features, it is still in preview and there can still be many more features. If you have any feature requests or ideas, be sure to drop a message on the Xamarin Insights User Voice.

There is a small docs page for Xamarin Insights here. So head over to the dashboard and get started creating and supporting awesome cross-platform apps now.

Binding Flurry Analytics with Xamarin.Android

This week, I needed to use Flurry Analytics in my Xamarin.iOS and my Xamarin.Android apps, but there was no .NET SDK for these platforms. Flurry did provide a SDK for each platform, but it was the native libraries, which cannot be used directly in .NET. Given this, I decided to bind those native libraries using Xamarin.iOS and Xamarin.Android.

I have split this project up into four parts:

  1. Introduction and Pre-requisites
  2. Xamarin.iOS binding
  3. Xamarin.Android binding
  4. Flurry.Analytics in the wild

After binding the iOS SDK for Flurry Analytics, we are going to move onto the Android release. This task needs only one thing from the downloaded SDK:

  • [Android-sdk-path]/Android 4.1.0/FlurryAnalytics/FlurryAnalytics-4.1.0.jar

Of course, the version numbers may change for later releases. The java archive file (.jar) is going to be used to generate the .NET interfaces and enums, and then be embedded in the resulting assembly.

Just before we do the real binding, we should just create our C# solution for the Xamarin.Android binding. Just create a new project/solution and select the Android “Bindings Library” template. For my project name I used Flurry.Analytics.Android, but you could use anything.

The default project has a few files and directories in it, we will have a look at each one in depth as we go through the binding steps:

  • /Additions/ (this allows you to add arbitrary C# to the generated classes
    before they are compiled)
  • /Properties/AssemblyInfo.cs (the usual assembly information attributes)
  • /Jars/ (this directory is for Android .jars)
  • /Transforms/EnumFields.xml (this allows you to map Java int constants to C# enums)
  • /Transforms/EnumMethods.xml (this allows changes to method parameters and return types from Java int constants to C# enums)
  • /Transforms/Metadata.xml (this allows changes to be made to the final API)

Creating the Initial Binding

This step will involve just adding the jar to the project, and letting the compiler do it’s thing, but we will almost always have to go in and tweak a few things in the Metadata.xml.

So, first things first, add the jar file to the project and compile. The build will probably fail with error messages containing single character methods and types. This is because the actual jar file has been obfuscated. However this can easily be fixed.

The way the generation works is that there is a two step process, there is a tool that generates a bunch of xml files from the jar file. These xml files are then used to generate C# code. The Metadata.xml sits in between the two steps and can be used to transform the generated xml before the C# generation.

Tweaking the Generated Binding (Manifest.xml)

As we can see that the build fails on obfuscated types, we can remove these. The removal is safe as we are only preventing the .NET binding from being created, not actually removing the underlying Java members. And, as these items have been obfuscated, we can safely assume that we aren’t supposed to be accessing them anyway.

But, instead of removing each member or type that appears, we can use a great tool that will decompile the jar file and show us exactly what types are internal and what types we should be binding. I use JD-GUI, which is a free Java decompiler. They also have a nice online version, JD-Online. What we can do is to just upload the jar file here and see what’s inside:

  • com.flurry.android.impl.analytics.*
  • com.flurry.android.*
  • com.flurry.sdk.*

As we can see, the impl and sdk branches contain internal and obfuscated types, so we can remove those:

<remove-node path="/api/package[starts-with(@name, 'com.flurry.sdk')]" />
<remove-node path="/api/package[starts-with(@name, 'com.flurry.android.impl')]" />

After this, the build should now succeed and we will have an assembly that we can use. However, there are still some types that we can remove to clean the API a bit: InstallReceiver and Constants. InstallReciever is not used by the consumer, so this is safe to remove, but Constants is still used. If we remove this, then the consumer will not have access to the values on the type. We can see that Constants just contains the values representing male, female and unknown.

To remove the InstallReciever, we can add this line to Metadata.xml:

<remove-node path="/api/package[@name='com.flurry.android']/class[@name='InstallReceiver']" />

For the Constants type, we will do something different.

Managing the Enumerations (Additions & EnumFields.xml)

As we clean up the API, we want to remove the Constants type and replace it with an enum. One way to do this is to use the EnumFields.xml:

<mapping clr-enum-type="Flurry.Analytics.Gender" jni-interface="com/flurry/android/Constants">
    <field clr-name="Male" jni-name="MALE" value="1" />
    <field clr-name="Female" jni-name="FEMALE" value="0" />
    <field clr-name="Unknown" jni-name="UNKNOWN" value="-1" />
</mapping>

This will generate a nice enum for us, but this does leave an unused interface IConstants. As this is a very small library, we can do this mapping slightly differently. First we remove the entire Constants type in the Metadata.xml:

<remove-node path="/api/package[@name='com.flurry.android']/interface[@name='Constants']" />

Then, we can create the enum in the /Additions/ directory. To do this, add a new file (for example called FlurryAgent.cs) under this directory and add the enum:

public enum Gender
{
    Male = 1,
    Female = 0,
    Unknown = -1
}

Now there is one last thing to do before the API definition is complete. There is a SetGender method on the type FlurryAgent, which takes the type sbyte. It is not intuitive to use the Gender enum here, so we can fix this in a two step process. First we will create an overload in the FlurryAgent.cs file that accepts a Gender enum member as an argument:

public partial class FlurryAgent
{
    public static void SetGender(Gender gender)
    {
        FlurryAgent.SetGender ((sbyte)gender);
    }
}

And, what we can do is also hide the original member as the new overload is good enough:

<attr path="/api/package[@name='com.flurry.android']/class[@name='FlurryAgent']/method[@name='setGender']" name="visibility">internal</attr>

And with this, our binding is complete, although we can do a few nice changes to the namespace and parameter names.

Changing Parameter Names

Now that we have the binding complete, we can see that it is using the namespace Com.Flurry.Android, which is no .NET-like at all. We can change this to something better:

<attr path="/api/package[@name='com.flurry.android']" name="managedName">Flurry.Analytics</attr>

This maps the com.flurry.android package name to the neat Flurry.Analytics namespace. One last thing is to fix the parameter names. Sometimes you can use the JavaDocs, but in this case, I couldn’t get it to work. Doing it manually is not hard, but it is boring and time consuming, but here are a few.

This is the usual mapping:

<attr path="/api/package[@name='com.flurry.android']/class[@name='FlurryAgent']/method[@name='onStartSession']/parameter[@name='p0']" name="name">context</attr>
<attr path="/api/package[@name='com.flurry.android']/class[@name='FlurryAgent']/method[@name='onStartSession']/parameter[@name='p1']" name="name">apiKey</attr>
<attr path="/api/package[@name='com.flurry.android']/class[@name='FlurryAgent']/method[@name='onEndSession']/parameter[@name='p0']" name="name">context</attr>

If there are complicated parameter types (note the &lt;):

<attr path="/api/package[@name='com.flurry.android']/class[@name='FlurryAgent']/method[@name='logEvent']/parameter[@name='p1' and @type='java.util.Map<java.lang.String, java.lang.String>']" name="name">parameters</attr>

If there are overloads with different parameter types:

<attr path="/api/package[@name='com.flurry.android']/class[@name='FlurryAgent']/method[@name='onError']/parameter[@name='p2' and @type='java.lang.Throwable']" name="name">exception</attr>
<attr path="/api/package[@name='com.flurry.android']/class[@name='FlurryAgent']/method[@name='onError']/parameter[@name='p2' and @type='java.lang.String']" name="name">errorClass</attr>

After doing this for all the members, the binding is now complete.

Finishing Up

So far we have defined our API, added any additional logic or types, added the native library and added parameter names. This is all that is needed, so our library should build fine now and we should be able to use it in an Xamarin.Android app:

// the methods
FlurryAgent.StartSession(this, "PQSZJRK4B5BW8Q7YQQXF");

// the properties that we changed back into methods
string version = FlurryAgent.ReleaseVersion;

// the extra method that we added
FlurryAgent.SetGender (Gender.Male);

Binding Flurry Analytics with Xamarin

Over the last few days I have been creating a Xamarin.iOS and Xamarin.Android binding for Flurry Analytics SDKs. Flurry Analytics is a neat little library that allows for tracking of your app usage and various user stats.
And, because I really enjoyed my time doing this, I thought that I will share just a bit of the fun times and the not-so-fun times.

I have split this project up into four parts:

  1. Introduction and Pre-requisites
  2. Xamarin.iOS binding
  3. Xamarin.Android binding
  4. Flurry.Analytics in the wild

Pre-requisites

Before we start any coding, we need to get all our tools and files needed for the actual binding tasks.

I was using both Windows 8, with Visual Studio, and Mac OS X with Xamarin Studio. You can bind the Android library on either platform, but for iOS, it is easier to use the Mac. In this case, I will use the Mac for both iOS and Android.

Some of my very excellent sources for this process were the actual Xamarin documentation:

But, along with this info, there are just a few things that you may need. Firstly, it is good to update your Xamarin Studio to the latest stable release as this makes sure that all potential problems are minimized from the start.

Then, the next cool tool to get hold of is, Objective Sharpie, for binding iOS libraries. This tool is quite nifty for quickly generating the .NET interfaces from the Objective-C header files. It uses the header files not the actual compiled native library. The Xamarin docs on Objective Sharpie has a brief walkthrough on how to use the tool, so I will assume you know how to use it.

After we have all our tools ready to go, we need those SDKs from Flurry.

What I did was to create a free account by Flurry, and then created an Android and iOS Application using their dashboard. You have to have an application before they will let you download their SDKs. This step is pretty straight forward, so I won’t go into it here right now. Once you have created and downloaded the SDKs, you can extract them to a nice location for reference.

Now to get started with the real work…

But, as this is quite a long process, I will be splitting this article into this intro, the iOS binding and the Android binding. So, enjoy!

Transparent WebView on Android Devices

I’m trying to re-write a java android app into Xamarin.Android, however I have come across an issue with the background transparency of the WebView that I use to display the contents of each screen.

This code works correctly on the java version (Black text on a green background), but in the C# version, the WebView’s background is black (black rectangle on the green background).

Java Code:

    @Override public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        LinearLayout layout = new LinearLayout(getApplicationContext());
        layout.setBackgroundColor(Color.GREEN);
        WebView webView = new WebView(getApplicationContext());
        layout.addView(webView);
        setContentView(layout);

        webView.getSettings().setJavaScriptEnabled(true);
        webView.setBackgroundColor(Color.TRANSPARENT);
        String html = "<html><body style='background-color: transparent;'>Some text...</body></html>";
        webView.loadData(html, "text/html", "UTF-8");
    }

C# Code:

    protected override void OnCreate(Bundle bundle)
    {
        base.OnCreate(bundle);

        var layout = new LinearLayout(ApplicationContext);
        layout.SetBackgroundColor(Color.Green);
        var webView = new WebView(ApplicationContext);
        layout.AddView(webView);
        SetContentView(layout);

        webView.Settings.JavaScriptEnabled = true;
        webView.SetBackgroundColor(Android.Graphics.Color.Transparent);
        string html = "<html><body style='background-color: transparent;'>Some text...</body></html>";
        webView.LoadData(html, "text/html", "UTF-8");
    }

There is also a ‘Android.Resource.Color.Transparent’, but don’t use this one as values returned from the Android.Resource namespace are resource ids, not colours.