Inter-App Communications in Xamarin.iOS and Why OpenUrl Freezes for 10+ sec

Inter-App Communications

Mobile apps are meant to communicate using multiple channels, but the most popular, recommended, and widely used is using Scheme Uri. If you have not used Scheme URI then you should consider adding them to your app, it takes less than a minute to add support to your app, and it provides you a great way to get users to your app.

Setting the Stage

One scenario that I had was App A was launching App B and querying data, App B was in turn looking up the request, and returning data to App A. This is a common practice and can be seen in the diagram below.

Scheme uri ios

Scheme uri ios

The Investigation

The problem here was that App B was freezing for up to 10+ sec before returning the result to App A. At first, I thought that this might be because the app initialisation or the data lookup taking long time, so I added diagnostic trace statements like below to time the operation and see where the time is spent.

public class AppDelegate
{
	...
	
	public override bool FinishedLaunching(UIApplication app, NSDictionary options)
	{
		Console.WriteLine("FinishedLaunching started: " + DateTime.Now.ToString("F"));

		...
		
		Console.WriteLine("FinishedLaunching complete: " + DateTime.Now.ToString("F"));
	}

	public override bool OpenUrl(UIApplication application, NSUrl url, string sourceApplication, NSObject annotation)
	{
		Console.WriteLine("OpenUrl started: " + DateTime.Now.ToString("F"));

		...
		

		Console.WriteLine("OpenUrl complete: " + DateTime.Now.ToString("F"));
	}
}

I found that my app was starting in less than 1 Sec, which is quite impressive, and I am very happy about 🙂 but the problem was in returning the data to the launching app (App A). The traces were like these:

Launch Services application launch failed - timeout waiting - Trace logs

Launch Services application launch failed – timeout waiting – Trace logs

This is telling me that App B was not able to launch App A to return back the data, which was quite surprising. I found that if you move that code to your pages/viewControllers things work fine. I thought that this was a bizarre situation, then I found this StackOverflow post, which explained the problem.

The Solution

Apparently, the iOS was having a race-condition like in trying to launch an app while the app itself was not fully launched. So the suggested solution was to add some delay or run it on another thread. Running the launch of App A on another thread would not work as it needs to be on the mainUiThread, so here is the solution I came up with:


public class AppDelegate
{
	...
	
	public override bool OpenUrl(UIApplication application, NSUrl url, string sourceApplication, NSObject annotation)
	{
		// handle opening url and look up data

		...

		Task.Delay(500).ContinueWith(_ => 
				{									
					this.InvokeOnMainThread( () => 
					{			
						var uri = NSUrl.FromString(callbackUri);
						UIApplication.SharedApplication.OpenUrl(uri);
									
					});

				});

		return true;
		
	}
}

: LaunchServices: application launch failed – timeout waiting for launch.

This works like a charm :). First, we got rid off the launch service error (shown above). Second, App B is now returning the results to App A in less than 3 sec. If App B is in the background then it would return the data in less than 1 sec. Otherwise, it would take up to 3 sec to return the data. yayyy 🙂

A Journey of Hunting Memory Leaks in Xamarin

My client was reporting performance issues with an existing app that was developed internally, and I had to find the problems. So, here is my journey on finding the issues and resolving them. The resolution was a reduction of the memory usage to 1/4 of what it was and usage was stabilised to this level (1/4). I am hopeful that this blog post can help you too in refining your app and pro-actively resolving any performance issues.

Capturing Telemetry Data

The first step in optimisation must be setting your benchmark, and in order to do that, we need to know where we stand. Thus, I set up an integration with Azure Application Insights to capture all memory warnings, errors, warnings, and battery level monitoring. For details on integrating with Azure App Insights, you can read more in my previous post here. The relevant part for us in this post is capturing memory warnings. There are three ways to capture memory warnings in iOS as I listed them on StackOverflow, we will stick with AppDelegate, as this is applicable to both traditional Xamarin and Xamarin Forms.


public partial class AppDelegate
{
	...
	public override void ReceiveMemoryWarning (UIApplication application)
	{
		// this (MemoryWarningsHandler) is a helper that I created 
		// to capture more info when a memory warning is raised. Things like (nav Stack, running time, etc)
		MemoryWarningsHandler.Record ();
	}
}


Always, Always, listen to these memory warning notifications from the OS, even if you are not actioning them now

In Android, we could also do the same using Application.OnLowMemory (See Android docos) as below:


public class MyApp : Application
{
	...
	public void OnLowMemory ()
	{
		MemoryWarningsHandler.Record ();
	}
}

Once we received and captured these memory warnings on Azure App Insights, we will then know that we have a memory warning, and whoever is looking at the report will keep bugging you until you fix this problem, if the app was not crashing due to low memory 🙂

Investigating Low Memory Issues

Once we identified that there is a problem with Memory, we need to figure out where the problem is occuring. To do this, we could use Xamarin Profiler. At the time of this writing (March 2016), Xamarin Profiler is still in preview and has many known bugs, but it still provides a good starting point.
We can monitor a number of performance indicators using Xamarin Profiler including:

  • Memory Allocation
  • Dependency Cycles
  • CPU Time
  • Few more aspects of the app Performance

For this post, we are interested in memory leaks, so we can start a profiler session, by choosing Memory Allocation when the profiler starts. More info on starting a profiler session can be found on Xamarin website.

In previous versions of Xamarin Profiler, I was able to view the call tree which gave me a great view on where the issue exactly was. This was based on call stacks and it tells you exactly how much memory is used in every entity/method. Unfortunately, in this version, I could not get this to show me this detailed view, but I was able to capture few memory snapshots and monitor the growth of used memory. My diagram looked like this:

Memory Usage before optimisation

Memory Usage before optimisation

This made it very clear that we have a problem in our memory consumption, the memory usage was racking up to 600 MB in some scenarios. The important part was now finding where the problem is.

Identify Problematic Code

