Monthly Archives: January 2020

The step by step set up of Media Plugin for Xamarin.Forms!

Let’s properly set up Media Plugin (Xam.Plugin.Media) for Xamarin.Forms, harnessing the full capabilities with an optimized implementation! 😀

This is a continuation from my previous blog post, Behold the check-list of Media Plugin set up for Xamarin.Forms! where I shared the list of important bits you need to focus on when setting up the Media Plugin.

So here I’m building up on that and compiling a step by step guide implementation of the Xam.Plugin.Media for Xamarin.Forms, with the latest updates!

Backstory…

During my recent implementation with the Media Plugin for Xamarin.Forms, I realize that there are some new updates to this Plugin and its dependent Permission plugin that are not documented properly out there!

So I thought of writing up a new article with those updated bits and a better implementation with this library in a proper manner to harness the best of its performance and features without running into accidental bugs! 😉

Media Plugin – Xam.Plugin.Media!

Xam.Plugin.Media is the free Plugin Library by James Montemagno, that allows us to easily interact with Capturing Photos and Video and accessing them from the device Galley using Xamarin.Forms! So this library provides two main functionalities,

  • Capture Photos/Videos from Camera
  • Pick Photos/Videos from Gallery

Apart from that it allows you to Crop, Compress Photos, Set Custom Sizing and Quality, Save to Albums, and etc. It fully supports Android, iOS, UWP (Windows), and even Tizen device platforms. Quite an awesome library for sure!

Github: https://github.com/jamesmontemagno/MediaPlugin
Nuget: http://www.nuget.org/packages/Xam.Plugin.Media

This library internally depends itself on Permissions Plugin (Plugin.Permissions) for taking care of the Permissions that are required to handle in each Native platform to access Camera features and device Gallery features.

Step by Step!

Alright then let’s take a step by step walk through of setting up Media Plugin in your Xamarin.Forms project from scratch!

1. Let the set up begin!

Assuming you have already created your Xamarin.Forms project, let’s begin by adding the Xam.Plugin.Media into your Project from Nuget Package Manager.

Lets search for “Xam.Plugin.Media” in Nuget and install the library for all the project nodes in your solution, Xamarin.Forms Host project, Android, iOS, and UWP (Windows) platform nodes.

2. Initialize()!

Then you need to set up the Initialization of the Media Plugin in the Xamarin.Forms layer, by calling up the Initialize() method preferably at the start up of the App.

If you’re using a Service instance to be used with Media Plugin, then you should set this is up in the Constructor of it.

Now let’s set up the configuration for all the platform projects one by one…

Let’s set up Android!

Let’s begin with the Android bits, which is the longest set of configuration.

1. Permissions in AndroidManifest!

by adding the Permission bits that are required for the Media Plugin. Simply go to Android Project -> Properties -> Click on “Android Manifest” tab -> scroll down to “Required Permissions” section…

Simply select those two Permissions, for Reading and Writing data to the device storage, in terms of Capturing Photos and Videos and saving them during run time.

You could even add them manually in the AndroidManifest.xml file.

<?xml version="1.0" encoding="utf-8"?>
<manifest ... >
    <uses-sdk ... />
    <application ... >
    ...
	<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
	<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
    ...
  </application>
    ...
</manifest>

Then again, unless you’re going to saving your captured Photos or Videos then no need to add the “WRITE” permission. So make sure to decide on your requirement.

2. Permission Plugin – OnRequestPermissionsResult()

Next we need to set up the call back for the Permission Plugin on the OnRequestPermissionsResult() method in your MainActivity.cs class.

on github: /XFMediaPluginDemo.Android/MainActivity.cs

Visual Studio 2019 adds the override of this method automatically to your MainActivity class, but if its not there you need to set up as shown above.

3. FileProviderfile_paths.xml

We need to set up the FileProvider path values in the file_paths.xml, so go ahead create a new folder called “xml” in your “Resources” folder, and add a new XML file called “file_paths.xml” with the following content.

on github: /XFMediaPluginDemo.Android/Resources/xml/file_paths.xml

Oh, and make sure the Build Action of that file is set to “AndroidResource” in Properties.

4. FileProvider in AndroidManifest!

Then let’s add the FileProvider definition in the AndroidManifest.xml

on github: /XFMediaPluginDemo.Android/Properties/AndroidManifest.xml

This should be added inside the <application> node.

5. Plugin.CurrentActity set up…

We need to set up the Plugin.CurrentActivity plugin for Media Plugin to attach itself to the active Activity during the run time. Nuget Package Manager -> install Plugin.CurrentActivity, only into your Android project node.

Now that’s installed we need to set it up in the code as well.

6. Plugin.CurrentActity Initialization!

First we need to create the MainApplication.cs class set up that inherits from Android.App.Application base for initializing the CrossCurrentActivity Instance up on the Activity change at run time.

on github: /XFMediaPluginDemo.Android/MainApplication.cs

Next we need to set up the init() call on MainActivity.cs class as well.

on github: /XFMediaPluginDemo.Android/MainActivity.cs

Here also we’re calling the Init() method of CurrentActivity plugin but this time we’re forwarding the Bundle parameter that’s passed into the OnCreate() method.

7. Hardware Requirement filter!?!

Now this is an optional step, once your app is published, and you want to Google Play store to make your app available only for devices that has the following features, “Camera”, “Camera with Auto Focus”, etc, then you need to add the following “UsesFeatures” attributes to your AssemblyInfo.cs file.

That concludes the Android project set up.

Let’s set up iOS!

The iOS set up is much easier actually where we only have to set up the permissions.

1. Permissions in Info.plist!

On your iOS project, right click on the Info.plist file -> Open With -> select XML (Text) Editor option, which will open up in the XML editor window as follows.

on github: /XFMediaPluginDemo.iOS/Info.plist

You need to add Permissions as shown here, with an appropriate description, which will be used to show to the User when the Permissions are being requested at run time. You need to explain what those Permissions are used for in your app.

<plist version="1.0">
<dict>
    ...
    ...
    <key>NSCameraUsageDescription</key>
    <string>This app needs access to the camera to take photos.</string>
    <key>NSPhotoLibraryUsageDescription</key>
    <string>This app needs access to photos.</string>
    <key>NSMicrophoneUsageDescription</key>
    <string>This app needs access to microphone.</string>
    <key>NSPhotoLibraryAddUsageDescription</key>
    <string>This app needs access to the photo gallery.</string>
</dict>
</plist>

But here also I’m reminding, set up only the Permissions that are absolutely required by your app’s functionality.

That concludes the iOS project set up.

Let’s set up UWP!

Well in UWP (Windows) project is even more easier to set up

1. Permissions in Package.appxmanifest!

Simply open up the Package.appxmanifest file in your UWP project -> Go to “Capabilities” tab -> Tick on “Webcam” option from the Capabilities list.

on github: /XFMediaPluginDemo.UWP/Package.appxmanifest

That concludes the UWP project set up.

Let the Xamarin.Forms, coding begin!

Now this is where we’re going to set up our implementation to use the Media Plugin in our Xamarin.Forms project host.

Doesn’t matter whether you’re going to implement in Page code behind or MVVM heavy ViewModel, we should maintain a clean decoupled structure as much as possible.

Pre-requisites!

So each feature we access we need to perform the following,

  • Check for the availability of the feature (ex: Camera, Gallery)

    Media Plugin provides these bool properties which allows you to check for the availability of the features you want to access, such as Camera, and Gallery. If they return true then it is safe to proceed with the call.
...
if (!CrossMedia.Current.IsCameraAvailable ||
		!CrossMedia.Current.IsTakePhotoSupported)
{
	await DisplayAlert("No Camera", 
              "Sorry! No camera available.", "OK");
	return null;
}
...
  • Check for the status of the Permission required (ex: Camera, Storage)

    This is another safety layer that is also recommended, checking the Status of the Permission before you access those features from Media Plugin. Based on it you can perform requesting Permission from the User during run time using the Permission Plugin that’s already set up in your project.
...
var cameraStatus = await CrossPermissions.Current.
			CheckPermissionStatusAsync(Permission.Camera);
var storageStatus = await CrossPermissions.Current.
			CheckPermissionStatusAsync(Permission.Storage);
var photosStatus = await CrossPermissions.Current.
			CheckPermissionStatusAsync(Permission.Photos);
...

Those two check ups are recommended as safety layers for smooth experience for the user and to avoid running into unexpected issues. Once those two calls are satisfied, then we can access the feature we need. 😉

