Tag Archives: Camera

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!