In the absence of the call tree view, I started using the app and monitoring the memory usage. I established that it was a particular Page (Xamarin Forms Page) that was causing the memory usage to grow rapidly. As you can see at the start of the application, things were quite alright. Then, I focused my attention to that page. Looking at the page, it seemed harmless. It’s only a screen-saver-like page for a kiosk app. I could see a couple of small problems, but these are minor and would not cause the memory to grow that quickly. The code of this screen saver page can be seen below:

    public class ScreenSaverPage : ContentPage
    {
        private readonly List<string> _imageSourceList;
        private readonly List<FileImageSource> _cacheImageSource = new List<FileImageSource>();
 
        private readonly Image _screenSaver;
        private int _currentImageIndex;
        private readonly CancellationTokenSource _cts = new CancellationTokenSource();

        public ScreenSaverPage()
        {
            _imageSourceList = new List<string> { "Screensaver1.png", "Screensaver2.png", "Screensaver3.png", "Screensaver4.png" };
            
            // Caching it to Reduce loading from File all the time
            foreach (string fileName in _imageSourceList)
                _cacheImageSource.Add(new FileImageSource {File = fileName});

            _screenSaver = new Image
            {
                HorizontalOptions = LayoutOptions.FillAndExpand,
                VerticalOptions = LayoutOptions.FillAndExpand,
                Aspect = Aspect.AspectFill,
                Source = _cacheImageSource.FirstOrDefault()
            };
            var tapGestureRecognizer = new TapGestureRecognizer();
            tapGestureRecognizer.Tapped += async (s, e) =>
            {
                _cts.Cancel();
                await Task.Run(async () => await App.ResetInactivity(typeof (BaseViewModel)));
            };
            
            Content = _screenSaver;
            _screenSaver.GestureRecognizers.Add(tapGestureRecognizer);
            // Configure the OnAppearing to kick off the ScreenSaver
            Appearing += async (sender, args) =>
            {
                try
                {
                    await Task.Run(async () =>
                           {
                               while (true)
                               {
                                   if (_cts.IsCancellationRequested)
                                   {
					App.Logger.LogInfo("CANCELLED - In the Loop");
                                       break;
                                   }

                                   await Task.Delay(5000, _cts.Token).ContinueWith(async t =>
                                   {
                                       try
                                       {
                                           if (_cts.IsCancellationRequested)
                                           {
						App.Logger.LogInfo("CANCELLED - In the Action");
                                           }
                                           else
                                           {
                                               // this is the unnecessary Task
                                               await Task.Run(() =>
                                               {
                                                   _currentImageIndex = _currentImageIndex < _imageSourceList.Count 1 ? _currentImageIndex + 1 : 0;
                                                   Device.BeginInvokeOnMainThread(
                                                   () =>
                                                   {
                                                       _screenSaver.Source = _cacheImageSource[_currentImageIndex];
                                                    });
                                               });
                                           }
                                       }
                                       catch (Exception ex)
                                       {
					   App.Logger.Log(ex);
                                           throw;
                                       }
                                   }, _cts.Token);
                               }
                           });
                }
                catch (OperationCanceledException e)
                {
		    App.Logger.Log(e);
                    Device.BeginInvokeOnMainThread(async () =>
                    {
                        await Navigation.PopModalAsync();
                    });
                }
            };
        }
    }

Now, please do not ask me why it’s done this way, because this is just what I have been given from the existing app. The three problems that stood out to me were:

  1. Wiring OnAppearing event without unsubscribing.
  2. GestureRecogniser is added but not removed.
  3. A Task was being created every 5 sec unnecessarily.

However, these all were small compared to the main problem, and even removing all these together did not help in reducing the memory usage. so I switched off the part that swaps the screensaver images.


_screenSaver.Source = _cacheImageSource[_currentImageIndex];

At first, this looked harmless to me, and we were caching the FileImaeSource in a list, so we were not loading the images every time, we only loading them once and only swapping the source on the background image. However, it appeared that this was the root cause. Commenting this line out made the memory usage stay stable below the 200 MB mark, which was great news for me :).

Make sure that you have your benchmark before any optimisations, otherwise you would not know the impact of your changes.

Developing a Solution

To avoid swapping the image source, which by the way, I think it is a Xamarin Forms problem, but I will chase that separately, I started thinking of creating multiple static background images, and only toggle their visiblity. This meant that I would have 4 images loaded and all bound to fill the screen, but I only show (make visibile) one of them at a time. The Page code changed to be like this:


public class ScreenSaverPage : ContentPage
{
        private readonly List<string> _imageSourceList = new List<string> { "Screensaver1.png", "Screensaver2.png", "Screensaver3.png", "Screensaver4.png" };
        private readonly List<Image> _backgroundImages = new List<Image>();
	private  RelativeLayout _relativeLayout;
        private int _currentImageIndex;
        private readonly CancellationTokenSource _cts = new CancellationTokenSource();

        public ScreenSaverPage()
        {
            _relativeLayout = new RelativeLayout { HorizontalOptions = LayoutOptions.FillAndExpand, VerticalOptions = LayoutOptions.FillAndExpand };

		LoadImages (_relativeLayout);
		_backgroundImages [0].IsVisible = true;

         	var tapGestureRecognizer = new TapGestureRecognizer();
         	tapGestureRecognizer.Tapped += async (s, e) =>
            	{
                	_cts.Cancel();
                	await Task.Run(async () => await App.ResetInactivity(typeof (BaseViewModel)));
            	};
            
		Content = _relativeLayout;
		_relativeLayout.GestureRecognizers.Add(tapGestureRecognizer);
        }

	protected async override void OnAppearing ()
	{
		base.OnAppearing ();
		try
		{
			await Task.Run(async () =>
			{
				while (true)
				{
					if (_cts.IsCancellationRequested)
					{
						App.Logger.LogInfo("CANCELLED - In the Loop");
						break;
					}
					await Task.Delay(5000, _cts.Token).ContinueWith(async t =>
					{
						try
						{
							if (_cts.IsCancellationRequested)
							{
								App.Logger.LogInfo("CANCELLED - In the Action");
							}
							else
							{
								_currentImageIndex = (_currentImageIndex < _imageSourceList.Count -1) ? _currentImageIndex +1 : 0;
								Device.BeginInvokeOnMainThread(
								() =>
								{
									SetBackgroundVisibility(_currentImageIndex);
								});
							}
						}
						catch (Exception ex)
						{
							App.Logger.Log(ex);
							throw;
						}
					}, _cts.Token);
				}
			});
		}
		catch (OperationCanceledException e)
		{
			App.Logger.Log(e);
			Device.BeginInvokeOnMainThread(async () =>
			{
				await Navigation.PopModalAsync();
			});
		}
	}

	private  void LoadImages (RelativeLayout layout)
	{
		foreach (string fileName in _imageSourceList) 
		{
			var image = CreateImageView (new FileImageSource { File = fileName });
			layout.Children.Add (image, Constraint.Constant (0), Constraint.Constant (0), Constraint.RelativeToParent (parent => parent.Width), Constraint.RelativeToParent (parent => parent.Height));
			_backgroundImages.Add (image);
		}
	}