It is best to have separate methods for each specific action, such as Capture new Photo or Select a new Photo from Gallery and those methods should return the resulting ImageSource object or default failure value.

Camera Feature – TakePhoto()

Here’s the method implementation that you can use to Capture Photo using the device Camera and return an ImageSource upon success.

public async Task<ImageSource> TakePhoto()
{
	if (!CrossMedia.Current.IsCameraAvailable ||
			!CrossMedia.Current.IsTakePhotoSupported)
	{
		await DisplayAlert("No Camera", 
                    "Sorry! No camera available.", "OK");
		return null;
	}

	var isPermissionGranted = await RequestCameraAndGalleryPermissions();
	if (!isPermissionGranted)
		return null;

	var file = await CrossMedia.Current.TakePhotoAsync(new 
        Plugin.Media.Abstractions.StoreCameraMediaOptions
	{
		Directory = "TestPhotoFolder",
		SaveToAlbum = true,
                PhotoSize = PhotoSize.Medium,
	});

	if (file == null)
		return null;

	var imageSource = ImageSource.FromStream(() =>
	{
		var stream = file.GetStream();
		return stream;
	});

	return imageSource;
}

You can easily use this for a Page behind code implementation or a Service layer implementation for Capturing Photos.

StoreCameraMediaOptions provides you with a whole bunch of features you can easily use to customize and resize the captured Photo within the library itself. 😀

Gallery Feature – SelectPhoto()

Here’s the method implementation that you can use to Select Photo using the device Gallery and return an ImageSource upon success.

public async Task<ImageSource> SelectPhoto()
{
	if (!CrossMedia.Current.IsPickPhotoSupported)
	{
		await DisplayAlert("Photos Not Supported", 
                   "Sorry! Permission not granted to photos.", "OK");
		return null;
	}

	var isPermissionGranted = await RequestCameraAndGalleryPermissions();
	if (!isPermissionGranted)
		return null;

	var file = await Plugin.Media.CrossMedia.Current.PickPhotoAsync(new 
        Plugin.Media.Abstractions.PickMediaOptions
	{
		PhotoSize = Plugin.Media.Abstractions.PhotoSize.Medium,
	});

	if (file == null)
		return null;

	var imageSource = ImageSource.FromStream(() =>
	{
		var stream = file.GetStream();
		return stream;
	});

	return imageSource;
}

In both above methods we are first checking the availability of the feature, and then the status of the permission, before we make the call to Media Plugin.

You can see that upon successful execution completion we’re returning the retrieved ImageSource, otherwise in any case of failure we return null. Also you can remove DisplayAlert() set up, if you’re using a Service layer, instead just throw an Exception which you can handle at the point of execution. 😉

Permission Checkup!

As you can see we have a method call to RequestCameraAndGalleryPermissions() which checks for the Permission status for the features we need to access, which implements as follows.

private async Task<bool> RequestCameraAndGalleryPermissions() 
{
	var cameraStatus = await CrossPermissions.Current.
	CheckPermissionStatusAsync(Permission.Camera);
	var storageStatus = await CrossPermissions.Current.
	CheckPermissionStatusAsync(Permission.Storage);
	var photosStatus = await CrossPermissions.Current.
	CheckPermissionStatusAsync(Permission.Photos);

	if (
	cameraStatus != PermissionStatus.Granted || 
	storageStatus != PermissionStatus.Granted || 
	photosStatus != PermissionStatus.Granted)
	{
		var permissionRequestResult = await CrossPermissions.Current.
		RequestPermissionsAsync(
			new Permission[] 
			{ 
				Permission.Camera, 
				Permission.Storage, 
				Permission.Photos 
			});

		var cameraResult = permissionRequestResult[Permission.Camera];
		var storageResult = permissionRequestResult[Permission.Storage];
		var photosResults = permissionRequestResult[Permission.Photos];

		return (
			cameraResult != PermissionStatus.Denied &&
			storageResult != PermissionStatus.Denied &&
			photosResults != PermissionStatus.Denied);
	}

	return true;
}

We’re check for Camera, Storage, Photos access permission status, which are required for Camera and Gallery access from the User in all the platforms. As you can see based on the existing status we request the Permission from user, and return the results. This will prompt the user with the popups asking for Permission to access. 😀

A better, Permission Checkup!

Just to make it more cleaner and decoupled, here’s an improved Permission check up method where you can pass in the exact Permission you need to check and it will take care of it. Oh and this is very much reusable for any kind! 😉

private async Task<bool> RequestPermissions(List<Permission> permissionList)
{
	List<PermissionStatus> permissionStatuses = new List<PermissionStatus>();
	foreach (var permission in permissionList)
	{
		var status = await CrossPermissions.Current.
		CheckPermissionStatusAsync(permission);
		permissionStatuses.Add(status);
	}

	var requiresRequesst = permissionStatuses
                                 .Any(x => x != PermissionStatus.Granted);

	if (requiresRequesst)
	{
		var permissionRequestResult = await CrossPermissions.Current.
		RequestPermissionsAsync(permissionList.ToArray());
		
		return permissionRequestResult
			.All(x => x.Value != PermissionStatus.Denied);
	}

	return true;
}

You simply have to pass in the Permission you want to check for as follows,

public async Task<ImageSource> TakePhoto()
{
	...
	var isPermissionGranted = await RequestPermissions
	(new List<Permission>(){ Permission.Camera, Permission.Storage }); 
	if (!isPermissionGranted)
		return null;
	...
}

public async Task<ImageSource> SelectPhoto()
{
	...
	var isPermissionGranted = await RequestPermissions
	(new List<Permission>(){ Permission.Photos }); 
	if (!isPermissionGranted)
		return null;
	...
}

You can pass in any kind of Permission type for check and request for Granted status.

Exception Handle!

You can see I’m not handling exceptions in here, that I would leave to the execution point of these methods calls.

try
{
	var result = await SelectPhoto();
	if (result != null)
		viewPhotoImage.Source = result;
}
catch (Exception ex)
{
	// handle your exception
}

This I believe the best way to handle any exceptions that could occur, could be in your ContentPage code behind or ViewModel. 😀

Main Thread!

Unless you’re calling these features of Media Plugin from a code behind Event handler, then you need to make sure this is executed on the app’s Main Thread.

https://theconfuzedsourcecode.wordpress.com/2020/01/27/behold-the-check-list-of-media-plugin-set-up-for-xamarin-forms/#Run-on-UI-Thread

If you ever run into any issues, make sure you have gone through my previous blog post: Behold the check-list of Media Plugin set up for Xamarin.Forms! which will definitely help you tackle any issues easily!

Well that sums it up the whole set up and a bit of under the hood check up!

Fire up the Demo!

So just for this article I created a simple demo that reflects all of this recipe of better implementation of Media Plugin for Xamarin.Forms!

Check it on my github: github.com/XFMediaPluginDemo

Side by side on Android, iOS, and UWP!

Conclusion

Following this guide you can easily implement the Media Plugin for Xamarin.Forms with a proper maintainable architecture! Although setting up might seem a bit tedious, its actually quite straight forward. Like I’ve shown in the code you need to handle Async Await calls properly and up to the UI Thread and exception handling.

Some of those bits that I have shared here aren’t mentioned in the plugin docs yet, since they’re out of date. So I really hope this helps you fellow devs!

Share the love! 😀 Cheers!

Behold the check-list of Media Plugin set up for Xamarin.Forms!

Let me share a check list for easily implementing the Media Plugin (Xam.Plugin.Media) for Xamarin.Forms with a peace of mind! 😉

Here I’m sharing some important bits that you need to focus on to avoid running into any obnoxious issues during run time of your Xamarin.Forms app!

Backstory…

Recently I was implementing Media Plugin library (Xam.Plugin.Media) in one of my Xamarin.Forms projects, even though I had implemented this before, I ran into some missing bits that caused some problems, so I had to Google them out.

So after resolving my implementation I thought of writing up this article to sum up a check list that you need to go through to make sure you’ve set up your project properly for the Media Plugin to work, hassle free, giving you a peace of mind! 😉

Media Plugin – Xam.Plugin.Media!

Xam.Plugin.Media is the free Plugin Library by James Montemagno, that allows us to easily interact with Capturing Photos and Video and accessing them from the device Galley using Xamarin.Forms!

Github: https://github.com/jamesmontemagno/MediaPlugin
Nuget: http://www.nuget.org/packages/Xam.Plugin.Media