	void SetBackgroundVisibility (int currentImageIndex)
	{
		for (int i = 0; i < _backgroundImages.Count; i++) 
		{
			_backgroundImages [i].IsVisible = i == currentImageIndex;
		}
	}

	private static Image CreateImageView (FileImageSource source)
	{
		return new Image
		{
			HorizontalOptions = LayoutOptions.FillAndExpand,
			VerticalOptions = LayoutOptions.FillAndExpand,
			Aspect = Aspect.AspectFill,
			Source = source, 
			IsVisible = false
		};
	}
}

You would agree that this is a big improvement on what we had originally, and it shows clearly on the Xamarin Profiler when we run the app with this new change. The memory plot on the Xamarin profiler was looking like this:

Memory usage after optimisation

Memory usage after optimisation

This is a great reduction, and it is less than one third of what the app was using before (~ 600 MB), but I was still thinking that it needs to be optimised further.

Can We Do Better?

The graph above was showing me that the memory usage was still going up, not by much but still growing. Also, when I switch between screens/pages, I noticed that the screensaver page was taking lots of memory to start with (~ 50 MB), which is to create the images and FileSourceImage objects. However, I noticed that when we move away from this page (screen saver), these entities are not being cleared quickly enough by the GC. Thus, I added the following:


public partial class ScreenSaverPage : ContentPage
{
	...
	protected override void OnDisappearing ()
	{
		base.OnDisappearing ();

		PrepareForDispose ();
	}

	void PrepareForDispose ()
	{
		foreach (var image in _backgroundImages) 
		{
			image.Source = null;
		}

		_backgroundImages.Clear();
		_relativeLayout.GestureRecognizers.RemoveAt (0);
		_relativeLayout = null;
		_cts.Dispose ();
		Content = null;
	}
}

This helped dispose of the images and the gesture recogniser quickly enough and helped me keep the memory usage at around 130 – 160 Mb, which is a great result considering that we started with 600 MB. The other pleasing part is that memory usage was very stable and no major peak were found. It fluctuates slightly when you move between pages, which is perfectly normal but it goes back to a steady level around 130 – 160 MB.

I hope you find this useful and please do check your Xamarin apps before you release or whenever you get the time, as these things are hard to see but they could bite you when you go to prod 🙂

Any device, any platform, one Microsoft

Only a few years ago you’d have been hard pressed to have mentioned the following four words in a single blog post where you weren’t arguing for / against a way of doing things: Microsoft, iOS, Android and development.

Unless you’ve been living under a rock you will no doubt have seen Microsoft’s announcement on their intent to acquire Xamarin, a business very much about cross-platform application development.

For those of us working in this space this has really been a case of
“what took you so long?” rather than “why?”.

So why should you care? Let me explore this for you…

Please note I don’t have any more insight than you in what the acquisition means. However, based on Kloud’s experience building real business and consumer solutions using Xamarin, I’m going to give you what I think it means to those of us who develop platform-specific applications.

Some background

Microsoft has been working independently of Xamarin to produce its own toolchain for cross-platform application development for the past few years. You’ll note the majority of these are about enabling solutions on any platform which, again, is very different to Microsoft of years gone by.

Portable Class Libraries (PCLs)
A great enabler that unlocks transportable .Net code. These are a big part of the success of Xamarin as they have allowed popular .Net libraries to be made available for use off-Windows, even prior to Microsoft open sourcing the .Net Framework.
https://msdn.microsoft.com/library/gg597391(v=vs.100).aspx

Visual Studio Tools for Apache Cordova
Cordova is a great tool for facilitating rapid delivery of cross-platform applications where you are prepared to forgo some aspects of native capability. If you have a bunch of web-centric developers then the foundation components for Cordova will seem very familiar. The Visual Studio tooling is some of the best you’ll find and is actively maintained.
https://www.visualstudio.com/en-us/features/cordova-vs.aspx
Azure – Mobile Apps, Notification Hubs & Mobile Engagement
Probably the most mature mobile back-end platform about. Integration with APNS and GCM just works and the quick-starts are a great way to dip your toes into mobile application development. The addition of Capptain in 2014 (now Mobile Engagement) bolstered this offering.
https://azure.microsoft.com/en-us/services/app-service/mobile/

Windows Bridge for iOS (formerly Project Islandwood)
There’s no denying iOS and Android are leading platforms, so how do you allow existing applications to run on Windows? You use a Bridge.
https://dev.windows.com/en-us/bridges/ios
Windows Bridge for Android (formerly Project Astoria)
This one’s an interesting one. Unlike the iOS Bridge, Astoria isn’t moving ahead. What happens here? We’ll have to wait and see, though no doubt Xamarin plays a part.
http://www.windowscentral.com/microsoft-officially-cancels-project-astoria-bridge-porting-android-apps-windows-10-mobile

So, C# is the future?

If you’re an experienced iOS and Android developers using Objective-C, Swift or Java you don’t need to drop everything you’re doing and pick up C#.

Chances are you aren’t particularly interested in it… but… you are in an extremely good position to pick up and run with development in this space using Xamarin and C#. Also, you can always import those native libraries you are already using anyway if you find a gap (which is unlikely).

C#’s syntax should not hold a lot of surprises for many iOS and Android developers, and as you already know a lot about the UI constructs on each platform you’re ahead of the pack. While it’s true that a C# developer can quickly deliver solutions using Xamarin, the nearer you get to the UI experience the more platform-specific knowledge you require, even if you leverage something like Xamarin.Forms.

APIs ahoy!

Existing C# developers also get benefits here as they can quickly build cross-platform solutions and only leverage specific skills for certain aspects of the applications (typically the UI). Write it once, deploy on any platform (where have I heard that before???) really comes true here in many cases.

Many great apps are let down by terrible APIs, either through poor performance or security. Imagine a world where your API implementation experts can also write the client libraries that will consume those APIs? C# and Xamarin unlocks this scenario.

But I already have an app for X

When I spoke about Xamarin at TechEd Australia 2013 the number one question I got after the session was along the lines of “I already have an native app on X, why would I use Xamarin?”

This is a fair question and to suggest that you simply re-implement the application in C# with Xamarin is not the answer you want to hear.

No doubt, though, you are eyeing at least one other major mobile platform in the market and wondering how your existing application can reach that platform.

You have two choices: go native or go cross-platform.

This is your sweet spot – go cross-platform. Eventually you will find a smaller incremental change will deliver you the same cross-platform application on your existing platform of choice.

Yeah, but a native app’s so much better

In the smallest of circumstances you may be right. As I said, Kloud has successfully built and deployed heavily used enterprise and consumer applications that I would dare you to pick as having been developed using Xamarin.

Xamarin has spent a lot of time documenting real-world use of their technology that I’d recommend you go and digest.

But it’s Microsoft!

Yes it is.

The one that has the leading productivity apps on iOS and Android platforms, supports Docker, has its own OpenSSH port, open sourced the .Net Framework, its JavaScript engine and works in the open on GitHub.

Microsoft’s strength has always been its understanding of the developer and the tools they need to do their work. Now with Xamarin you get this benefit regardless of your platform of choice.

Happy Days! 🙂

Google Cloud Messaging using Azure Notification Hub

The Xamarin team have provided a very helpful tutorial to get started with setting up Android notifications – I suggest using this to get the basic implementation working, and ensure you’re using the GcmRegistrationIntentService version, and avoid using the depreciated GCM Client.

To get a complete end to end solution up and running there is a fair bit of additional information required.  Here’s a guide for using Microsoft Azure Notification Hub.

Set up Google Cloud Messaging service

Log into the Google Developer Console (https://console.developers.google.com/), and if you haven’t done so already create a project for your application.

Once created make a note of the Project ID as this will be used in your application code.  When the application starts it will send the Project ID to Google to exchange for a device token.  This unique token is what will be used to target each device with a notification.  Be sure to check for a new token each time the application starts as it is subject to change.

Next step is to enable the Google “Cloud Messaging for Android” and create an API key:

GCM

Click credentials and create a new “Server Key” and make a note of it for later.  We’ll need it for when we set up the Azure Notification Hub, and also to test sending a notification.  Whist here you may want to think about how you’ll set up your dev/test/prod implementations as it’s a good idea to keep these separate.

Google_API_key

* the key used here is for dev purposes only!

Set up the Azure notification hub

Next step is to set up the Microsoft Azure Notification Hub.  Log into the portal and create a new App Service > Service Bus > Notification Hub.  As soon as the service is running you can configure the Google Cloud Messaging settings by entering the API key created in the previous step into the GCM API Key field.

Google_API_Key

Set up the Android code

Before you begin, make sure you add the following to your packages.config file:

<package id="Xamarin.GooglePlayServices.Base" version="25.0.0.0" targetFramework="MonoAndroid50" />
<package id="Xamarin.GooglePlayServices.Gcm" version="25.0.0.0" targetFramework="MonoAndroid50" />

For my implementation the client wanted to pop up a message when the customer is using the application as well as adding a message to the notification status bar. At the point of receiving the message I create a pending intent to display a message when the customer opens the app (by clicking the status bar message), and display a message if the application is open when the message is received.

public override void OnMessageReceived (string from, Bundle data) {

 Log.Info(TAG, "GCM message received");
	
 if (from == Constants.SenderId) // make sure we sent the message

 {
		
   try
	
   {
			
    var messageId = data.GetString ("account");
 // message ID		
    var message = data.GetString ("msg");
 // message body

    if (CurrentApplicationState.appIsInForeground)
        GcmMessaging.DisplayNotificationInApp();					
	
    // create a pending intent to display to the customer at a later date

    CreateSystemNotification (message, messageId);

		
   }
		
   catch (System.Exception e)

   {

    Log.Debug (TAG, "Error displaying message: " + e);
   }

  }

}

When a message has been received the following code is used to create the pending intent, which will fire when the user selects the notification from the Android notification status bar. For this notification I have chosen to display a message that can be expanded when the user selects it. The other important point here is the messageId is used when displaying the notifications. This ensures a unique notification will be displayed for each account in the status bar. If a notification is delivered with the same ID, then it will replace the existing one.

private void CreateSystemNotification (string message, int messageId) {
  
  Notification.BigTextStyle textStyle = new Notification.BigTextStyle ();
  textStyle.BigText (message);

  var intent = new Intent (this, typeof(MainActivity));
  intent.AddFlags (ActivityFlags.SingleTop);
  intent.AddFlags (ActivityFlags.ClearTop);

  var pendingIntent = PendingIntent.GetActivity (this, 0, intent, PendingIntentFlags.UpdateCurrent);

  var notificationBuilder = new Notification.Builder (this)
   .SetSmallIcon (Resource.Drawable.app_notifications_status_bar)
   .SetContentTitle (ApplicationInfo.LoadLabel(PackageManager)) // app name
   .SetContentText (message)
   .SetAutoCancel (true)
   .SetContentIntent (pendingIntent)
   .SetLargeIcon (BitmapFactory.DecodeResource (Resources, Resource.Drawable.agl_launch_icon))
   .SetSound (RingtoneManager.GetDefaultUri (RingtoneType.Notification))
   .SetStyle (textStyle);

  _notificationManager = (NotificationManager)GetSystemService (Context.NotificationService);
  _notificationManager.Notify (messageId, notificationBuilder.Build ());
}

To keep track of whether the application is in the foreground I use the following:

public static class CurrentApplicationState

{

 private static bool _appIsInForeground;
	
 public static bool appIsInForeground
	
 { 
		
  get { return _appIsInForeground; } 
		
  set 
		
  { 
			
    _appIsInForeground = value; 
		
  } 
	
 }
}

And I call this from my base application:

protected override void OnPause () 
{
	
 base.OnPause ();
	
 CurrentApplicationState.appIsInForeground = false;

}


protected override void OnResume ()
 {
	
 base.OnResume ();
	
 CurrentApplicationState.appIsInForeground = true;


}

In order for a user to receive notifications on his/her Android device they’ll need to have Google Play installed. There is no way of avoiding this as we are using the Google Cloud Messaging service! This code can be used to detect if Google Play is installed and on the latest version:

public static bool IsGoogleServicesAvailable ()
{
	
 GoogleApiAvailability googleAPI = GoogleApiAvailability.Instance;
	
 int resultCode = googleAPI.IsGooglePlayServicesAvailable (Context);
	
 if (resultCode != ConnectionResult.Success) 
	
  {
		
   return false; // There is an issue with the Google Play version installed on the device
	
  }

	
 return true;
}

Using this implementation you’re relying on Google to provide the messaging. I choose not to inform the customer at this point as the message from Google is fairly blunt. As you can see below it mentions the application won’t run without updating Google play which is not strictly true, as it will run fine! Instead I pop up a message at the point in which they configure the notification service, which happens much deeper in the app than the main activity!
Google_error

Using the simulator

If, like me, you find it easier to use the Xamarin Android emulator for debugging you’ll need to install Google Play before you can test notifications on the simulator.  Download the Gapps package from the following website: http://www.teamandroid.com/gapps/. Simply drag the zip file into the emulator window (this works on a Mac, I’m not sure about Windows?) and follow the on screen prompts to install Google Play.

Log in with a Google account and you’re ready to test your notifications!

Testing the service

In order to make sure things are running as expected you can send a test notification.  There are a number of ways to do this but my preference is to use Postman (the Chrome extension) with the following settings:

POST /gcm/send HTTP/1.1
Host: gcm-http.googleapis.com
Authorization: key=[YOUR API KEY]
Content-Type: application/json
Cache-Control: no-cache

And the body of the POST request:

{ 
   "type": "android", 
   "data": { 
     "title": 
     "This is the title of the message", 
     "message": "You have been served, from the Google Cloud Messaging service.", 
     "account": 123456789 
    }, 
    "to" : "eD4ceBas2SN3:APA93THISchdsISsasdNOTqwe9asczAasd98EHsdREALasd0c+KEYv0kx50GZPsyc3ah6_eyvur-wvwVQe6Lfbv5ICijBfYOCkujQK271sK-RmxTe-Y_Aofx1RCe7yfnYgK7MEL7xgqY"
}

Image below for further clarity!

Postman_settings

Or if you prefer you can also log into Azure and send a notification from there. In order to send a message to a specific device you will need to set up a server side implementation and then target a device using the “Send to Tag” option.  As I only have 1 device activated I can choose Random Broadcast and it will send an alert to my test device.

Screen Shot 2015-11-08 at 20.43.21

Summary
Hopefully this will have provided a good taster on how to set up Google Cloud notifications on Android using Microsoft Azure notification hub. In order to target specific devices you’ll need to create a server side API to maintain a dataset of devices and associated tokens. Hopefully if time permits this will be the subject of a future post!

If you’re looking for more information, I found the following sites helpful when setting this up:
The Xamarin Android notification guide: https://developer.xamarin.com/guides/cross-platform/application_fundamentals/notifications/android/remote_notifications_in_android/
Google Cloud Messaging docs: https://developers.google.com/cloud-messaging/

Taking Advantage of The (iOS 9) Universal Links on Xamarin iOS apps

What is Scheme URI?

In the context of mobile apps, Scheme URIs are used for communicating between mobile apps. Mobile developers can register a unique URI for each app in the application manifest (info.plist). The operating system would then use that to launch your application once the user clicks on a link that matches your uri. For instance, I could have my-cool-app:// as my scheme uri. I could then generate links (should start with my-cool-app://) to send in my email to my app’s users and once clicked, my app will be launched. These have become standard and they are widely supported on iOS, Windows, and Android.

What is Universal Links?

Universal Links is a new feature that was introduced by Apple in iOS 9. The idea is instead of registering a scheme Uri, you could use your own website domain name (which is inherently unique) and associate this domain name with your mobile app. Once the user clicks on a http/https link that links to your domain name, iOS would then launch your mobile application instead of opening the link in Safari. More details about Universal Links could be found in in this WWDC session and Apple’s official documentation.

Why Do we need Universal Links?

If you have used Scheme URIs before to open your mobile apps, you would know the pain of trying to keep your links valid to open your app (when installed) and fallback to the web links when your app is not installed. You would also know this was not a simple task, and there was no guarantee that this would work exactly the way you want. Therefore, Apple has introduced Universal Links, which is great. Imagine how many times you get a URL link via email and you click it to end up in a web browser asking you for username and password. Most people do not remember their accounts (at least not for all accounts), or they want to see this content on the mobile app instead of Safari. This new feature (Universal Links) solves this problem.

How Can we Enable Universal Links?

To enable Universal Links, you need to follow the following steps:

1. Enable “Associated Domains” on your Application Id (in Apple Developer portal).

Enable Associated Domains in your App Identifier settings - Apple Dev Portal

Enable Associated Domains in your App Identifier settings – Apple Dev Portal

2. Create an apple-app-site-association file on your domain. This is just a text file that contains a JSON object to describe your universal links. You could associate multiple link paths with multiple apps. Notice that your app id needs to have your full app identifier (TeamName.Appid). I’ve shown a sample of the JSON content below:

    {
        “applinks”: {
            “apps”: [],
            “details”: [
                {
                    “appID”: “ABC-Team-Id.com.my.bundle.id“,
                    “paths”: [ “/”, “*” ]
                }
            ]
        }
    }

This file needs to be served over HTTPS and have no file extension – it must be named “apple-app-site-association”. Apple will try to retrieve this file from your domain before it launches your app for the first time. This is to verify the authenticity of your domain ownership before starting the app. If you are hosting this file on an Azure Web App, you might also need to add a static content mapping in your web.config.

The bottom line is you need to make sure that you can navigate to this file as https://your-domain.com/apple-app-site-association. There is also a small app that helps you verify your Apple association file, you could find it here. Do not worry about the last 2 errors that it displays concerning signing your file. I have my Universal Links work without signing the association file, but this web page is still good to verify other aspects of the association file.

3. Add the Universal Links Entitlement to your info.plist. This can be done very simply by navigating to your Entitlements.plist and add the new applinks as follows:

Applinks in Entitlments-plist file

Applinks in Entitlments-plist file

4. Regenerate your provisioning profiles. This is very important since we changed our app id entitlements. If you don’t do this you will get an error message when trying to build the app saying that you have entitlements that are not permitted by your provisioning profile.

5. OPTIONAL: Override ContinueUserActivity method in your app’s delegate to capture the URL link that the user clicked on. This is necessary when you want to take the user into the particular screen in your application. For instance, if the user clicked on a link to view a product on your website, you could capture the link in this method and once your app opens up, view the details of that product on your mobile app.

public override bool ContinueUserActivity (UIApplication application, 
     NSUserActivity userActivity, 
     UIApplicationRestorationHandler completionHandler)
{
	Console.WriteLine ("ContinueUserActivity method has been called...");
	// you can get the url that the user clicked on here.		
	return true;
}

Once all the above is done, you can build and deploy to your device. I have tested my implementation by creating a link to my associated domain and sent it via email to the device. When I click on the link, I get redirected to my app directly (without going through Safari).

Applinks in the mobile app - screenshot

Applinks in the mobile app – screenshot

Notice that Apple give the user the option to stay on my app, go directly the browser (upper right link) or go back to the email that launched my app. I really like this design because it keeps the user in charge. Also, there are few posts that suggest once the user taps on the link to go to the browser, Apple would then bypass your app for this link and take the user directly to the website in the future. I have not verified this but you could find the details on this Stackoverflow post.

How about devices that are still using older versions of iOS?

What we have seen above is very cool stuff and I have been hoping for this for years. However, this only solves the problem on a subset of devices. Remember there are still lots of devices out there that are not using iOS 9. If you are like me and are required to support iPhone 4, then you need to have a fallback mechanism for these devices. For this scenario, we could have simple JavaScript code that helps us redirect to our mobile app, if this redirection fails, then we assume that the app is not installed and we redirect the user to our web URL. A sample of this is below, and more details can be found on Stackoverflow:


// this could needs to sit in your website page
setTimeout(function() {
  window.location = "http://my-domain-app"; // or your could put  link to your app on iTunes
}, 25);

// If "my-cool-app://" is installed the app will launch immediately and the above
// timer won't fire. If it's not installed, you'll get an ugly "Cannot Open Page"
// dialogue prior to the App Store application launching
window.location = "my-cool-app://";

Future-Proofing

It will be very interesting to see how Apple will use this to integrate apps more with the web. Apple has already done a great work in terms of search and user activity that is bridging the gap between web and native apps. Universal Links is another step in the right direction.

How about Android?

Although most of the contents of this post is related to iOS, Android’s implementation is quite similar. Google introduced this in Android M and you can read more about it on the Android developer documentation site.

Solving self signed certificate blocking by inspecting web requests using Xamarin iOS

In iOS 9 Apple have turned on App Transport Security (ATS) as default. So if your iOS application is connecting to an insecure url resource then you’re out of luck as it will be blocked, an example of the most likely culprit is viewing a webpage without SSL encryption.

With the current application I’m working on I ran into trouble whilst loading a dev resource only to find it was using a self signed certificate and being blocked by the OS. I also had a requirement to inspect an Ajax web request and the WebView ShouldStartLoad delegate was not receiving these request callbacks.

First things first, if your applications requests are being blocked you will see something like:

NSURLSession/NSURLConnection HTTP load failed (kCFStreamErrorDomainSSL, -9802)

The best way to resolve this issue is to ensure all resources are securely protected in the correct way, and therefore your application, and users data, is secure!

But this is not always possible!  And if you’re like me then you have no choice but to step around the default ATS setting.

Quick, change the Info.plist!

To resolve a problem with a blocked resource you can turn off ATS for you application with a single entry in your Info.plist file. Whilst this is the simplest and quickest approach, my advice would be to avoid doing this. Yes, you may just be making the change for a quick test or prototype app, but it’s easy to forget you made the change and before you know it you’ve released an insecure app to your users.

My advice is to turn off ATS for the only resources you trust. In my case a single domain.

This can be achieved by adding the following into your Info.plist file:

<key>NSAppTransportSecurity</key>
	<dict>
		<key>NSExceptionDomains</key>
		<dict>
			<key>[ENTER YOUR BASE URL HERE]</key>
			<dict>
				<key>NSTemporaryExceptionAllowsInsecureHTTPLoads</key>
				<true/>
				<key>NSIncludesSubdomains</key>
				<true/>
				<key>NSAllowsArbitraryLoads</key>
				<true/>
			</dict>
		</dict>
	</dict>

Spying on all requests

iOS is no longer blocking my webpage but we need a way to listen in to all requests our web view is making so we can work our magic with trusting the self signed certificate (remember this part is for dev releases only and not production).

Start by creating a new class and have it inherit from NSUrlProtocol.  Then override the default delegate methods so that we can add our custom logic.

[Export ("canInitWithRequest:")]

public static bool canInitWithRequest (NSUrlRequest request)
{
   Console.WriteLine (String.Format ("URL # { 0}. Loading URL: { 1}", counter.ToString(), request.Url.ToString()));
   
   counter++;

   if (CustomNsUrlProtocol.GetProperty(MY_KEY, request) == myObj)
   {
      return false; // request has already been handled	
   }

   return true;
}

Here we get the opportunity to check all requests before they are loaded, and make a decision if we need to do something clever or not.  The default behaviour here is to return ‘true’ which means we need to do something.  So let’s do something…

public override void StartLoading ()
{
   // start loading the URL now we have handled it
   new NSUrlConnection (Request, new CustomNSUrlConnectionDataDelegate (this, new NSUrl(Constants.baseUrl)), true);
}

The clever part is to create a new instance of a NSUrlConnectionDataDelegate and use this delegate to inspect the certificate of each request.

Finally we just need to tell our custom protocol that we have now dealt with this request and we do not want to see it again.

public override NSUrlRequest Request
{
   get {
         NSMutableUrlRequest mutableRequest = (NSMutableUrlRequest)base.Request.MutableCopy ();
         CustomNsUrlProtocol.SetProperty (myObj, MY_KEY, mutableRequest);
         return mutableRequest;
   }
}

We’ve assigned an object to our request.  Now when it attempts to load, via canInitWithRequest, it will recognise that we have already dealt with this request and the browser will continue to load the request as normal.

On to the magic

So far you’ve probably noticed we haven’t actually done anything with our requests other than inspect them and assign an object to say we have done so.

Create a class that inherits from NSUrlConnectionDataDelegate and override CanAuthenticateAgainstProtectionSpace.  This method will be called if we receive an authentication for any of the requests we pass if from our NSUrlProtocol.

public override bool CanAuthenticateAgainstProtectionSpace (NSUrlConnection connection, NSUrlProtectionSpace protectionSpace)
{
   #if DEBUG || TEST
      if (protectionSpace.AuthenticationMethod.Equals (Foundation.NSUrlProtectionSpace.AuthenticationMethodServerTrust))
         return true;
      return false;
   #else
      return false;
   #endif
}

The default value we return is false which means we will not authenticate against any insecure connections.  However, if we receive a challenge and we are running in the development or test environment then we return true as this is something we want to handle.

Finally I use the delegate ReceivedAuthenticationChallenge to trust the request.

public override void ReceivedAuthenticationChallenge (NSUrlConnection connection, NSUrlAuthenticationChallenge challenge)
{
   var baseUrl = new NSUrl(Constants.baseUrl); // this is the base URL we trust

   // check we trust the host - an additional layer of security
   if (challenge.ProtectionSpace.Host.Equals (baseUrl.Host))
   {
      challenge.Sender.UseCredential (new NSUrlCredential (challenge.ProtectionSpace.ServerSecTrust), challenge);
   }
   else
   {
      Console.WriteLine ("Host not trusted: " + challenge.ProtectionSpace.Host);
   }
}

A quick check to ensure the URL is from a webpage I trust, and if so I provide my own credentials and reload the connection.  Re-run the application and if all goes well there will be a heap of URLs written to the debug log as they are ‘taken care of’ and the page will load as normal.

As always, leave a comment below if you have a question.  A sample project with the complete working code can be downloaded from here.

If you’re after more information or want to introduce more control over your request loading then I recommend this page as a starting point: https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/URLLoadingSystem/Articles/AuthenticationChallenges.html

Azure Applications Insights for Xamarin iOS

Azure Application Insights (AI) is a great instrumentation tool that can help you learn about how your application is doing during run-time. It is currently in Preview mode, so bear that in mind when developing production ready apps. It gives you the ability to log lots of different kinds of information like tracing, page views, custom events, metrics and more.

Azure AI supports multiple platforms, but unfortunately they have not released a Xamarin package yet. There is one library which is for Xamarin.Forms since it uses the DependencyResolver. I have taken that and removed that dependency to make it compatible with Xamarin.iOS. You could do the same thing to use it for Xamarin.Android too if you like.

It’s very simple to use, all you need is your instrumentationkey which you can get from your Azure portal. Follow the steps from the MSDN tutorial as you can see here to create the Azure AI instance and get your key. Once done, you could download and reference the repository that I have created on GitHub, as you can find it here.

To start Azure AI on your Xamarin iOS app, you could do:

    
	AzureAIManager.Setup();

	AzureAIManager.Configure("my-user-or-device-name");

	AzureAIManager.Start();

The implementation of the AzureAIManager is as follows:


	public static class AzureAIManager
	{
		public static void Setup(string appKey = "your-azure-AI-instrumentation-key")
		{
			AI.Xamarin.iOS.ApplicationInsights.Init();

			var ai = new AI.Xamarin.iOS.ApplicationInsights ();
			ApplicationInsights.Init (ai);

			TelemetryManager.Init(new AI.Xamarin.iOS.TelemetryManager());
			ApplicationInsights.Setup(appKey);

		}

		public static void Start()
		{
			ApplicationInsights.Start();
		}

		public static void Configure(string userId = "" )
		{
			ApplicationInsights.SetAutoPageViewTrackingDisabled(true);

			if (string.IsNullOrEmpty(userId))
				ApplicationInsights.SetUserId(userId);
		}

		public static void RenewSession()
		{
			ApplicationInsights.StartNewSession();
		}
	}

I have not put this as a Nuget package because I am sure Microsoft will release one very soon, so until that happens, you can use this bindings to play around with Azure AI and you could even use it on your small projects.

Xamarin Plugins

Cross-platform NuGet Packages

Xamarin Plugins are a special kind of NuGet package that let you easily add cross-platform functionality to your apps. Using NuGet to distribute Plugins means that anyone can create them, and of course consume them. The platforms supported by Plugins include Android, iOS, iOS Unified (64bit), Windows Phone 8, Windows Phone 8.1 RT and Windows Store.

Plugins abstract common device functionality or expose cross-platform APIs via a single interface

Plugins are small, have few or no dependencies, and provide a simple mechanism for accessing a single device function or feature. The following list represents some of the features you would expect to find on modern mobile devices.

  • GPS
  • Network Access
  • Battery Status
  • Vibration
  • Camera / Media
  • App cache
  • Speech-to-text

The aim of a Plugin is to expose one such feature using a singleton object (via an Interface) that hides the platform specific implementation on all platforms.

This approach in synonymous with using Inversion of Control (IoC) or Dependency Injection (DI) to invoke platform specific code from a shared project or a Portable Class Library (PCL).

Plugins Aren’t Components

… but they can be by following the Component creation and publishing guidelines.

A Xamarin Component gives developers the opportunity to distribute cross-platform libraries together in one neat package. When you add a Component to your Xamarin mobile project the correct platform implementation is automatically installed. Components are deployed by Xamarin and must be officially approved.

Plugins vs. Components

  • Components are normally used to offer cross-platform functionality at the UI level
  • Components typically integrate deeply into each platform they target

The above differences usually result in Components with diverging API implementations on each platform. As a consequence the use of the API becomes tightly coupled to each platform. In addition, very few Components target all of iOS, Android and Windows. Plugins, on the other hand, strive for a true cross-platform offering through one common API.

Plugin Development & Deployment

Plugins can be created by anyone and are a third-party driven part of the Xamarin ecosystem. Plugins do not need to be reviewed or approved by Xamarin.

In order to build a Plugin you will need Visual Studio and a business license of Xamarin (use a fully featured 30 day trial if you’re new to Xamarin). If you want to create and support your Plugins but have no intention to build and distribute apps, then you can apply for a special free license of Xamarin.

Publishing will require a NuGet user account. Alternatively an organisation can create an internal repository to host their cross-platform Plugins privately. However, if you do intend to contribute back to the Xamarin Community then ensure you publish your Plugin under an Open Source (OSS) friendly license like MIT.

Walkthrough

Many Plugins have already been published so definitely checkout the packages repository at nuget.org just in case your Plugin idea has already been developed. Alternatively you can view the Plugins offered in the Xamarin Component store.

Cross-platform “App Version” plugin

It’s common in almost every app to show the current version. Each platform uses a different approach for storing and retrieving this information, so abstracting this simple feature with a Plugin makes sense.

Quick Setup

  • Check your NuGet Package Manager is up to date. Ensure minimum version 2.8.3
  • Download and Install the Xamarin Plugin Template for Visual Studio
  • Create a project using the new Plugin template. The name of the solution needs to be simple because it will used throughout the Plugin code structure as a prefix and suffix for classes and file names.

ScreenShot1

With all projects created and initialized the screen shot below shows what your solution structure should resemble. Each platform being targeted has a corresponding project, with two additional portable (PCL) projects needed to complete the Plugin architecture.

ScreenShot2

The project called Version.Plugin.Abstractions is where we need to define the common API Interface. If you expand this project’s file structure you will see that an empty Interface has already been created for you by the template. For this walkthtough our interface is called IVersion.

At a minimum this Plugin needs to return the app’s version as a string, so we’ll add a getter property to our API.

///
/// Interface for Version
///
public interface IVersion
{
    ///
    /// Current App Version
    ///
    string Version { get; }
}

That’s it. With our simple API defined we just need to create concrete implementations for each targeted platform. When the template created each platform specific project, it added an implementation class with the name of your Plugin as the prefix.

IVersion for iOS implementation

// ./Version.Plugin.iOS/VersionImplementation.cs
public class VersionImplementation : IVersion
{
    readonly NSString _buildKey;
    readonly NSString _versionKey;

    public VersionImplementation()
    {
        _buildKey = new NSString("CFBundleVersion");
        _versionKey = new NSString("CFBundleShortVersionString");
    }

    ///
    /// Returns the app version with build number appended
    ///
    public string Version
    {
        get
        {
            var build = NSBundle.MainBundle.InfoDictionary.ValueForKey(_buildKey);
            var version = NSBundle.MainBundle.InfoDictionary.ValueForKey(_versionKey);
            return string.Format("{0}.{1}", version, build);
        }
    }
}

IVersion for Android implementation

// ./Version.Plugin.Android/VersionImplementation.cs
public class VersionImplementation : IVersion
{
    ///
    /// Returns the app version
    ///
    public string Version
    {
        get { return GetPackageVersion(); }
    }

    static string GetPackageVersion()
    {
        try
        {
            return Application.Context.PackageManager.GetPackageInfo(
                Application.Context.PackageName, PackageInfoFlags.MetaData).VersionName;
        }
        catch
        {
            return string.Empty;
        }
    }
}

The other platform implementations can be found in the sample code along with apps for testing each one.

CrossVersion Class

Using the API is the same on each platform. Example,

var version = CrossVersion.Current.Version;
Debug.WriteLine(version);

As you can see the name of the class that exposes the API has the Plugin name as a suffix. This is the standard naming convention for accessing all Xamarin Plugins. For example, a cross-platform Plugin for “battery status” would be accessed with a CrossBattery class.

The CrossVersion class is located in the PCL called Version.Plugin. You may have noticed this class file is also linked into all of the platform specific projects. This simple yet powerful class ensures the correct IVersion implementation is loaded at runtime because it’s compiled into each assembly.

public class CrossVersion
{
    static readonly Lazy Implementation = new Lazy(() =>
        #if PORTABLE
        null,
        #else
        new VersionImplementation(),
        #endif
        System.Threading.LazyThreadSafetyMode.PublicationOnly);

    public static IVersion Current
    {
        get
        {
            var version = Implementation.Value;
            if (version == null)
            {
                throw new NotImplementedException(
                    "Don't use CrossVersion from your PCL without first installing the NuGet package in your main project first.");
            }
            return version;
        }
    }
}

NuGet Deployment

Packaging

Download NuGet.exe and add it to your solution root folder. This executable will be used via the command prompt.

ScreenShot3

NuGet.exe needs a specifications file in order to package your assemblies correctly. Add a NuSpec file to the solution and fill in appropriate details. The Plugin template installed a new file type allowing you to add one with most of the details filled in.

ScreenShot4

ScreenShot5

Make sure you fill in these required fields,

  • id
  • version
  • title
  • owners
  • authors
  • license and project urls
  • descriptions

ScreenShot6

From a command prompt switch to the Plugin root folder. Set your NuGet account key, which can be found on your NuGet account profile page.

nuget setapikey xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx

Ensure your project configuration is in release mode and rebuild the solution. Then from the command prompt run the NuGet package command.

nuget pack Version.Plugin.nuspec

The output of this command is a NuPkg file with all of your Plugin assemblies packaged together.

ScreenShot7

Testing

Before releasing the package to the public you’ll need to test it throughly. The best way is to create a test app project and install the Plugin with the NuGet package manager. Via the package manager settings, add another source location for the package manager to search.

ScreenShot8

The source path will be the root folder of your Plugin.

ScreenShot9

Check the Plugin installs correctly and the implementation works as expected.

ScreenShot10

Publishing

Once you’ve fully tested the Plugin package, use the command prompt and your account key to publish.

nuget push Xam.Plugin.Version.1.0.0.0.nupkg xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx

Let’s Hack It: Securing data on the mobile, the what, why, and how

Our solution to secure the mobile app data

Our solution to secure the mobile app data. It uses open source libraries and took a very minimal effort to implement

Here is the presentation of tonight’s talk. It was great to see so many passionate developers and business people at Melbourne Mobile. I have embedded the slides below and I hope you find it useful.

Talk Summary

This presentation is basically a summary of what I have learned and the experience I have had going through my recent project. In trying to secure the users data on the mobile device, I have come to learn quite few common flaws in the security implementation, I have learned more reasons why you need to protect the data on your mobile app, and have come to know and use few useful open source projects. I share my experience from this project hoping that it would help you gain some insight and protect your mobile app data easily.

I said in the presentation that you could start securing the app data by a couple of lines of code and I do mean it. In fact, if you use SQLCipher, then you could do that by only changing one line of code :). I have put the links to all my reference and the libraries I have used at the end of the slides.