There’s a little intro to the Media Plugin, then let’s jump right in!

Behold the check list!

It is quite straight forward how to set up Media Plugin with the guidelines of the official docs in github repo, but there are a few bits that you need to focus on as follows…

1. On Android: CurrentActivity Plugin!

You need to install Android CurrentActivity Plugin using the Nuget package manager, and properly set up the MainApplication Class set up. This used to be automatically set up during the installation from nuget but it doesn’t seem to be doing that so far, so you need to manually set it up yourself.

#if DEBUG
[Application(Debuggable = true)]
#else
[Application(Debuggable = false)]
#endif
public class MainApplication : Application
{
    public MainApplication
      (IntPtr handle, JniHandleOwnership transer)
      : base(handle, transer)
    {
    }

    public override void OnCreate()
    {
        base.OnCreate();
        CrossCurrentActivity.Current.Init(this);
    }
}

Also you need to initialize CrossCurrentActivity.Current instance in MainActivity.OnCreate() method.

public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity
{
    protected override void OnCreate(Bundle savedInstanceState)
    {
        ...
        
        base.OnCreate(savedInstanceState);

        CrossCurrentActivity.Current.Init(this, savedInstanceState);

        Xamarin.Essentials.Platform.Init(this, savedInstanceState);
        global::Xamarin.Forms.Forms.Init(this, savedInstanceState);
        LoadApplication(new App());
    }
    
    ..
}

2. On Android: Permission Plugin set up!

When you install the Xam.Plugin.Media it will come with the Plugin.Permissions library references inside it. For this to work properly on Android you need to make sure to set up its native handlers on Android in the MainActivity.OnRequestPermissionsResult() method override.

public override void OnRequestPermissionsResult(int requestCode, string[] permissions, [GeneratedEnum] Android.Content.PM.Permission[] grantResults)
{
    Xamarin.Essentials.Platform.
       OnRequestPermissionsResult
       (requestCode, permissions, grantResults);

    Plugin.Permissions.PermissionsImplementation.
       Current.OnRequestPermissionsResult
       (requestCode, permissions, grantResults);

    base.OnRequestPermissionsResult
       (requestCode, permissions, grantResults);
}

If you’re using Xamarin.Essentials already in your app or you’ve created your Xamarin.Forms Project recently with an update Visual Studio 2019, then OnRequestPermissionsResult() override should already exist in your MainActivity class. In that case just add the PermissionsImplementation.Current.OnRequestPermissionsResult(..) snippet to the method. Well I actually missed out on on this and I ran into some weird issues on Android.

3. On Android: FileProvider set up!

Make sure to set up the FileProvider in AndroidManifest along side the xml/file_paths.xml file in the Resources directory. One crucial point to keep in mind is that there are two ways you can set up the android:authorities value in the FileProvider.

  • android:authorities=”${applicationId}.fileprovider”
  • android:authorities=”com.example.android.fileprovider”

Sometimes it can be confusing when you are setting up this value, as shown above, either keep it as the first option as it is or the second option, with your app package name “<your app package name>.fileprovider” minted. For the clarity of it though I would suggest sticking to the first option as shown in the docs as well.

<?xml version="1.0" encoding="utf-8"?>
<manifest ... >
    <uses-sdk ... />
    <application ... >
    ...
    <provider android:name="android.support.v4.content.FileProvider"
                android:authorities="${applicationId}.fileprovider"
                android:exported="false"
                android:grantUriPermissions="true">
      <meta-data android:name="android.support.FILE_PROVIDER_PATHS"
                android:resource="@xml/file_paths"></meta-data>
    </provider>
    ...
  </application>
    ...
</manifest>

4. CrossMedia.Current.Initialize();

You need to make sure to initialize the Media Plugin before calling up any of its method functions. You can do this on Xamarin.Forms layer, or even in Platform Nodes, but preferably on the Page that you’re intending to use the plugin.

You should set it up on App.xaml.cs start up methods if you’re intending to use Media Plugin on multiple pages in your App.

public partial class App : Application
{
    public App()
    {
        InitializeComponent();

        Plugin.Media.CrossMedia.Current.Initialize();

        MainPage = new NavigationPage(new MainPage());
    }
}

If you’re abstracting it out to a Service instance, then you can call this up in the Constructor during instantiation as well.

5. Run on UI Thread!

Unless you’re calling up the Media Plugin’s functions in an Event Handler directly invoked by a UI Element, you need to make sure you’re running on UI Thread during the run time. Otherwise you could run into various kinds of issues since, since accessing Camera or Gallery relies heavily on Native IO operations.

Therefore make sure to run it on UI Thread, by either using default Xamarin.Forms UI Thread force invoke method, Device.BeginInvokeOnMainThread() as below,

Device.BeginInvokeOnMainThread(async () =>
{
	await Plugin.Media.CrossMedia.Current.TakePhotoAsync(...);
});

...

Or if you’ve got Xamarin.Essentials installed in your project, then you can use MainThread Helper it provides a neat way to check for the execution thread, and based on that force the execution on UI Thread,

if (!MainThread.IsMainThread)
{
    await Plugin.Media.CrossMedia.Current.TakePhotoAsync(...);
}
else 
{
    MainThread.BeginInvokeOnMainThread(() =>
    {
        await Plugin.Media.CrossMedia.Current.TakePhotoAsync(...);
    }); 
}

...

6. Perform Permission check up!

It is best perform a Permission availability check up for the features that you’re accessing from Media Plugin using the Permission Plugin, that’s referenced along with it. This is something that’s recommended in the Media Plugin’s docs as well, which you will find at the end though. But in my experience this is a crucial set up to have an extra assurance of the features you’re trying to access from Media Plugin.

Basically before each call to Capture or Pick any Photo/Video from the Media Plugin, you need to check for the availability of the Permission for Camera, Storage, and Photos. Initially as shown below…

private async Task<ImageSource> TakePhoto()
{
    ...
    
    var isAccessGranted = await RequestCameraAndGalleryPermissions();
    
    ...
}

private async Task<bool> RequestCameraAndGalleryPermissions() 
{
    var cameraStatus = await CrossPermissions.Current.
                CheckPermissionStatusAsync(Permission.Camera);
    var storageStatus = await CrossPermissions.Current.
                CheckPermissionStatusAsync(Permission.Storage);
    var photosStatus = await CrossPermissions.Current.
                CheckPermissionStatusAsync(Permission.Photos);
    ...

    // request access permissions

    ...
}

If they’re not Granted yet or denied you need to launch a request for them from the User during the run time. I must note that the github docs of the Permission plugin are outdated and doesn’t reflect the latest changes of the library. I will be sharing the full implementation of this code snippet later in this article.

7. Set up Required Permissions!

Some of those permission requirements you need to define in the device native configuration in Android -> AndroidManifest.xml, iOS -> Info.plist, and UWP -> Package.appxmanifest. This is well documented in the Media Plugin’s docs.

https://github.com/jamesmontemagno/MediaPlugin#important-permission-information

8. Set up Required Permissions! only!

Yes it’s better not to set up Permissions unless you absolutely need them, according to your requirement. Let’s say you’re only using the Media Plugin to access Gallery, then you don’t need to set up required Permissions for Camera, and data Write Access. This will also give an extra peace of mind for your Users as well. 😉

9. Re-usable code!

If your apps is going to be using Camera and Gallery usage all over the in multiple pages, then it’s better to implement a separate Service layer for it using the Media Plugin.

This will definitely come in handy when you’re dealing with a good MVVM architecture in your project solution. You can abstract out the required features into a Service instance, that’s best registered as a Singleton object in your IoC Container.

public MediaService : IMediaService
{
	public MediaService()
	{
		...
	}
	
	public async Task<ImageSource> CapturePhoto()
	{
		...
	}
	
	public async Task<ImageSource> SelectPhoto()
	{
		...
	}
	
	...
}

As an added extra you could have a Permission check up method, where you pass in the type of permissions you want to request from User unless already granted.

...
private async Task<bool> RequestPermissions(List<Permission> permissionList)
{
    ...
}
...

Well.. that’s basically the check list you need to go through when setting up Media Plugin in your Xamarin.Forms! 😉

Conclusion…

Even though its straight forward to set up the Media Plugin (Xam.Plugin.Media) for Xamarin.Forms, there’s a high chance you might miss something during the process and run into all kinds of weird issues during the run time, specially since there’s some platform specific bits to set up as well!

I’ve also shared some tips at the end for setting up the usage of it to cater for a better implementation. I might write up another post sharing a step by step guide for setting up all these bits in my next article! Until then, hope this helps!

Share the love! 😀 Cheers!

Building a bi-directional interop bridge with WebView in Xamarin.Forms!

Let’s build an advanced communication bridge into your Xamarin.Forms WebView, talk to it, and let it talk back to us at will!? 😉 lol Yes let me show you how to pass data from Javascript environment to C# .NET run time in the Web page rendered inside your Xamarin.Forms WebView!

I’m talking about building a bi-directional communication tunnel with HTML/Javascript inside your WebView in Xamarin.Forms yo! 😀 buckle up your seatbelts!

So in my previous article, Talking to your WebView in Xamarin.Forms! I talked about, how to build a uni-directional C# .NET to Javascript environment in Xamarin.Forms WebView.

WebView in Xamarin.Forms..

In this article I’m going to take another step forward and allow the same functionality to occur the other way around as well… We’re talking about a two-way invoking between .NET run time and javascript run time in a Xamarin.Forms WebView!

Unfortunately this cannot be done by default in WebView.

Behold, Hybrid WebView!

This right here is a bit more advanced extension of the WebView with a bit of Xamarin Native magic! 😉 In order to establish an invoke bridge directly from HTML Javascript sandbox that its running inside the WebView, out to the .NET runtime, we need something more natively handled in Xamarin!

Basically we’re going to implement a device native script handler for the WebView which is going to handle the bridging between the Javascript and the .NET runtime handshake, in return giving us the opportunity to invoke calls from javascript into the .NET run time the Xamarin.Forms is execution on! 😉

Well that’s a very simplistic explanation, but there’s a whole article about it on Microsoft Xamarin Docs, Customizing a WebView if you’re interested! Since its already there, I wouldn’t be going into complete details of it, rather I would be explaining the improved implementation I have done on top of it for the Hybrid WebView.

Over there it focuses on loading Embedded HTML content, but I will extend my implementation to support for dynamic HTML content, allowing you to handle javascript loaded from a Web Source and support even run time generated javascript.

Invoking C# from Javascript in the WebView!

In order to do this, in par with Xamarin.Forms WebView, we need to implement a Custom Renderer for WebView, which we will refer to as HybridWebView.

HybridWebViewRenderer will be created across all the native platforms we intend to use our HybridWebView, in Android, iOS and Windows native environments each equipped with its own javascript handler to build a bridge on to our .NET run-time. 😉

We access the native WebViewRenderer properties and basically implement a special handler to listen to a certain pre-defined Javascript method execution. In this method which we add into the javascript that is rendered inside the WebView, we will define the parameters we need to use, in that way we can pass any number of parameters and data types as we want.

We’re going to intercept the execution of this javascript method inside our Hybrid WebViewRender, and then redirect it on to the .NET method we’ve subscribed to. So in the Hybrid WebView definition we will have an Action method that we bind to in our Xamarin.Forms level which we will subscribe to wherever we’re using this magical bits! 😉

Let the coding begin!

Let’s begin with HybridWebView Control in Xamarin.Forms! Here we;re adding an Action that we will subscribe to in order to receive data from Javascript invokes inside the WebView rendered content.

HybridWebView

namespace XFWebViewInteropDemo.Controls
{
    public class HybridWebView : WebView
    {
        private Action<string> _action;

        public void RegisterAction(Action<string> callback)
        {
            _action = callback;
        }

        public void Cleanup()
        {
            _action = null;
        }

        public void InvokeAction(string data)
        {
            if (_action == null || data == null)
            {
                return;
            }
            _action.Invoke(data);
        }
    }
}

 

InvokeAction is the method that will be used by the Native Renderer object to direct the invokes from javascript executions. Using the RegisterAction we can dynamically register the Action we need to subscribe to.  You can add any number of parameters as you wish in here, but you need to make sure to handle them in the native renderer as well.

Native Renderers…

We’re going to build native renderers for each platform we’re targeting, Android, iOS, and UWP (Windows). Basically all the renderers follow the same basic concept as we discussed before, but each of their implementation is going to be different based on the platform.

We need to make sure to handle the subscribe and unsubscribe of the Element Native properties and events properly in the renderer’s OnElementChanged() event.

We’re going to inject the javascript method that we’re going to listen to in the renderers as following.

private const string JavaScriptFunction = "function invokeCSharpAction(data){....}";

 

We will be defining this in each renderer, according to the native platform. Every time a invokeCSharpAction() javascript method executes inside the WebView, it will get fetched by the Renderer and the following method call will occur.

((HybridWebView)Element).InvokeAction(value);

 

Up to the HybridWebView’s Action subscription on Xamarin.Froms run time, allowing our Action to fire up and retrieve the data coming in from javascript.

Alright now let’s get into details of each native renderer.

Android Renderer!

We’re going to use the Android’s WebViewRenderer to subclass our HyrbidWebViewRenderer.

github: /XFWebViewInteropDemo.Android/Renderers/HybridWebViewRenderer.cs

Like we discussed before for Android, we have the following script injection defined,

private const string JavascriptFunction = "function invokeCSharpAction(data){jsBridge.invokeAction(data);}";

 

For Android we need some extra bits of implementation, by creating a JavascriptWebViewClient that will set up listening to the execution of javascripts inside the WebView.

Then we have to create a JsBridge, which handles the interfacing with Javascripts, and fires up InvokeAction() method to redirect the execution flow up to the Xamarin.Forms level handlers.

Both those custom objects need to be set up in the HybridWebView in the renderer Element upon instantiation.

Control.SetWebViewClient
(new JavascriptWebViewClient($"javascript: {JavascriptFunction}"));
Control.AddJavascriptInterface
(new JsBridge(this), "jsBridge");

 

Once all that set up, and you build the Android project straight away, you might be getting a build error as following. (unless you’ve set this fix up before in your project)

Its caused by the JsBridge class we implemented with an Export attribute for the invokeAction method for our renderer, to export this into a native java method. So we need to add the Mono Android Export library.

You can fix this by going to Android Project -> References -> Add References -> Select Assemblies tab on the left panel -> tick on Mono.Android.Export Reference from the list of References.

Click Ok and rebuild, you’re all set! 😉

That’s pretty much it for the Android Renderer. Next on to iOS…

iOS Renderer!

For iOS we are going to use WkWebViewRenderer as the base renderer for our HybridWebView and in addition we have to implement IWKScriptMessageHandlder interface to handle the custom javascript execution monitoring that we target to handle.

github: /XFWebViewInteropDemo.iOS/Renderers/HybridWebViewRenderer.cs

We set up a WKWebViewConfiguration object in the constructor and we get access to the property WKWebViewConfiguration.UserContentController which allows us to set up our native bridge to Javascript execution firing up inside the WebView.

public HybridWebViewRenderer(WKWebViewConfiguration config) : base(config)
{
    _userController = config.UserContentController;
    var script = new WKUserScript(new NSString(JavaScriptFunction),
                   WKUserScriptInjectionTime.AtDocumentEnd, false);
    _userController.AddUserScript(script);
    _userController.AddScriptMessageHandler(this, "invokeAction");
}

 

Then for iOS, we have the following script injection defined using webkit API, accessing the invokeAction script that we attached and finally calling on the postMessage() method with the data parameter.

private const string JavaScriptFunction = "function invokeCSharpAction(data){window.webkit.messageHandlers.invokeAction.postMessage(data);}";

 

IWKScriptMessageHandler provides us with DidReceiveScriptMessage() method which we use to transfer the data up to the Xamarin.Forms level handler using, HybridWebView.InvokeAction(data).

Quite simple ans straight forward eh! next to Windows, or UWP as you might prefer.. 😉

UWP Renderer!

We use the Xamarin native WebViewRenderer for UWP or Windows platform.

github: /XFWebViewInteropDemo.UWP/Renderers/HybridWebViewRenderer.cs

The native default renderer grants us access to these two events NavigationCompleted and ScriptNotify. We need to make sure to subscribe to those events in our HybridWebViewRenderer in Windows as follows.

Control.NavigationCompleted += OnWebViewNavigationCompleted;
Control.ScriptNotify += OnWebViewScriptNotify;

 

NavigationCompleted, allows is to easily inject our javascript handler function, which is defined as follows for UWP or Windows,

private const string JavaScriptFunction = "function invokeCSharpAction(data){window.external.notify(data);}";

 

And then ScriptNotify, provides us the chance to redirect back the execution to Xamarin.Forms level handler using HybridWebView.InvokeAction(data).