Let's Hack It Presentation

Let’s Hack It Presentation

Finally, just in case you do not like Prezi, here is the slides as a PDF file:
Let’s Hack It, the presentation as PDF

Announcing KeyChain.NET: a unified API for using KeyChain on many platforms

Storing and accessing private keys and passwords can be a tricky task. How far do you need to go to protect your (and the user’s) data? This is where KeyChain on iOS comes in handy. It allows you to store keys in a (arguably) secure database. This has seen great improvements since iOS 8 and iOS devices (since iPhone 5S) equipped with a special A7 chip designed particularly for holding your keys. More on iOS KeyChain can be found on Apple’s website here. Android, on the other side has its KeyStore, which also gives you some level of protection, but leaves a major part of the implementation to your (the developer). Details of Android KeyStore can be found on Android SDK here.

While working on recent projects, I found myself needing to have a unified way of accessing the KeyChain on both platforms. I implemented the generic library and it’s been working very well, so I thought it would be nice to share the love with the community, so here it comes 🙂

KeyChain.Net offers developers a unified, simple-to-use api for storing, accessing, and deleting keys from the keyChain (or KeyStore). It also offers further customisation capabilities based on what the platform supports. For instance, iOS KeyChain supports seamless sync (of your private keys) with other iOS devices using iCloud. This can be achieved using KeyChain.Net by turning ON the autoSyncToiCloud setting.

The package is open source and it is hosted on GitHub here. Currently, I am supporting Xamarin iOS and Xamarin Android. I might add Windows Phone depending on the feedback I get.

Keychain nuget package

Keychain nuget package

The library can be found on Nuget here. I have put some sample code on the read.me file on GitHub, and you could also look at the unit tests for information on how to use it. Tests are also available on Github.

Feel free to fork the repo on github and use it in any way you like or simply pull the nuget package to your project and enjoy it :). I would appreciate all feedback and if you have any issues or feature requests then please log them on Github.