Bingo, that completes the UWP or Windows Renderer!

Now that we’ve finished the setting up of our HybridWebView and its Native Renderer for Android, iOS and Windows, its time to consume it and taste it out! 😉

Let’s try it out!

Here’s we shall begin by consuming it in a XAML page in Xamarin.Forms!

<controls:HybridWebView
	x:Name="webViewElement"
	HorizontalOptions="FillAndExpand"
	VerticalOptions="FillAndExpand" />

github: /XFWebViewInteropDemo/HybridWebViewDemoPage.xaml

And then don’t forget to Subscribe to retrieve the data coming in from javascript inside our WebView using RegisterAction() method we created!

...
    // Subscribe for the data coming in from Javascript
    webViewElement.RegisterAction(DisplayDataFromJavascript);
}

private void DisplayDataFromJavascript(string data)
{
    Device.InvokeOnMainThreadAsync(() =>
    {
        ...
        // Do whatever you want with the data
        ...
    });
}
...

github: /XFWebViewInteropDemo/HybridWebViewDemoPage.xaml.cs

I’m just going to use the Main UI Thread’s help to execute any UI related stuff. And here’s a little demo HTML that I’m setting up in our Hyrbid WebView.

webViewElement.Source = new HtmlWebViewSource()
{
    Html =
        $@"<html>" +
        "<head>" +
            ...
            "<script type=\"text/javascript\">" +
                "function invokexamarinforms(){" +
                "    try{" +
                "        var inputvalue = 
document.getElementById(\"textInputElement\").value;" +
                "        invokeCSharpAction(inputvalue + '. This is from Javascript in the WebView!');" +
                "    }" +
                "    catch(err){" +
                "        alert(err);" +
                "    }" +
                "}" +
            "</script>" +
            ...
        "</head>" +

        "<body>" +
            "<div>" +
                "<input type=\"text\" id=\"textInputElement\" placeholder=\"type something here...\">" +
                "<button type=\"button\" onclick=\"invokexamarinforms()\">Send to Xamarin.Forms</button>" +
            "</div>" +
        "</body>" +

        "</html>"
};

github: /XFWebViewInteropDemo/HybridWebViewDemoPage.xaml.cs

As you can see I have a javascript function, invokexamarinforms() that will get invoked from a button call in the body. Once this method executes, it calls on the invokeCSharpAction() method that we defined in our Hybrid WebViews Native renderers.

In my javascript snippet I’m surrounding this call with a try catch in order to make sure the Native Renderer is properly implemented or not. Making sure this method is properly executes is a crucial step during debug if you run into any issues.

So let’s try out that sample code bits in action!

Time for some action! 😉

Hit that F5 yo! (well.. if you’re in Visual Studio! lol)

Side by side iOS, Android and UWP working like charm! 😉

As you can see in my simple Xamarin.Forms demo, I am demonstrating a simple C# .NET to Javascript call with data and Javascript to C# .NET call with data, a true bi-directional communication bridge!

Here we are typing some text in the Xamarin.Forms Entry element and sending it into the HTML inside the WebView. And then typing some text in the HTML Text Input element inside the WebView and click on HTML Button, and sending it to the Xamarin.Forms Label to be displayed, works like a charm!

I have shared the demo app code in my github as usual: github.com/XFWebViewInteropDemo

A little chat conversation between Javascript to C# and vise-versa! 😉

Yeah just a fun little demo I have added to the same repo in github! 😀

Extra tips!

Yep it’s that time, for some extra tips based on my experience with Xamarin.Forms Hybrid WebView! Although the extra tips that I already discussed in my previous article Talking to your WebView in Xamarin.Forms! still applies for this as well since we’re still extending from default Xamarin.Forms WebView, but apart from that…

Web Source, Embedded, Code HTML!? all same!

Doesn’t matter whatever the source of the HTML you’re setting in the Hybrid WebView, be it a web source directly from a URL, or loading an embedded HTML File, or even a code generated dynamic HTML content, it doesn’t make a difference.

The only thing that matters is the invokeCSharpAction() in your rendered HTML, so that the native renderers can pick it up and forward the execution to Xamarin.Forms .NET handlers!

Yes! extra parameters!

Even though I’m showcasing only a single parameter during this demo article, from javascript to C# .NET run time, you can easily extend this same implementation to pass any number of parameters as you wish! As I explained in the article make sure to define it in the following bits,

HybridWebView.InvokeAction(string data1, string data2)

Something to keep in mind is that you can only pass a single parameter into the invokeCSharpAction(data).  So in your javascript make sure to merge all the parameters into a single value and have a pipe delimiter (ex: |) like separator for them (ex: data1|data2) that you’re before to the invokeCSharpAction(data) method, which you will break it up on arrival in the native renderer and pass them up to the InvokeAction(data1, data2).

var dataBody = data;
var dataArray = dataBody.Split("|");
var data1 = dataArray[0];
var data2 = dataArray[1];

((HybridWebView)Element).InvokeAction(data1, data2);

Finally wire it all up, you’re good to go! 😉 I might share another article with some cool implementation with this in near future! 😀

Conclusion

You can easily build a communication bridge from C# .NET to javascript environment in Xamarin.Forms WebView! but the other way is not really possible out of the box!

That’s why we’re implementing this Hybrid WebView Control which allows us build a communication bridge from javascript to C# .NET environment directly during run time! 😉

So this concludes my bi-directional communication tunnel with HTML/Javascript inside your WebView in Xamarin.Forms yo!

Well that’s pretty much it!

Share the love! Cheers! 😀

Talking to your WebView in Xamarin.Forms!

Let’s build a communication bridge into your Xamarin.Forms WebView, and talk to it!? 😉 lol Yes let me show you how to pass data into the Web page rendered inside your Xamarin.Forms WebView!

I’m talking about building a uni-directional communication with Javascript inside your WebView in Xamarin.Forms yo! 😀 get your game face on!

WebView in Xamarin.Forms..

Xamarin.Forms provides a neat WebView that could render any Web HTML content efficiently similar to a browser inside your own Xamarin.Forms App.

Earlier there used to be a lots of issues that needed to be dealt with when to comes to rendering HTML content alongside Javascript inside the WebView, but with the recent update it has gotten far better with lots of features and facilities straight out of the box to be used! 😀

Invoking Javascript in the WebView!

Using the WebView straight out of the box, we can execute Javascript methods rendered inside the HTML content. Now I know this used to require a lot hacks and tricks, along side dealing with lot of run time exceptions.

But in the most recent updates of Xamarin.Forms, the WebView has gotten rock solid, and now even provides a dedicated method, EvaluateJavaScriptAsync() to invoking Javascript methods straight out of the box.

WebView.EvaluateJavaScriptAsync(String)

 

So now you can execute Javascript methods along with data parameters from you C# code in Xamarin.Forms using the default WebView control. EvaluateJavaScriptAsync() is an async method that lets you execute javascript and even await the call to response from the invoke as well.

var result = await webView
        .EvaluateJavaScriptAsync
            ("javascriptmethod('Hello world!')");

 

All you need to do is call the javascript method you’re targeting to invoke with or without the parameters you prefer using EvaluateJavaScriptAsync() in an asynchronous manner allowing you to await for a result back from the javascript into the .NET environment itself! Yep its that simple to talk to the HTML content in your WebView now! 😀

Let’s give it a try and establish a uni-directional communication with our WebView! 😉

Let the coding begin!

Here I have prepared a small demo where I’m loading some HTML content, along with a nice little javascript bits, into my WebView using HtmlWebViewSource as follows…

webViewElement.Source = new HtmlWebViewSource()
{
    Html =
        $@"<html>" +
        "<head>" +
            ...
            "<script type=\"text/javascript\">" +
                "function updatetextonwebview(text) {" +
                "    document.getElementById
                     (\"textElement\").innerHTML = text;" +
                "}" +
            "</script>" +
            ...
        "</head>" +

        "<body>" +
        ...
        ...
        "</body>" +

        "</html>"
};

Full code on github: /XFWebViewInteropDemo/DefaultWebViewDemoPage.xaml.cs

So here in my HTML content, I have a simple Javascript method, updatetextonwebview(text) where it takes in a value and set it to an HTML text element in the body. Pretty simple and straight forward.

string result = await webViewElement
        .EvaluateJavaScriptAsync
           ($"updatetextonwebview('{textEntryElement.Text}')");

 

And then I take a Text value from an Entry Element and pass it into the updatetextonwebview() javascript method using EvaluateJavaScriptAsync() of WebView.

Alright, let’s try it out!

Hit F5!

Well if you’re on Visual Studio, just hit F5 and watch the magic!

Side by side iOS, Android and UWP with Xamarin.Forms right out of the box! 😉

As you can see in my simple Xamarin.Forms demo, I have an Entry element which I type some text into and then I click on the Button which then going to pass that text data into the WebView’s javascript method. Then inside the javascript, it takes in the data and set it to a text label in the HTML body.

I have shared the demo app code in my github as usual: github.com/XFWebViewInteropDemo

No hacks, no work arounds, no custom renders, just straight out of the box in Xamarin.Forms! Works like a charm! 😉

Extra tips!

Yep it’s that time, for some extra tips based on my experience with Xamarin.Forms WebView!

-Track invoking of Javascript

Using WebView.EvaluateJavaScriptRequested event you can track the javascript invoke calls injecting into the WebView from your .NET code, basically an monitoring mechanism of all your javascript invokes from C# which will allow you to validate them or add extra details as you prefer on demand.

-Track Navigation inside the WebView

WebView provides a whole list of events to track the navigation now, along side back and forward navigation, redirects, and even refresh events.

WebView.Navigating

This event Triggers upon the beginning of the Navigation, allowing you to cancel it on demand. This event provides a WebNavigatingEventArgs object which provides you all the details about the navigation that is about to occur, direction, url endpoint and so on.

This also provides WebNavigatingEventArgs.Cancel property which allows you to cancel that navigation on demand. So yeah a lot of cool bits you can do with it!

WebView.Navigated

This event Triggers after a Navigation completes, providing you with the same details similar to Navigating event. In addition it gives WebNavigatedEventArgs.Result property which tells you whether the navigation was success or failure.

WebView.GoBackRequested | GoForwardRequested | ReloadRequested

Now these are some simplified events thats provided by WebView, allowing you to directly hook into GoBack, GoForward and Reload events when they occur. Although they do not provide facility to cancel those events like how we get in Navigating event. Just a quick easy way to monitor those events as they occur.

-Think Creative!

Most developers miss this point, if you can send a simple text string, then you can pass anything into the WebView’s javascript. Well… in disguise of a string of course!

  • Get device native data
  • Location GPS data
  • Proximity data
  • Internet Connectivity data
  • Captured File/Image data

Those are few examples, yes even an Image captured from the device camera can easily be sent as a byte array converted into a base64 string!  Imagination is the limit yo! 😉

Conclusion

Xamarin.Forms WebView has come a long way since the early days, into a complete mature sandbox environment to render any HTML Web Content inside your Xamarin.Forms app. And it provides lots of features to communicate, pass data back and forth, and even monitor and control the navigation happens inside itself.

This article basically focuses on uni-directional execution from C# .NET code to Javascript environment, while you can still await for the results from the javascript.

But there is no direct execution from Javascript environment to C# .NET yeah? So in my next article I’ll share how to build a bi-directional execution from C# .NET code to Javascript environment with Xamarin.Forms WebView. 😉

Well that’s pretty much it!

Share the love! Cheers! 😀

Xamarin.Forms Native HttpClientHandler for HttpClient…

Let’s make sure our Xamarin.Forms apps are properly configured with Native HttpClientHandler for optimum performance and better network security..

If you’re using the HttpClient for making Web API calls outside your app, you probably using the HttpClientHandler to set up various kinds of configuration for the HttpClient instance.

Now this HttpClient and Native HttpClientHandler applies directly for both Xamarin Native and Xamarin.Forms apps…

Although in this article I’m focusing on Xamarin.Forms, the same configuration set up can be used for any Xamarin Native apps as well.  By default in Xamarin you can use either the Managed HttpClientHandler which is fully maintained by .NET mono run time or the Native HttpClientHandler that maps itself to the Native run time configuration.

Why Native HttpClientHandler?

Thanks to the awesomeness of the Xamarin and the powerful Xamarin.Forms ability to map itself efficiently to the Native device environment, provides you with this facility to use the device Native Network Layer’s configuration in your Apps as well.

  • Using the Native HttpClientHandler provides you with a lot of advantages in terms of Network Communication Layer, which maps itself completely to the native properties and behaviors.
  • It provides your App with the in built default System native Security such as Transport Layer Security, TLS 1.2 features. This is basically built in for both Android and iOS system devices by default, which then we can leverage automatically on to our Xamarin.Forms app as well during run time.
  • This gives the user a peace of mind, in terms of the security of the network communication in the app while also giving the user the free of choice to let the app inherit itself the system configured security settings.
  • Defaulting to the Native Network configuration we can make sure our app is fine tuned for Security and Performance on the device native level and you do not have to spend extra time managing those bits manually.
  • Another great advantage is not needing to manually handle device Proxy Settings, allowing your Xamarin.Forms app to communicate through the device’s default network tunnel.

Well that’s pretty much a good list of reasons to make sure to set up our Xamarin.Forms apps to use the Native HttpClientHandlers eh! 😉

So what are they?

So below are the Native HttpClientHandlers available in Xamarin run time for each Platform, which applies for Xamarin.Forms as well.

AndroidClientHandler -AndroidClientHandler is the new handler that delegates to native Java code and Android OS instead of implementing everything in managed code. This option has better performance and smaller executable size.

NSUrlSessionHandler -The NSURLSession-based handler is based on the native NSURLSession framework available in iOS 7 and newer. This options has better performance and smaller executable size, supports TLS 1.2 standard.

WinHttpHandler -WinHttpHandler is implemented as a thin wrapper on the WinHTTP interface of Windows and is only supported on Windows systems. Provides developers with more granular control over the application’s HTTP communication than the default HttpClientHandler class.

So here as you can see, using the device native HttpClientHandlers provides you with the best of performance and security for your app compared to opting to use the Managed HttpClientHandler where you have to manually handle those optimizations yourself.

Although I must make a note here, in Windows or UWP Xamarin apps the default set up is the .NET Managed HttpClientHandler because the underlying native environment is Windows itself. But opting to use WinHttpHandler provides arguably better advantage according to many documentation, and also it’s in the same .NET stack! 😉

What no to do?

So before we get into “the how?”, let’s first make sure the bits not to do in our app project!

– not use “Managed”

So when it comes to Xamarin.Forms, by default when you create your project in Visual Studio the Native project nodes Properties are set up to use the Native HttpClient Handlers already. You can see this in both Android and iOS Project settings,

  • Android project node -> Properties -> Android Options -> Click “Advanced”
  • iOS project node -> Properties -> iOS Build

Do not set it to option to “Managed” HttpClientHandler in either of those settings, which will opt you out of Native HttpClientHandler.

– not use “new HttpClientHanlder()” 

If the above Settings check success, the next thing to consider is not instantiating HttpClientHanlder on its own as below,

HttpClientHandler httpClientHandler = new HttpClientHandler();
...
// setting up httpClientHandler settings
...
...
HttpClient httpClient = new HttpClient(httpClientHandler);

 

This is something you should not do, which will override your Native project property set up regarding the HttpClientHandler, and opt your HttpClient to use Managed HttpClientHandler instead, resulting you losing all the native goodness!

Next let’s see what to do?

What to do?

Here are the things you need to make sure to do instead.

– not using HttpClientHandler!?

Consider not using HttpClientHandler at all with your HttpClient, then you’re basically good to go, as long as you have set it up in your App Project Native settings. Not a joke though! lol 😛

Just use plain HttpClient instance out of the box! but make sure to do the following as well.

– set Native HttpClientHandler!

Go to the following settings in each of your Xamarin.Forms Native project nodes,

  • Android project node -> Properties -> Android Options -> Click “Advanced”

  • iOS project node -> Properties -> iOS Build

Make sure to set the Native Android and NSUrlSessionHandler those settings, to opt to use AndroidClientHandler and iOS NSUrlSessionHandler for your HttpClientHandler by default.

Well UWP or Windows project nodes doesn’t have such settings as it by defaults use .NET Managed HttpClientHandler.

A little demo!

Now if its all good, you should be able to see the following behaviors in action,

So this is a little Xamarin.Forms demo that I prepared to demonstrate the behaviors of Native HttpClientHandlers on Android, iOS and Windows UWP.

Here I’m demonstrating the Network access (blue color access granted and red color access blocked in run time) for a list of scenarios,

Now you can see how each device Native environment handles those endpoint calls, basically only allowing access to trusted secure web endpoints in the native network tunnel to go through.

Well that was quite simple eh! but we all know the real life requirements wouldn’t be so simple, what if we need to use the HttpClientHandler in code?

Yes we need access to the Native HttpClientHandler in code!

So then let me walk you through handling an advance implementation of the native HttpClientHandler with more customization added in code! 😉 

How to? Advanced set up of Native HttpClientHandler!

Yes as you can see in the Project Settings, it doesn’t really give you much options to customize your Native HttpClientHandler settings, or even override some of its behaviors at all. In a real life scenarios you would definitely need some more access to your HttpClientHandler use in code.

Compared to the Managed .NET HttpClientHandler where you easily have access to all its properties and behaviors.

But it is crucial for us to stick to the Native HttpClientHandler, so the solution would be to implement an access to the Native HttpClientHandler in our Xamarin.Forms code.

– Under the hood!?

Thanks to the awesomeness of Xamarin we have full access to those Native HttpClientHandlers in code as well, so that we can use them as however as we like. Let’s take a look under the hood of these Native bits shall we,

Android:

iOS:

Windows:

Now you can see that all these Native Handlers are extending from either HttpClientHandler or the HttpMessageHandler,

Drilling down further into HttpClientHandler we can see that its extending itself from HttpMessageHandler.

– Using em in code!

Let’s start by using our AndroidClientHandler in code to be used with HttpClient instance.

var androidClientHandler = new AndroidClientHandler();
... 
// setting up native httpClientHandler settings
...
...
HttpClient httpClient = new HttpClient((HttpMessageHandler)androidClientHandler);

 

And for iOS with the NSUrlSessionHandler.

var iosClientHandler = new NSUrlSessionHandler();
... 
// setting up native httpClientHandler settings
...
...
HttpClient httpClient = new HttpClient((HttpMessageHandler)iosClientHandler);

 

Then for Windows or UWP, opt to our WinHttpHandler.

var uwpClientHandler = new WinHttpHandler();
... 
// setting up native httpClientHandler settings
...
...
HttpClient httpClient = new HttpClient((HttpMessageHandler)uwpClientHandler);

On Windows or UWP make sure to install nuget package: System.Net.Http.WinHttpHandler to use WinHttpHandler which is a far better native option than default HttpClientHandler.

As you can see we’re casting them to HttpMessageHandler as a common ground object, since they all inherit from that base.

Now that we’ve got access to them in code, we can access all their properties and behaviors, and even override to customize them as we wish to.

– build the bridge to Xamarin.Forms!

Since the above bits are not directly accessible from Xamarin.Forms, we need to build the bridge that will allow us to access the Native HttpClientHandler instance in Xamarin.Forms environment directly.

Since I already created a common ground instance across all the native environments with the casting to HttpMessageHandler, this is much easier. Now there are plenty of ways leverage the access to this object up towards Xamarin.Forms layer, but here I’m going to showcase rather a simple implementation.

code on github repo: XFNativeHttpClientHandler/Services/HttpClientService.cs

Here I have a simple Service implementation in Xamarin.Forms where it maintains a Singleton object of itself, which contains a HttpClient object and HttpClientHandler object.

Given the HttpClientHandler is provided, I am instantiating my HttpClient() on demand during the run time as you can see below.

private HttpClientService()
{
    HttpClient = HttpClientHandler != null ?
        new HttpClient((HttpMessageHandler)HttpClientHandler) 
      : new HttpClient();
}

public static HttpClientService Instance
{
    get
    {
        lock (Padlock)
        {
            return _instance ?? 
                  (_instance = new HttpClientService());
        }
    }
}

 

So the setting up of the HttpClientHandler property happens in the each Native level’s execution start up point.

On Android: MainActivity.cs

protected override void OnCreate(Bundle savedInstanceState)
{
    ...
    
    var androidClientHandler = new HttpClientHandler();
    Services.HttpClientService.HttpClientHandler =               
                                     androidClientHandler;
    
    ...
}

 

On iOS: AppDelegate.cs

public override bool FinishedLaunching(UIApplication app, NSDictionary options)
{
    ...
    
    var iosClientHandler = new NSUrlSessionHandler();
    Services.HttpClientService.HttpClientHandler = iosClientHandler;

    ...
}

 

On Windows (UWP): MainPage.xaml.cs

public MainPage()
{
    ...

    var uwpClientHandler = new WinHttpHandler();
    Services.HttpClientService.HttpClientHandler = uwpClientHandler;

    ...
}

 

That’s it for the set up, then let’s use it in Xamarin.Forms code:

var result = await HttpClientService.Instance.
		HttpClient.GetAsync("https://google.com/");

 

Now this should provide you with a Xamarin.Forms Solution allowing you to be able to access all the Properties and Behaviors of Native HttpClientHandlers!

Yay! Access in Code!

So the whole point of access these Native HttpClientHandlers in code was to be able to customize their settings and behaviors according to our requirements eh! 😀

Go ahead and access those properties and behaviors that you wish to use…

Here’s me demonstrate a simple scenario, how to override HTTPS Certificate Validation while using our Native HttpClientHandlers!

Full gist: https://gist.github.com/UdaraAlwis/0787f74796d22c294b91be81ff162347

Things Keep in mind!

So when you’re accessing the Native HttpClientHandlers in code there are some things you need to absolutely keep in your mind, to make sure the performance and security is not compromised.

– Custom bits, only Native level!

All the custom configuration that you need to do should be done in Native Xamarin level code, accordingly to native properties and behaviors.

– One time init() only!

You should instantiate your Native HttpClientHandler instances from Native level only once, and they shouldn’t be altered later for consistency during run time across your app.

– HttpMessageHandler, keep it as it is!

Keep the HttpMessageHandler instance that we up-cast from the Native HttpClientHandler instances as it is after instantiation, to make sure you’re not overriding any native properties and behaviors that we set up or inherited prior.

– Release Build, watch out!

When you’re using the Xamarin Platform specific Project Settings, make sure those settings are propagated to Release mode as well. In .csproj file has separate configurations for Debug and Release build configurations, so make sure keep an eye out for those configuration during Release builds as well.

Conclusion

Whenever you need to use the HttpClientHandler along side HttpClient, in your Xamarin.Forms or Native Xamarin Apps, its best to use the Native HttpClientHandler. This can be easily configured in each Native Project Settings or we can even instantiate them in code to be used across our Xamarin.Forms app environment as I’ve explained in this article.

I have shared the demo app code in my github as usual: github.com/XFNativeHttpClientHandler

Well that’s it! 😉

Share the love! Cheers!

Prepping your Xamarin.Forms App for Penetration Testing!

Let’s make sure your Xamarin.Forms App is ready for Penetration Testing, or widely known as PEN Testing! Focused on the Network Communication Layer, so that we can have a peace of mind for ourselves without being annoyed by our QA and Security Analysis team! 😉 lol

In any Mobile App Development project, we need to thoroughly test our Mobile Apps for vulnerabilities and security of user data. That is why these penetration testing processes are very important, we need to make sure that we deliver a mobile application as hardened and safe guarded as possible for our Users.

Now this post is not about securing or hardening the security of your mobile app, but rather how to prepare your Xamarin.Forms built app for QA and PEN Testing procedures.

But why, Xamarin.Forms?

Xamarin.Forms does an incredible job at producing a almost native-like level Mobile Application at the end of development. But given the unique nature of Xamarin.Forms, the .NET framework that we work with, sometimes developers take it for granted, giving all the responsibility to the framework, and we miss some bits that we need to pay attention to in oppose to native mobile development.

We need to make sure our App is compatible with the QA and PEN Testing procedures. Most of the QA and PEN testing revolves around the Native Mobile App environment. But sometimes those typical native mobile app testing processes aren’t compatible with what we work on out of the box of default .NET builds of Xamarin.Forms!

PEN Testing of a Mobile App…

Now there are many different kinds of QA procedures and PEN Test cases, such as local DB analysis, MiTM packet analysis, etc. In order to support those different PEN Test procedures, some times we need to provide separate builds with different configurations of your app to our PEN Test team. Such as disabling SSL Pinning in the app so that they can execute MiTM packet analysis testing on our app, and there could be many different scenarios as such.

So I’m going to share with you some of the important key points that you need to make sure you have configured in your Xamarin.Forms project, specifically in your Network Communication Layer and for some of those custom builds that you might have to provide for the PEN Testing process.

HttpClient Handler setup..

While Xamarin does provide a full fledged Managed HttpClient and Handler, it is best to set up the HattpClient’s handlers to the device native handlers. This will make sure better performance and better native system level security for your app.

On your Xamarin.Forms project solution, go to the Android project node -> Properties -> Android Options -> Click “Advanced” button and take a look at HttpClient implementation and SSL/TLS implementation.

Make sure to set them up as above using the native Android handler, and Default (Native TLS 1.2+) Transport Layer Security for all the web calls. This will make sure all our web endpoint calls will be handled by those configurations which are best suited for performance and security of the native android system.

Then for the iOS, On your Xamarin.Forms project solution, go to the iOS project node -> Properties -> iOS Build and take a look at HttpClient implementation.

Make sure its set to NSUrlSession handler, which will provide your iOS app with native iOS level security and better performance for web endpoint calls. Also this means your app won’t support devices before iOS version 7, so better check your app requirements as well.

HttpClient setup in Xamarin.Forms!

It is very crucial that you imperilment the use of HttpClient in your Xamarin.Forms app properly with performance and security in mind. It would be best to register the instance of HttpClient as a Singleton, and refer to that singular instance for all your web endpoint calls. This will not only make it easy for debugging, also easy for configuring your API/Web endpoint execution layer’s implementation.

And set up a HttpClientHandler to be passed into your HttpClient instance during the instantiation, so that we can include all the custom configuration easily.

Unless its a must, make sure to use the Native HttpClientHandlers for your HttpClient, which will increase the performance and native security features for your app.

  • Android: AndroidClientHandler
  • iOS: NSUrlSessionHandler
  • UWP: WinHttpHandler

Instead using the .NET Managed HttpClientHandler, use the above instances mapped up to your Xamarin.Forms shared environment. Here’s something that might be useful: Xamarin and the HttpClient For iOS, Android and Windows

Do not re-instantiate the same HttpClientHandler nor HttpClient instance during run time and keep those different configuration separately for each HttpClient by registering multiple types with a pre-defined use case. Such as AuthClient for handling authentication and ApiClient for normal endpoint calls.

Although there are third party HttpClient libraries such as ModernHttpClient, that provide better features for these specific scenarios, so you could even try one of them! 😉

Disable SSL Certificate Validation..

In case if you needed to disable HTTPS / SSL Certificate validation for your PEN Test procedures such as Man-in-The-Middle packet trace analysis, then we can easily disable this by overriding the Certificate validation execution in the HttpClientHandler and assigning that to HttpClient.

var handler = new HttpClientHandler();
handler.ServerCertificateCustomValidationCallback =
	(message, certificate, chain, sslPolicyErrors) => true;

HttpClient = new HttpClient(handler);

 

The above applies of course if you have set up Managed HttpClientHandler in your Xamarin.Android and Xamarin.iOS settings instead of using the native handlers.

If you have set up your projects with Native HttpClientHandler then you can easily disable HTTPS Certificate validation by following ways.

For Android, create a Custom derived implementation of AndroidClientHandler as follows,

public class CustomAndroidClientHandler : AndroidClientHandler
{
	protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
	{
		request.Version = new System.Version(2, 0);
		return await base.SendAsync(request, cancellationToken);
	}

	protected override SSLSocketFactory ConfigureCustomSSLSocketFactory(HttpsURLConnection connection)
	{
		return SSLCertificateSocketFactory.GetInsecure(0, null);
	}

	protected override IHostnameVerifier GetSSLHostnameVerifier(HttpsURLConnection connection)
	{
		return new BypassHostnameVerifier();
	}
}

internal class BypassHostnameVerifier : Java.Lang.Object, IHostnameVerifier
{
	public bool Verify(string hostname, ISSLSession session)
	{
		return true;
	}
}

Based on: https://nicksnettravels.builttoroam.com/android-certificates/

for iOS, subscribe to TrustOverride and return true to override certificate validation.

var iosClientHandler = new NSUrlSessionHandler();
iosClientHandler.TrustOverride += (sender, trust) =>
{
	return true;
};

 

For UWP: subscribe to ServerCertificateValidationCallback and return true to override certificate validation.

var uwpClientHandler = new WinHttpHandler() 
{ 
	ServerCertificateValidationCallback = 
		(message, certificate2, arg3, arg4) =>
		{
			return true;
		}
};

 

As you can see in all the snippets above we’re overriding HTTPS Certificate Validation process manually. Now this is not a build to be pushed for Production, make sure to produce this build as a Test only build for PEN testing. So I would suggest keep this configuration in a separate branch build and opt back to the main branch for production release.

Enable Self-Signed SSL Certificates..

Instead of disabling entire SSL Certificate validation process, we could narrow down the override to a certain SSL Certificates, such as a Self-Signed Certificate endpoints that our PEN Testers might be using.

Although there are many ways to do this, basically we include the given self-signed certificate data in the app’s configuration, or override the validation with it’s key. I would recommend going into the following tutorials for it hence it covers a wide aspect of it for both iOS and Android.

Self Signed iOS Certifcates and Certificate Pinning in a Xamarin.Forms application

Self Signed Android Certificates and Certificate Pinning in Xamarin.Forms

So kudos to nicksnettravels blog! 😉 They’ve got great stuff in there!

Enable non-HTTPS!

As you know by default Android (since Android P) and iOS platforms doesn’t allow insecure non-HTTPS calls to be made from our apps,

Now we might have to disable this during development until the back end server is TSL enabled or even for a PEN test case with a custom build.

Let’s disable this on Android by using android:networkSecurityConfig in your AndroidManifest.xml with a reference to the @xml/network_security_config which we’ll create next.

<manifest ... >
    <application
        android:networkSecurityConfig="@xml/network_security_config"
        ... >
        <!-- Place child elements of <application> element here. -->
    </application>
</manifest>

 

Add a new folder called “xml” in your Resources folder and add a new xml file with the name network_security_config.xml this will hold the key to disable or enable HTTPS connections restriction as you wish.

<?xml version="1.0" encoding="utf-8" ?>
<network-security-config>
  <domain-config cleartextTrafficPermitted="true" />
</network-security-config>

 

You can set cleartextTrafficPermitted to false later during production build.

And on iOS add the following configuration in the info.plist file.

<key>NSAppTransportSecurity</key>
<dict>
    <key>NSAllowsArbitraryLoads</key>
    <true/>
</dict>

 

Oh once again, make sure to disable this during PROD builds!

System Proxy Settings support!

Something to keep in mind is that you don’t need to worry about System Proxy settings as long as you’re using the Native HttpClientHandlers as they would by default use the system preferences under the hood, but if you’re using Managed .NET HttpClientHandlers then you need to handle the System native Proxy Settings.

You can do this by creating a Platform specific Service that will extract the System Proxy Settings, and you can use that when you’re instantiating HttpClientHanlder. This article provides a great example for it: HttpClient and Proxy

Is all good? 😉

Now before you ship out your build for the PEN test you can make sure everything is in place according to your specific requirements.

BadSSL (https://badssl.com/) is a great web tool to check whether your app is able to access non-https endpoints or self-signed certificate endpoints and so on based on your PEN Test requirement. You can call upon those test endpoints directly from your app to make sure they’re accessible or not.

Network monitoring tools like Fiddler and Charles Proxy, allows you to set up dummy local proxy servers that you can test with in order to make sure your app supports proxy communication or in that case App’s compatibility with using System proxy settings. You could even monitor the data streams going in and out of the app, and see if they’re properly secured with encryption.

So for this demo I prepared a little sample app which showcases the use of non-HTTPS, Self-Signed endpoints access, and Proxy settings reading capabilities. Check out below Android, iOS and UWP run times…

As you can see it’s able to go through all the defined scenarios I mentioned before. For this demo app I’m using all Native HttpClientHandlers, so I’m using the exact code snippets I’ve shared in this blog post. Now let me try to emulate some failure scenarios where its missing some configuration I shared in this post.

Full demo code: github.com/UdaraAlwis/XFPenTestPrepDemo

   

1st I’m emulating the instance where Self-Signed HTTPS endpoints unauthorized to execute as well as Non-HTTPS endpoints blocked by default System Security layer. 2nd one shows where the Self-Signed HTTPS is diabled but non-HTTPS endpoints allowed and so on to the 3rd scenario.

Well that’s it. Hope this helps you to configure your app properly with security in mind and provide builds for the PEN Test processes according to the requirements. 🙂

Share the love! Cheers! 😀