Category Archives: Android

So I played around with Android Emulators in Visual Studio 2019!

Let me share some of my experience with playing around with the latest updated Android Emulators in Visual Studio 2019!

Microsoft had finally rolled out a full fledged Android Emulator set up (Xamarin Android Device Manager) that’s very stable and much easier to use with Xamarin mobile development, expiring the previously buggy always-out-dated VS Emulator set up that was shipped for Xamarin dev. Yeah seriously I hated that and had a lot of issues using those emulators.

Backstory…

So recently I got a little deep into the new Xamarin Android Emulator set up in Visual Studio 2019, where I had to build a whole bunch of custom Emulators for some experiments. I had to do a lot of fine tuning and customization for those Android Virtual Devices. Also I had to focus on Performance management as well, which was quite interesting to deal with given the HAXM and Windows Hyper-V separation.

It was a great learning experience, where I noticed a lot of new features and differences between the previous VS Emulator set up compared to this one.

So here I am sharing my experience…

Getting Started…

Here are some important articles that might be important for anyone to get started…

Managing Virtual Devices with the Android Device Manager
https://docs.microsoft.com/en-us/xamarin/android/get-started/installation/android-emulator/device-manager?tabs=windows&pivots=windows
Great step by step guide on how to update Device Manager, create new Virtual Devices, Customizing and Managing the performance further…

Editing Android Virtual Device Properties
https://docs.microsoft.com/en-us/xamarin/android/get-started/installation/android-emulator/device-properties?pivots=windows
Step by step guide for Editing Virtual Device Properties…

Troubleshooting
https://docs.microsoft.com/en-us/xamarin/android/get-started/installation/android-emulator/troubleshooting?pivots=windows
Basically this includes fixing HAXM issues, Hyper-V issues not configured up in BIOS, or not Enabled in Windows, etc.. It’s quite easy to miss those configurations so you might want to focus twice on those if you ever run into any issues.

The official documentation from Microsoft does a great job of explaining how to get started and all, so I won’t be repeating the same on my blog post, rather I would focus on the important bits that I experienced and issues I ran into which I eventually solved during my playing around! 😉

The adb binary is obsolete!?!

So this is the first weird issue I ran into when I tried out the Android Emulator on Visual Studio 2019, there is a reason why I call it weird though… lol

“The ADB binary found at C:\Program Files (x86)\Android\android-sdk\platform-tools\adb.exe is obsolete and has seriousperformance problems with the Android Emulator. Please update to a newer version to get significantly faster app/file transfer.”

Yeah notice the “seriousperformance” lol, no idea why they haven’t spell-checked the error message. Anyhow I kept on getting this warning message every time I launched my Android Emulators, I couldn’t really understand why, since I had VS 2019 updated to the latest version at the time. But later only I figured out that you need to manually update some other bits from your Android SDK Manager as shown in below steps…

Update Android Emulator!

You need to make sure to update your Android Emulator version, from the Android SDK Manager as shown below…

Go to the Tools tab, and expand the Android Emulator section, make sure you have installed the latest version as shown there. Most likely this won’t be updated by the usual VS Updater process, which was the issue in my case.

Also one more thing you need to do, since the “obsolete ADB binary issue” could be occurred from either one of these.

Update Android SDK Build Tools!

Go to Tool tab and expand Android SDK Build Tools section…

You need to make sure to have the latest version installed, and remove any older versions already installed of the Android SDK Build Tools as shown above. Because this could be causing the “obsolete ADB binary issue” that I mentioned earlier.

Intel HAXM vs Windows Hyper-V!

Now some devs seem to be getting confused about this, first think of it as this, you have an Android Emulator and you have these two different support systems that you can use to accelerate the performance of it. You can use only one of them, its either Intel HAXM or Windows Hyper-V, you cannot use both at the same time. Got it? 😉

Check out the docs: Hardware acceleration for emulator performance (Hyper-V & HAXM)
Well the documentation from Microsoft does a great job at explaining both these setups in great detail step by step.

I personally tried both of them separately in my Lenovo Windows Laptop, that’s running on Intel Core i7 Processor. Keep in mind, if you want to try Intel HAXM then you need to disable Windows Hyper-V and vise-versa, otherwise you’ll run into all kinds of issues.

Aha! Intel HAXM!

Intel’s Hardware Accelerated Execution Manager (HAXM). HAXM is a virtualization engine for computers running Intel CPUs. – Source

Check if your Intel Processor supports Virtualization Technology: https://www.intel.com/content/www/us/en/support/articles/000005486/processors.html

You development machine needs to be running on an Intel processor in order for HAXM to work, even in that case that processor needs to support Intel VT, you can check it from the link I shared above. This works on both Microsoft Windows and Apple Mac OS systems, as long as the hardware requirements are met.

Intel HAXM has always been there since long time back for accelerating the performances of Android Emulators, so it supports Emulators that are running older versions of x86-based virtual devices.

If you’ve successfully set up Intel HAXM, you can check status of HAXM set up as follows:

sc query intelhaxm

Microsoft recommends this option to be your default choice for setting up your Android Emulators. But if your dev set up doesn’t support Intel HAXM acceleration, next let’s see the second option…

Ooo! Windows Hyper-V!

Microsoft’s Hyper-V and the Windows Hypervisor Platform (WHPX)Hyper-V is a virtualization feature of Windows that makes it possible to run virtualized computer systems on a physical host computer. Source

As obvious as it is, this only works on Windows OS! This was introduced for Android Emulators quite recently, so you need to have the following set up for your local Android SDK and Tools:

  • Android Emulator package 27.2.7 or later
  • Android SDK Tools version is 26.1.1 or later

Also you need to have Microsoft Windows 10 Pro, Enterprise, or Education version installed. You can check if your system could support Windows Hyper-V as follows:

systeminfo

If all those values are shown as Yes, then you can go ahead and enable Windows Hyper-V on your machine 🙂

So, Intel HAXM or Windows Hyper-V!?!

Yeah, so which is better? given that you can ONLY think of if you’re development PC is compatible for both of them!

I’ve tried both of them, and to be honest I’ve seen much better performance with Intel HAXM Acceleration in my Windows 10 Lenovo Laptop, with Intel Core i7 processor. Since Microsoft docs also recommend this option, yes I would definitely recommend this be your primary choice as well for better performance.

FastBoot, Intel HAXM only!

Now this is something strange that I noticed during my try outs, FastBoot feature does not seem to be supported on Windows Hyper-V, during every launch it was executing a fresh cold boot. But with Intel-HAXM it works like a charm! So that’s probably something you need to keep in mind! 😉

If you’re not familiar with FastBoot, let me walk you through a little intro…

FastBoot vs ColdBoot!

You can see this configuration in the Properties from the Android Device Manager as following…

FastBoot allows you to directly boot your Android Emulator from a pre-saved snapshot state image, so you get a super fast boot and be able to deploy the apps faster when you launch directly from Visual Studio. Every time you close the Emulator it will save a snapshot of it’s current state, which will be used in the next boot.

So what is ColdBoot?

The opposite of FastBoot is ColdBoot, where during every launch the Android Emulator executes a fresh boot instance. ColdBoot is by default disabled as you can see in my previous screenshot, you need to tick on the fastboot.forceColdBoot in order to enable this. You should only use this if you need a fresh boot in each time your Emulator launches.

Now as obvious as it is, keep in mind you can’t use both of them at the same time, so make sure to tick on either forceColdBoot or forceFastBook as you prefer. 🙂

Maximum performance!

For maximizing the performance of your Android Virtual Device, I found utilizing on these three properties quite useful,

  • hw.gpu.mode – the GPU allocation set up of your Emulator
  • hw.cpu.ncore – number of Processor Cores allocated to your Emulator
  • hw.ramsize – amount of RAM size allocated to your Emulator

Now the higher values you set for those properties will definitely provide better performance in your Android Emulator, but it will require consumption of more resources from your development machine, so make sure to cross check against it when you tweak those up!

hw.gpu.mode -> host!

By default this property will be set to “auto” mode which will set the Emulator to decide whether to use device GPU processor to render the Emulator’s GPU processing or use Software GPU Emulation.

If you’ve got a dedicated powerful GPU in your development machine, I would say this should set the “host” option for the GPU emulation in the Emulator, which forces the Emulator to use the system GPU device, which in return provides great performance.

New Camera magic!

Since the latest update Android Emulators are now updated with an awesome Camera emulation feature which allows you to emulate a virtual 3D scene. You can enable this by setting the hw.camera.back property to virtualscene value.

This is such an awesome feature it allows you to navigate through an emulated virtual scene in a 3D space, with full 360 degree camera angle movements.

Now that’s some awesomeness eh! 😉

LCD Density!

You can set the density of the screen in your Android Emulator, to a list of custom values possible to set up the density-independent pixels for rendering.

Keeping in mind, setting hw.lcd.density to 160 value will cause the emulator to render each pixel in the device screen equivalent to your host machine’s physical screen pixels. You should be able to find the most suited screen density for the screen resolution you have set up for your emulator.

Here’s an example of screen resolution 1080×2160 with each lcd screen density option available from 160, 240, 213, 320, 420, 480, to 560 as follows…

Well well you can see how it clearly changes the UI rendered DPI based on the density settings you have set up… 😀

Custom Resolutions play!

So one tricky thing I got to play around was creating Android Emulators with custom screen resolutions, now this really requires a careful set up of the screen Density settings as well.

So for the fun of let me show you a custom Android Emulator that I build with the screen resolution equivalent to iPhone 11 which has height to width 1792×828 resolution…

So something to keep in mind is that, right on the first try you wouldn’t get screen density property compatible for the custom screen resolution, so you will need a few try outs to sort out the density property. Yes it took a few try outs for me as well! 😉

hw.lcd.height – screen height, hw.lcd.width – screen width, hw.lcd.density – screen density

Setting up skin.path value…

When you set up a custom resolution to your Emulator, you need to make sure to update the skin.path property value as well.

Set this value followed by the format resolution, widthxheight as shown here.

Not sure how this related to the custom resolutions, but if you miss this step your emulator screen will end up with the default resolution value set up here upon create. So make sure to set this value according to your custom screen resolution as well 🙂

Enabling on-screen Keys…

[ back | home | recent ] yes those on screen keys might not be available when you first create your custom emulator, to enable this you need to disable the hw.mainKeys property.

You should un-tick this property value to enable on-screen navigation keys.

And the resulting should be as straight as below… 😉

Well there you have it, working like a charm! and that’s pretty much it for all the tricks and lessons that I learned during my playing around with Android Emulators in Visual Studio 2019!

Conclusion

The latest updates to Android Device Manager allows you to create Android Virtual devices or emulators with incredible flexibility and easy to manage interface, with improved performances and enhancements unlike before. 🙂

The Microsoft documentations provide an incredible support for getting started step by step, and even customizing your Android emulators for Xamarin Development with ease.

I happened to be stumbled upon a great opportunity to learn a few tricks and lessons for complex use of the latest Android Virtual Devices for Xamarin Development, which I had shared in this article. 😉

Hope it helps any of you fellow devs out there!

Share the love! Cheers! 😀

Using SMS Retriever API in Xamarin Android!

Let’s use the SMS Retriever API in Xamarin Android, and possibly avoid the troubles of new Google Play Store SMS/Call Log access restrictions! 😉 Is your Android App ready for the new Google Play Store permission policy?

SMS Retriever API, in a nutshell…

Android SMS Retriever API allows you to access the SMS Messages in the phone without having to request SMS read access permission, thus giving a complete peace of mind for the user. 🙂 Allowing specific SMS messages to be read from the Inbox, which are specifically targeted to be delivered for the  app we’re requesting from. This is the perfect solution for One Time Password (OTP) mobile number verification implementation in our Android apps.

Furthermore from Google Docs: https://developers.google.com/identity/sms-retriever/

Now that the introduction is out of the way… Let’s get started!

How it works, in short…

NO! I’m not gonna get into detailed explanation, but in simplest terms we are going to have an object called SmsRetrieverClient that’s going to wait for an incoming SMS message with the matching hash key to the app we are using. This active waiting is going to execute for 5 minutes and automatically dispose itself.

When the certain SMS arrived at the inbox during the 5 minute waiting , the SmsRetrieverClient then sends a broadcast to the app with the captured message content, for any listening broadcast receivers registered in the app.  From there we pick up the message inside our broadcast receiver and we process it or do whatever the heck we want with it. 😛

But in case if the SMS wasn’t received by the phone it would still execute the broadcast but with a time out failure code, so that we know the 5 minutes waiting exceeded and the SMS wasn’t received or read.

So there’s mainly 2 components to it, SmsRetrieverClient object, and the Broadcast Receiver object. Not to mention the App Hash key, which is also very crucial element here, you need to make sure the SMS that’s sent to the device has the App hash key that’s derived from the signing keystore of the app’s running instance.

In Xamarin…

Yes this is completely available in Xamarin Android as well, right out of the box! Just a matter of figuring out the right namespaces and method calls comparing to the official Google Android Docs! 🙂

Although I’m quite surprised I could not find any official Documentation from Xamarin regarding this important API. Thus here I am filling that void! 😀

Let’s get started!

Add em Nuget!

To use SMS Retriever API in Xamarin we need to install Xamarin.GooglePlayServices.Auth nuget package to our Android project.

Just pick the latest version as you prefer and hit install.

Activate the SMSRetrieverClient…

Then we need to implement the executing of the activation of SMSRetrieverClient that is the client object that’s going to actively watch out for any incoming SMS messages with the hash key that is similar to the app we are requesting it from.

You could initiate the SMSRetrieverClient inside a button click event or invoke it from a Service instance method, choice is up to you. 🙂

private void btnStartSMSRetreiver_OnClick(object sender, EventArgs eventArgs)
{
	// Get an instance of SmsRetrieverClient, used to start listening for a matching SMS message.
	SmsRetrieverClient _client = SmsRetriever.GetClient(this.ApplicationContext);
	// Starts SmsRetriever, which waits for ONE matching SMS message until timeout
	// (5 minutes). The matching SMS message will be sent via a Broadcast Intent with
	// action SmsRetriever#SMS_RETRIEVED_ACTION.
	_client.StartSmsRetriever();
}

As you can see we’re instantiating the SmsRetrieverClient using the Application Context, and calling the StartSmsRetriever() method to activate listening to the incoming SMS messages with matching app hash key included.

A little cherry on top…

Here are some extra bits you could adopt if needed regarding the SmsRetrieverClient. You could get the return result of the SmsRetrieverClient initiation as follows…

...

	var task = _client.StartSmsRetriever();

	// You could also Listen for success/failure of StartSmsRetriever initiation
	task.AddOnSuccessListener(new SuccessListener());
	task.AddOnFailureListener(new FailureListener());
}

...

internal class SuccessListener : Java.Lang.Object, IOnSuccessListener
{
	public void OnSuccess(Object result)
	{
		// do as you wish on Success init
	}
}

internal class FailureListener : Java.Lang.Throwable, IOnFailureListener
{
	public void OnFailure(Exception e)
	{
		// do as you wish on Failure init
	}
}

And even await for the init result asynchronously as follows…

...
var task = await _client.StartSmsRetriever();
...

But don’t forget to switch the caller method to an async method! 😉

Well that’s just some cherry on top features if you ever wanted to try!

Next the BroadcastReceiver…

So here’s the other piece of the puzzle, the BroadcastReceiver that will be listening to the broadcasts of the above SmsRetreieverClient.

SMS Retriever API has provided us with an intent filter SmsRetriever.SmsRetrievedAction which we will use to register our BroadcastReceiver, which we’re going name as SMSBroadcastReceiver, and implement as following…

[BroadcastReceiver(Enabled = true)]
[IntentFilter(new[] { SmsRetriever.SmsRetrievedAction })]
public class SMSBroadcastReceiver : BroadcastReceiver
{
	public override void OnReceive(Context context, Intent intent)
	{
		if (intent.Action != SmsRetriever.SmsRetrievedAction)
			return;

		var extrasBundleundle = intent.Extras;
		if (extrasBundleundle == null) return;
		var status = (Statuses)extrasBundleundle.Get(SmsRetriever.ExtraStatus);
		switch (status.StatusCode)
		{
			case CommonStatusCodes.Success:
				// Get SMS message contents
				var messageContent = (string)extrasBundleundle.Get(SmsRetriever.ExtraSmsMessage);
				// Extract one-time code from the message and complete verification
				// by sending the code back to your server.
				ShowResultOnUI("SMS retrieved: " + messageContent);
				break;

			case CommonStatusCodes.Timeout:
				// Waiting for SMS timed out (5 minutes)
				// Handle the error ...
				ShowResultOnUI("Timed Out Error! SMS retrieval failed!");
				break;
		}
	}
}

So once the SmsRetrieverClient does its job, either success or failure it will hit our Broadcast Receiver above and pass in the results, with Status code and Content of the Message if success, which will be included in the Extra Bundle as you can see above.

Once we receive the results, its up to you to do whatever you want with it, as you can see in the code itself! 😉

That’s pretty much it! simple and straightforward eh! 😀 But I wouldn’t end there without mentioning some important other bits that you need to make sure to get it right!

Other important bits…

Here are some helpful tips for you to troubleshoot any issues you’re having with getting the SMS Retriever API to function as it should.

SMS format..

You need to make sure you’re sending the correct SMS format as mentioned in the Google Android Documentation.

<#> Your ExampleApp code is: 123ABC78
FA+9qCX9VSu

It should be same format as above, although you could make some alterations to the message content, but the structure should be same. Start with “<#>” followed by the content of the SMS and ending with the App Hash key. You can learn more about it from their documentation: SMS Retriever API: Construct a verification message

Please, get your App Hash Key right!

I’ve seen people get this wrong all the time. It is such an easy simple process but a delicate one. So if you can’t get your implementation of SMS Retriever API to function properly, you should definitely take a look at your app hash key, whether you’ve generated the correct key and using the properly in the SMS content.

Given Xamarin Android development, there’s no official documentation provided by Xamarin yet, that’s why I have written a step by step blog article to how to easily generate the accurate App hash key, give it a try if it could be of any help…

You can check it out here: App Hash Key Helper extension for Xamarin Android apps!

Let’s see it in action! 😀

Let’s fire it up and see the beauty of Android SMS Retriever API in Xamarin!

Look at the beauty eh! 😀 No SMS Read permission required 😉 way to give some peace of mind for your users for a simple functionalities such as OTP or Phone number verification!

You can try out my full blown demo in my github repo:

https://github.com/UdaraAlwis/XAndroidSMSRetrieverAPIDemo

It’s got all the bits I talked about above fully functional 🙂

in Xamarin.Forms Android?

Even if you’re using Xamarin.Forms the same implementation above can be applied easily. Just simply create a platform specific service to invoke the SMSRetrieverAPIClient on Android and call it from Xamarin.Forms at run time, then from the BroadcastReceiver just return back the results by using Xamarin.Forms MessagingCenter… 😉

Simple eh! 😀

There you have it fellas!

Cheers! Share the love! 😀 ❤

App Hash Key Helper extension for Xamarin Android apps!

Remember my last post “Generating App Hash key for SMS Retriever API for (Xamarin incl.)…” where I shared with you guys how to successfully  generating the App hash key in both MacOs and Windows environments without any hassle?

Now this is the improved alternative of it! making the whole process much easier specially for Xamarin Android development!

Previously…

So earlier we looked at how we could generate the App Hash key straight away from MacOS Terminal or on Windows with the keystore hex generation followed by the Xamarin Android helper method execution to retrieve the app hash key!

That specific helper method I had extracted partially from the Google’s official documentation sample regarding the SMS Retriever API, which I couldn’t completely port to Xamarin Android at that time while I was working on my private project.

But later I took a proper look at it and figured out how to completely port it to Xamarin Android, with a few minutes of back and forth between the Java code and C# Xamarin namespaces! 😀

Easier and Faster method!

Now with the fully ported code, as an extension helper class, we could easily generate the Hash key for our Xamarin Android app either on Windows or Mac using Visual Studio, without having to use any external Terminal or Command prompt.

but you need to follow some pre-requisites to get it to properly work..

Let’s get started!

Get your pre-requisites right!

You need to make sure you’re using the correct Keystore file to sign your APK during build, therefore navigate to your Xamarin Android project properties and set the correct Keystore file path and configuration.

In Visual Studio on Windows:

In Visual Studio on Mac:

That’s done!

Finally make sure you have given the proper app package name or app id to your app in the same project properties. ex: com.testapp.xyz

Why you ask? Since we’re directly generating the app hash code from the project itself, we need to make sure during the compilation the app, the final APK is signed using the keystore we are hoping to use in production. So we can retrieved the signed hash hex from the app Context at run time and the app id to generate the app hash code. 🙂

Then let’s begin the AppHashKeyHelper implementation… 😉

Let the implementation begin…

Let the implementation begin! lol 😀 So here is the complete ported helper class for generating the app hash key for your Xamarin Android app!

Simply copy the whole code to anywhere in your Xamarin Android project, and you could straight away call it from anywhere in the app to generate the app hash key!


using System;
using System.Linq;
using System.Text;
using Android.Content;
using Android.Content.PM;
using Android.Util;
using Java.Security;
using Java.Util;
namespace WhateverNameSpace.Droid.Util
{
/// <summary>
/// This is a helper class to generate your message hash to be included in your SMS message.
///
/// Without the correct hash, your app won't recieve the message callback. This only needs to be
/// generated once per app and stored.Then you can remove this helper class from your code.
///
/// Ported to Xamarin C# from the AppSignatureHelper.java offcial Android sample
/// – Udara Alwis
/// </summary>
public class AppHashKeyHelper
{
private static string HASH_TYPE = "SHA-256";
private static int NUM_HASHED_BYTES = 9;
private static int NUM_BASE64_CHAR = 11;
/// <summary>
/// Retrieve the app signed package signature
/// known as signed keystore file hex string
/// </summary>
/// <param name="context"></param>
/// <returns></returns>
private static string GetPackageSignature(Context context)
{
PackageManager packageManager = context.PackageManager;
var signatures = packageManager.GetPackageInfo(context.PackageName, PackageInfoFlags.Signatures).Signatures;
return signatures.First().ToCharsString();
}
/// <summary>
/// Gets the app hash key.
/// </summary>
/// <returns>The app hash key.</returns>
/// <param name="context">Android app Context.</param>
public static string GetAppHashKey(Context context)
{
string keystoreHexSignature = GetPackageSignature(context);
String appInfo = context.PackageName + " " + keystoreHexSignature;
try
{
MessageDigest messageDigest = MessageDigest.GetInstance(HASH_TYPE);
messageDigest.Update(Encoding.UTF8.GetBytes(appInfo));
byte[] hashSignature = messageDigest.Digest();
hashSignature = Arrays.CopyOfRange(hashSignature, 0, NUM_HASHED_BYTES);
String base64Hash = Android.Util.Base64.EncodeToString(hashSignature, Base64Flags.NoPadding | Base64Flags.NoWrap);
base64Hash = base64Hash.Substring(0, NUM_BASE64_CHAR);
return base64Hash;
}
catch (NoSuchAlgorithmException e)
{
return null;
}
}
}
}

We’re simply passing in the Android App Context, which will then first retrieve the signed kestore hash string from the Package Manager.

Then we retrieve the app package name from the Context itself, and move ahead with the usual encrypted key generation.

I would recommend calling this from your MainActivity itself, since this is just a one time execution in your local debug environment.

There you go! Simple as that! 😀

Now once again, keeping in mind to make sure to remove the above helper class call from your project code, before you submit your final APK to the Play Store, since google does not recommend generating the App’s hash key during user run time. Just simply retrive your hash key and remove the code, and then set it up in your SMS API gateway execution.

Thats it! 😀

Cheers!

Share the love! 😀 ❤

Generating App Hash key for SMS Retriever API for (Xamarin incl.)…

Trying to generate your app’s Hash Key for the implementation of new Android SMS Retriever API? Still couldn’t get it to work? Well the problem could be in the actual generation process of the has string!

And here are some ways you could actually make sure to generate the valid hash string to get the functionality working.

Specially if you’re developing on Windows, or better working on a Xamarin Android app? I’ve got some goodies to make it work as well! 😉

App Hash string for SMS Retriever API

Anyhow, to use the SMS Retriever API we need generate our App’s unique Hash string which is a combination of app’s package name and your app’s public key certificate. Once the SMS is received into the Inbox the SMS Retriever API looks for any matching hash key in the message corresponding to the app that requested to read the SMS, if it finds a perfect match it will kick in the execution of retrieving the SMS string, otherwise it will time out. So without the accurate app hash key the SMS Retriever API will not kick in at all. That is why it is very crucial we generate the correct app hash key for our app using the App package name and keystore hash.

Troublesome!

Although according to the official Google Documentation, it should be easy and straight forward, but it is not, specially if you’re using a Windows Dev Environment, which could be troublesome at times. To add some topping on to that, if you’re working on a Xamarin Android project in Windows, you’re in deep troublesome waters, since even Google Docs only provides samples for the Android Java implementation.

Then the sample command that Google Docs provide doesn’t really throw any error if anything goes wrong during, wrong parameter, or a wrong keyword, during hash string generation, it simply returns a false hash string, which makes things worse!

This is actually something I experienced while I was developing one of our Xamarin Android applications. Oh yes! that’s even more annoying since there’s no official documentation or Xamarin sample of the implementation code regarding that API. 😦

Hence Google’s doc command failed me I had to play around with the parameters we’re passing in to the command, re-arrange and modify to get it to work. But anyhow with a walk in the midst of the dark forest of troubleshooting, I figured out how to properly generate the App Hash key!

Get your pre-requisites right!

First of all prepare your keystore file path, keystore alias name and keystore password, and double check those values are being properly set. This is where most of them goes wrong. Then the obvious requirement, make sure you have Androd

Method 1: On MacOS Terminal

So this is the easiest and most straight forward way to generate the hash string, by simply executing the below command on a MacOS Terminal.

keytool -exportcert -alias <keystore alias name> -keystore <keystore file with extension> | xxd -p | tr -d "[:space:]" | echo -n <your app id> `cat` | sha256sum | tr -d "[:space:]-" | xxd -r -p | base64 | cut -c1-11
  • Replace the <keystore alias name> with your keystore alias name, ex: mykeystorename
  • Replace the <keystore file with extension> with the full path to your keystore file, ex: /Users/username/Desktop/mykeystorefile.keystore
  • Replace the <your app id> with your app id: com.mytest.app

If everything went well, next line Terminal will immediately prompt you to enter the keystore password, which will generate the accurate app hash key!

Yep simple as that! 😀

Now you might wonder how I shared the above screenshot so bravely without worrying about the security, oh well its just using the default Xamarin Android keystore generated by VS for Mac with its default settings and a fake app id! 😛

Troublesome? Get Utils installed!

Unless you got some missing utils in your mac developer machine, such as the following error: sha256sum: command not found, which indicates missing coreutils in your Mac. Therefore you need to fist install Homebrew if you don’t have already.

Install Homebrew: https://brew.sh/

Restart Terminal and run the below command!

brew install coreutils

Restart Terminal and re-run the has generation command! 🙂

Method 2: On Windows CMD Prompt

Now on Windows its going to be a little bit of more work specially most of the command parameters which are used in unix cannot be executed straight up in Windows Command Prompt.

So in hope of avoiding at least a little bit of pain I would recommend using the Visual Studio Command Prompt or the Android ADB Command Prompt in your Windows PC. Specially since the java keytool path should already be configured in the Path property there.

Step 1: Generate the hex string from keystore file

keytool -alias <keystore alias name> -exportcert -keystore "<keystore file with extension>" -storepass "<keystore password>" | xxd -p

Now the parameters that you need to replace are the same as we did on MacOS command, but as you can see keystore file path and password are provided within brackets or quotations. So make sure to add that detail.

If everything went well, it will return you the hex string from your keystore file!

Now that’s me trying out the default debug keystore file in Windows. If everything executes properly, it should return a super long hex string as shown above, actually even much longer than that lol, I just cropped it out 😛

Copy that hex string and keep it, we are gonna use it in the next step.

Step 2: Implement the Hash key generate code script

Next we’re going to port the Google Doc’s Android Java implementation of the Hash key generation execution to Xamarin Android C# code snippet, thanks to my few minutes of trail and error efforts 😛


// move to the class global level
using Android.Util;
using Java.Security;
using Java.Util;
using System.Text;
// move to the class global level
private static string HASH_TYPE = "SHA-256";
private static int NUM_HASHED_BYTES = 9;
private static int NUM_BASE64_CHAR = 11;
/// <summary>
/// Generate App hash key using package
/// name and keystore hex signature
/// </summary>
/// <param name="packageName"></param>
/// <param name="keystoreHexSignature"></param>
/// <returns></returns>
public static string GetAppHashKey
(String packageName, String keystoreHexSignature)
{
string appInfo = packageName + " " + keystoreHexSignature;
try
{
MessageDigest messageDigest = MessageDigest.GetInstance(HASH_TYPE);
messageDigest.Update(Encoding.UTF8.GetBytes(appInfo));
byte[] hashSignature = messageDigest.Digest();
hashSignature = Arrays.CopyOfRange (hashSignature, 0, NUM_HASHED_BYTES);
string base64Hash = Android.Util.Base64.EncodeToString
(hashSignature, Base64Flags.NoPadding | Base64Flags.NoWrap);
base64Hash = base64Hash.Substring(0, NUM_BASE64_CHAR);
return base64Hash;
}
catch (NoSuchAlgorithmException e)
{
return null;
}
}

Simply copy that snippet into a Xamarin Android project with the specific imports mentioned at the top of the snippet. You could use this as a little helper extension method to generate the app hash key by passing in the app package name and keystore hash value that we generated in the step 1, as mentioned in the parameters.

That should work like a charm! 😀

Although keep in mind once you generate the app hash string, you should remove the keystore hex and package name hex from the code before you submit it to the app store. Google does not recommend those sensitive information inside the code as magic strings due to obvious security reasons.

Now the above code snippet can be used in either Visual Studio on Windows or Mac as long as you got the keystore hex string. 😉

TADAAA! 😀 That’s it!

You’re welcome!

Share the love! 😉 ❤

Is your Android App ready for the new Google Play Store permission policy?

Not so long ago in October, 2018 Google has announced a new policy regarding the use of SMS and Call Log access permissions in your Android apps.

“Providing a safe and secure experience for our users. – Android Developers Blog, Google”

“Google is restricting which apps can request Call Log and SMS permissions – XDA Developers”

Which created quite a buzz amongst the Android Developer community, by short it means Google is restricting the access to the user’s SMS and Call logs from our Android apps, which is actually a step forward to protect the user’s privacy and security.

Root cause…

Since the beginning on Android you could gain access directly to read the user’s SMS and Call logs on android upon permission request, and your app didn’t have to be registered as a Phone or SMS handler app to perform this action. Any app could easily ask for permission from user and gain access to SMS functionality and Call logs seamlessly.

After a while,

some apps had actually started to misuse this open access, and violate user’s private data continuously…

As a fellow developer, speaking of this matter it was just a matter of getting the user to permit the one time permission and setting up the broadcast receiver to reading the messages forever even in background, which was a very easy and open access which could have easily misused for any illegal activity.  And frankly since this was just a one time permission access thing, the user wouldn’t really be aware of what’s going on in the background. :O

And frankly even for a small feature such as OTP we had to gain access to reading the whole list of SMS data in the phone, which was kind of way too much access in my opinion for such a simple task.

Restricting it up!

So Google has started to crack down on this issue as such..

“Some Android apps ask for permission to access a user’s phone (including call logs) and SMS data. Going forward, Google Play will limit which apps are allowed to ask for these permissions. Only an app that has been selected as a user’s default app for making calls or text messages will be able to access call logs and SMS, respectively.”

– Google

Well done Google! now that’s how it’s done. 😀

So frankly what Google is saying as the new policy is that your app will not be given SMS and Call log access permission unless user has selected your app as the default system SMS or Call provider app.

Unless your app’s “core functionality” is related to SMS or Call logs, such as a SMS Sender/Reader or a Call log recording app or something similar of sorts, your app will not be granted access. Otherwise you’re going to have to revert to other API’s Google has provided to access SMS and Call logs for minor functionalities such as OTP verification and so on. 🙂

Now that was back in October, 2018!

Don’t comply? App will be blocked!

Yep they first gave a grace period of 90 days and now they are bringing the rain down upon the apps…

“Reminder SMS/Call Log Policy Changes – Android Developers Blog, Google”

“Google will remove unapproved apps that use call log/SMS permissions in the next few weeks – XDA Developers”

So they have begun cracking down on the apps that are already in the Play Store which does not comply with the new policy of accessing the SMS/Call logs information.

It’s now being striclty mentioned in the Play Store Developer Policy Center: https://play.google.com/about/privacy-security-deception/permissions/

But this doesn’t mean they wouldn’t give any exceptions, in cases like if it is heavily required for the app’s core functionality, as if it’s a sub-functionality that could break the core flow of the app. In which case you will be able to submit a special review for an exception.

So what solution?

This is where you need to take a hard look at your app’s functionality and decide what is core functionality and what’s a side feature.

They have defined this very well in their new updated help document:

“Use of SMS or Call Log permission groups – Play Console Help, Google”

let me put it frankly.

Not Core Functionality but still needed!

This are the instances where it would really not break the core functionality of your app, but it is still required for some other sub-functionality in your app?

Such as for an example, let’s say SMS OTP verification? In that case you could use Google’s alternate API to access SMS OTP retriever API, which doesn’t require SMS access Permission from user. 😀

So they have also given a list of alternate possible APIs you could use to fulfil the requirement without having need the access to SMS/Call logs information.

https://support.google.com/googleplay/android-developer/answer/9047303

Once you have implemented the alternate API use, then you should submit a new version to Play Store without the mentioned permissions.

Core Functionality!

So this is where you need to define the use of your app, is your app an actual SMS Sender/Reader app such as Messenger? or a Call Log keeping app? which then can be defined as a the core functionality of your app. In that case you could continue using the access to the information as long as the user has set your app as the default phone SMS or Call service provider.

But if it is not a default Messenger or Caller app and still needed the access permissions for core functionality then…

“Submit a new version of your app that retains the permissions. Doing so will require you to complete a permissions declaration form inside the Play Console (coming soon) and will give you an extension until March 9th to remove the permissions or receive approval for your use case.”

– Android Developers Blog, Google

If accessing SMS/Call logs is required for a main functionality and you believe it does not violate the policies then you could submit a Declaration Form in Google Play Store, requesting for manual review to exclude your app from removal from Play Store.

They may provide a temporary exception to apps that aren’t Default SMS, Phone, or Assistant handlers when certain scenarios aren’t possible to achieve without such permission access, which is defined in the Exceptions section in “Use of SMS or Call Log permission groups – Play Console Help, Google”

In Conclusion…

Now this actually is going to break a lot of cool features of apps, which may or may not be violating user’s sensitive information. But still it’s a one big step forward for gaining the Android User’s trust and making them feel positive about using your app in long term. 🙂

Again that I’m saying this is going to prevent some really cool apps being pushed to public market via Play Store though. 😐 but a much needed restriction…

I encountered “GenerateJavaStubs” task failed unexpectedly in Xamarin Android

I encountered this during error during a compilation of one of my Xamarin Android apps. After installation of a new 3rd party library, I tried compiling my project, but BOOM! this happened!

What happened ?

So I took a little look-around. Well my project solution is a multi-hierarchical project, where as I have an Android Library, Core Library, and Client Project App referenced in a hierarchical manner .

So what has happened was, after some third party library installation, a duplicate MainApplication class had been generated somehow. 😮

Solution ?

Remove the duplicate  MainApplication class in your project, hence Android requires only one point to fire up. 😉

Make sure you don’t have duplicate MainApplication classes that derives from Application base class in your Xamarin.Android project. Specially if you have a hierarchical project implementation, such as a Android Library project attached to your Main application project.

In such cases make sure you maintain only one MainApplication class that derives from Application base class, in either of your projects. 😀

TADAAA! 😀

Is your Visual Studio stuck at, Emulator is already running?

So few days back after doing a fresh installation on my WIndows 10 laptop, and installing Visual Studio, I tried running a Xamarin Forms project, with the Visual Studio Android Emulator.

The project was successfully building itself, and the Visual Studio Android Emulator also started running successfully, but then the build process was on a hang state after the Emulator started running. Specifically the build log was on a hang state after “Emulator is already running” step, as I saw in the output log in VS.

So after Googling a while I figured out the problem thanks to wasting a bunch on hours on google search and forums, since many others were also having the same issue.

So let me post the solution for you right here.

Cause?

You must keep in mind that my project was building fine, and the Emulator also started running successfully and booted up itself. I was having a already built solution and up and running Emulator, but the VS couldn’t connect to the Emulator.

The cause for this is Visual Studio debugger was unable to connect to the started Emulator through the ADB (Android Debug Bridge).

This is due a wrong registry entry in the system, where as Visual Studio is looking to start up the ADB and connect to it, in order to connect to the Emulator, but due to this wrong registry entry, VS is unable to find the path to ADB, to start it up.

This is very well explained in this Visual Studio troubleshoot article:

https://msdn.microsoft.com/en-us/library/mt228282.aspx?f=255&MSPPError=-2147217396#ADB

This seem to be happening by default with fresh installations of VS lately, where as the Android SDK installation path in the above registry entry doesn’t seem to be matching with the actual SDK installation location in our system, which is probably done by default when installing Visual Studio 2015.

Solution!

So yeah as the article explains we just have to update the registry entry with the accurate path to the Android SDK installation in our system, so that Visual Studio can start up ADB to connect to the Emulator.

Step1 : Copy the actual Android SDK installation path

to find the actual Android SDK path in your system, that is referred by Visual Studio, go to the top tool bar of Visual Studio, and open the Android SDK Manager as shown below.

capture-3

If you did the default Visual Studio installation with the Cross-Platform mobile dev tools, then your path location should also look similar as above.

Copy that path, or type the same exact path on Run command and open the folder and copy the full path from there.

Step2 : Update the invalid registry entry

Open registry editor, by “regedit” in Run window and navigate to the following Registry.

HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Android SDK Tools

Now open the Path registry key and change the value with the above Android SDK path which you copied earlier.

capture-2

Well, that’s it.

There goes the solution. Now you should close the Emulator and Visual Studio and reopen your solution, hit F5! you’re all good! 😀

Cheers!

Listening to the Layout on Xamarin Android PageRenderer! (LayoutListener)

So when you create a Custom Renderer for your Xamarin Forms ContentPage, on Android, sometimes you have to tap into the Android Layout changes on your current page.

For instances like, Orientation changes, Keyboard visibility changes on Android and so on.

This is done by Adding a Layout Listener to our Layout’s ViewTree. 🙂 Confusing? Let’s get to work!

Create a Layout Listener…

First let’s create our Layout Listener, the guy who get’s the call back when the Layout Changes on the ViewTree of our Layout.

public class CustomLayoutListener : Java.Lang.Object, ViewTreeObserver.IOnGlobalLayoutListener
{
	public void OnGlobalLayout()
	{
		// do whatever the stuff you wanna do here
	}
}

 

We derive to from the IOnGlobalLayoutListener interface, where as you need to implement its OnGlobalLayout() method which get’s the call back when a Layout change occurs.

Add the Listener to the ViewTree…

Next add it to the ViewTreeObserver of your Layout.

[assembly: ExportRenderer(typeof(CustomContentPage), typeof(CustomContentPageRenderer))]
namespace WhateverYourNamespace
{
    public class CustomContentPageRenderer : PageRenderer
    {
        protected override async void OnElementChanged(ElementChangedEventArgs<Page> e)
        {
			var rootView = CrossCurrentActivity.Current.Activity.Window.DecorView.RootView;
			rootView.ViewTreeObserver.AddOnGlobalLayoutListener(new CustomLayoutListener());
		}
	}
}

 

Since I implemented this on a Xamarin Forms Custom Renderer, first I have gained access to the current Activity’s RootView (from a 3rd party library CurrentActivityPlugin) and then I have added my listener to the ViewTreeObserver of my root view. 😀

TADAA! 😀

but you could also…

Oh well good things comes to those who wait.. lol Xamarin Android provides you an event called GlobalLayout where you could also directly subscribe to Layout changes without having to implement your own listener.

rootView.ViewTreeObserver.GlobalLayout += (sender, args) =>
{
	// do whatever the stuff you wanna do here
}

 

Oh well it depends on your implementation requirement though.

Anyways there you have it! 😀

Enjoy!

An improved ScrollView control for Xamarin Forms by me, myself and I…

Alright now when it comes to the default Xamarin Forms ScrollView, its pretty much generic and limited with the simple common attributes and behaviours, and it does not deliver any specific “cool” features with it.

What’s so cool about it?

So I thought of creating my own Custom ScrollView for Xamarin Forms using Custom Renderers, which would include the following awesome features,

Bouncy Effect – Yeah you gotta admit, the bounce effect of a native scrollview is pretty fun to play with, in a User’s perspective. So I thought of enabling this feature in my custom ScrollView even when the Child Element doesn’t exceeds the ScrollView boundaries… 😉
(PS: this effect is interpreted in native Android and iOS differently)

Disabling and Enabling Horizontal and Vertical Scroll Indicators – Now sometimes these scroll bar indicators are useful but there are times which we want to hide them, as it might look ugly on the UI in certain cases. So yeah let’s have some control over it shall we? 😀

Background Image – Of course who wouldn’t like a background Image on a Scroll view eh! 😉 Well to be specific we are going to add a Fixed Background Image for the ScrollView. And note that this background Image would be fixed, and will not be scrolling with the Content of the ScrollView. (I will do another post to enable that feature).

Yes behold, me, myself and I presenting the “BloopyScrollView” why the name “BloopyScrollView”? I don’t even know. lol 😛

Implementation

Alright let’s go ahead and create our Custom ScrollView Control in the PCL project. Along with the following properties, so that we could have direct control over the above said behaviours.

Alright now expect this to be longer, since I have added the properties as Bindable Properties, so you could use them in any MVVM scenario with ease. 😀

namespace WhateverYourNamespace
{
    public class BloopyScrollView : ScrollView
    {
        public static readonly BindableProperty IsHorizontalScrollbarEnabledProperty =
        BindableProperty.Create(
            nameof(IsHorizontalScrollbarEnabled),
            typeof(bool),
            typeof(BloopyScrollView),
            false,
            BindingMode.Default,
            null);
        /// <summary>
        /// Gets or sets the Horizontal scrollbar visibility
        /// </summary>
        public bool IsHorizontalScrollbarEnabled
        {
            get { return (bool)GetValue(IsHorizontalScrollbarEnabledProperty); }
            set { SetValue(IsHorizontalScrollbarEnabledProperty, value); }
        }


        public static readonly BindableProperty IsVerticalScrollbarEnabledProperty =
        BindableProperty.Create(
            nameof(IsVerticalScrollbarEnabled),
            typeof(bool),
            typeof(BloopyScrollView),
            false,
            BindingMode.Default,
            null);
        /// <summary>
        /// Gets or sets the Vertical scrollbar visibility
        /// </summary>
        public bool IsVerticalScrollbarEnabled
        {
            get { return (bool)GetValue(IsVerticalScrollbarEnabledProperty); }
            set { SetValue(IsVerticalScrollbarEnabledProperty, value); }
        }


        public static readonly BindableProperty IsNativeBouncyEffectEnabledProperty =
        BindableProperty.Create(
            nameof(IsNativeBouncyEffectEnabled),
            typeof(bool),
            typeof(BloopyScrollView),
            true,
            BindingMode.Default,
            null);
        /// <summary>
        /// Gets or sets the Native Bouncy effect status
        /// </summary>
        public bool IsNativeBouncyEffectEnabled
        {
            get { return (bool)GetValue(IsNativeBouncyEffectEnabledProperty); }
            set { SetValue(IsNativeBouncyEffectEnabledProperty, value); }
        }


        public static readonly BindableProperty BackgroundImageProperty =
        BindableProperty.Create(
            nameof(BackgroundImage),
            typeof(ImageSource),
            typeof(BloopyScrollView),
            null,
            BindingMode.Default,
            null);
        /// <summary>
        /// Gets or sets the Background Image of the ScrollView
        /// </summary>
        public ImageSource BackgroundImage
        {
            get { return (ImageSource)GetValue(BackgroundImageProperty); }
            set { SetValue(BackgroundImageProperty, value); }
        }
    }
}

 

There we go IsHorizontalScrollbarEnabled, IsVerticalScrollbarEnabled to disable/enable Horizonal and Vertical Scrollbars.

IsNativeBouncyEffectEnabled to control the Native Bouncy effect.

BackgroundImage to set the ImageSource for the ScrollView’s background Image. And make sure to provide a proper image for this hence we will be resizing the given image in our native renderer level to fit to the background of the ScrollView.(You will see in the next steps below)

Alright let’s head over to creating the Custom Renderers associated with our BloopyScrollView.

Something to keep in mind…

So if you’re a frequent reader of my blog, you may remember sometime ago I created an Extention class for handling Xamarin Forms Images in Native code level: https://theconfuzedsourcecode.wordpress.com/2016/12/12/an-awesome-image-helper-to-convert-xamarin-forms-imagesource-to-ios-uiimage-or-android-bitmap/

Why I’m bringing this up, is because we are going to be needing it for this project. You ask why? Because we need to convert the above BackgroundImage, which is of type Xamarin Forms ImageSource.

So we need to convert that ImageSource to native UIImage or Bitmap image respectively in our Custom renderer levels. 😉

So go ahead and grab that code real quick and add it to your Native Projects. 😀

iOS Implementation

Now let’s create the Custom Renderer for the Control in Xamarin.iOS project.

[assembly: ExportRenderer(typeof(BloopyScrollView), typeof(BloopyScrollViewRenderer))]
namespace WhateverYourNamespace.iOS
{
    public class BloopyScrollViewRenderer : ScrollViewRenderer
    {
        private UIImage _uiImageImageBackground;

        protected override async void OnElementChanged(VisualElementChangedEventArgs e)
        {
            base.OnElementChanged(e);

            this.ShowsVerticalScrollIndicator = ((BloopyScrollView)e.NewElement).IsVerticalScrollbarEnabled;
            this.ShowsHorizontalScrollIndicator = ((BloopyScrollView)e.NewElement).IsHorizontalScrollbarEnabled;

            if (e.NewElement != null)
            {
                if (((BloopyScrollView)e.NewElement).IsNativeBouncyEffectEnabled)
                {
                    this.Bounces = true;
                    this.AlwaysBounceVertical = true;
                }

                if (((BloopyScrollView)e.NewElement).BackgroundImage != null)
                {
                    // retrieving the UIImage Image from the ImageSource by converting
                    _uiImageImageBackground = await IosImageHelper.GetUIImageFromImageSourceAsync(((BloopyScrollView)e.NewElement).BackgroundImage);
                }

                ((BloopyScrollView)e.NewElement).PropertyChanged += OnPropertyChanged;
            }
        }

        private void OnPropertyChanged(object sender, PropertyChangedEventArgs propertyChangedEventArgs)
        {
            if (propertyChangedEventArgs.PropertyName == BloopyScrollView.HeightProperty.PropertyName)
            {
                // check if the Width and Height are assigned
                if (((BloopyScrollView)sender).Width > 0 & ((BloopyScrollView)sender).Height > 0)
                {
                    // resize the UIImage to fit the current UIScrollView's width and height
                    _uiImageImageBackground = ResizeUIImage(_uiImageImageBackground, (float)((BloopyScrollView)sender).Width, (float)((BloopyScrollView)sender).Height);

                    // Set the background Image
                    this.BackgroundColor = UIColor.FromPatternImage(_uiImageImageBackground);
                }
            }
        }

        // We need to override this to have the background image to be fixed
        public override void Draw(CGRect rect)
        {
            base.Draw(rect);
        }

        // Resize the UIImage
        public UIImage ResizeUIImage(UIImage sourceImage, float widthToScale, float heightToScale)
        {
            var sourceSize = sourceImage.Size;
            var maxResizeFactor = Math.Max(widthToScale / sourceSize.Width, heightToScale / sourceSize.Height);
            if (maxResizeFactor > 1) return sourceImage;
            var width = maxResizeFactor * sourceSize.Width;
            var height = maxResizeFactor * sourceSize.Height;
            UIGraphics.BeginImageContext(new CGSize(width, height));
            sourceImage.Draw(new CGRect(0, 0, width, height));
            var resultImage = UIGraphics.GetImageFromCurrentImageContext();
            UIGraphics.EndImageContext();
            return resultImage;
        }
    }
}

 

Inside the method we are assigning the relevant properties of our BloopyScrollView to the native control properties.

The UIScrollView which is associated with the Xamarin Forms ScrollView has the following native properties:

  • ShowsVerticalScrollIndicator: Make the vertical scrollbar visible or hidden
  • ShowsHorizontalScrollIndicator: Make the horizontal scrollbar visible or hidden
  • Bounces: Always enable the native bounce effect on iOS UIScrollView
  • BackgroundColor: Allows to set the background color for the UIScrollView or set an Image as a pattern

Also you may have noted that we are converting our Image Source BackgroundImage to a UIImage using our extension.

And then when the Height and Width are set to the Control, we are resizing the Image to fit those properties and setting that as the Background of the UIScrollView through the UIColor.FromPatternImage() which allows us to set the image as a pattern throughout the canvas of the UIScrollView.

the strange tale of getting the UIScrollView’s Fixed background in Xamarin… :O

Notice that we are overriding the Draw(CGRect rect) method, this is to have the UIScroll Background Image to be fixed within the boundaries, and not to be spanned across the Content area.

Because usually if we set the BackgroundColor property, it will span across the Content area, but strangely if we override the Draw() method, BackgroundColor would only be contained within UIScrollView’s boundaries, without spanning across the Content area. This is something I figured out while playing around with the above implementation. 😀

Alright let’s jump into Android… 😀

Android Implementation

Now let’s create the Custom Renderer for the Control in Xamarin.Android project.

[assembly: ExportRenderer(typeof(BloopyScrollView), typeof(BloopyScrollViewRenderer))]
namespace WhateverYourNamespace.Droid
{
    public class BloopyScrollViewRenderer : ScrollViewRenderer
    {
        private Bitmap _bitmapImageBackground;

        protected override async void OnElementChanged(VisualElementChangedEventArgs e)
        {
            base.OnElementChanged(e);

            this.VerticalScrollBarEnabled = ((BloopyScrollView)e.NewElement).IsVerticalScrollbarEnabled;
            this.HorizontalScrollBarEnabled = ((BloopyScrollView)e.NewElement).IsHorizontalScrollbarEnabled;

            if (((BloopyScrollView)e.NewElement).IsNativeBouncyEffectEnabled)
            {
                this.OverScrollMode = OverScrollMode.Always;
            }

            if (((BloopyScrollView) e.NewElement).BackgroundImage != null)
            {
                // retrieving the Bitmap Image from the ImageSource by converting
                _bitmapImageBackground = await AndroidImageHelper.GetBitmapFromImageSourceAsync(((BloopyScrollView)e.NewElement).BackgroundImage, this.Context);

                // resize the Bitmap to fit the current ScrollView's width and height
                var _resizedBitmapImageBackground = new BitmapDrawable(ResizeBitmap(_bitmapImageBackground, this.Width, this.Height));

                // Set the background Image
                this.Background = _resizedBitmapImageBackground;
            }
        }

        // Resize the Bitmap
        private Bitmap ResizeBitmap(Bitmap originalImage, int widthToScae, int heightToScale)
        {
            Bitmap resizedBitmap = Bitmap.CreateBitmap(widthToScae, heightToScale, Bitmap.Config.Argb8888);

            float originalWidth = originalImage.Width;
            float originalHeight = originalImage.Height;

            Canvas canvas = new Canvas(resizedBitmap);

            float scale = this.Width / originalWidth;

            float xTranslation = 0.0f;
            float yTranslation = (this.Height - originalHeight * scale) / 2.0f;

            Matrix transformation = new Matrix();
            transformation.PostTranslate(xTranslation, yTranslation);
            transformation.PreScale(scale, scale);

            Paint paint = new Paint();
            paint.FilterBitmap = true;

            canvas.DrawBitmap(originalImage, transformation, paint);

            return resizedBitmap;
        }
    }
}

 

The Android ScrollView which is associated with the Xamarin Forms ScrollView has the following native properties:

  • VerticalScrollBarEnabled: Make the vertical scrollbar visible or hidden
  • HorizontalScrollBarEnabled: Make the horizontal scrollbar visible or hidden
  • OverScrollMode: Always enable the native bounce effect on Android ScrollView
  • Background: Allows to set the background drawable for the ScrollView

As you may have noticed we are converting our Xamarin Forms Image Source BackgroundImage to a Bitmap image using our extension.

Then we are resizing out Bitmap image according to the Width and Height of the ScrollView to fit to the full background to be wrapped around a BitmapDrawable and set to the Background of ScrollView.

There you go! 😀

Let’s use it… 😉

Alright now that’s done, let’s consume this in our PCL project.

<StackLayout Padding="10,0,10,0">

	<Label Text="Welcome to Xamarin Forms!"
		   VerticalOptions="Center"
		   HorizontalOptions="Center" />

	<local:BloopyScrollView 
	IsNativeBouncyEffectEnabled="True"
	IsVerticalScrollbarEnabled="False"
	IsHorizontalScrollbarEnabled="False">
	<local:BloopyScrollView.BackgroundImage>
	  <FileImageSource File="xamarinBackgroundImage.png"/>
	</local:BloopyScrollView.BackgroundImage>
	
			<Label
			  FontSize="22"
			  HeightRequest="400"
			  Text=
			  "Whatever your text content to be displayed." />
			  
	</local:BloopyScrollView>

</StackLayout>

 

As you can see I have inserted my BloopyScrollView in a StackLayout and as the content of the ScrollView I have added Label. Well you can add any content you want or set any Height or Width as you wish.

Notice that I have set IsNativeBouncyEffectEnabled to be True as I want to see the native Bouncy effect. Then I have disabled the Vertical and Horizontal Scrollbars from the properties we added earlier. Then finally I have added the BackgroundImage and set the FileImageSource to the ImageSource type, where as I have placed the image in the native Resource folder, as you would do with any defualt Xamarin Forms Image. 😉

Now let’s see the results… 😀

bloopscrollview-on-ios-lowq  bloopscrollview-on-android-lowq

Yaay! 😀

As we expected the Vertical and Horizontal Scrollbars are disabled and our ScrollView has full native bouncy effect accordingly.

Also you can see the Background Image nicely resized itself and fit to the background of the BloopyScrollView. 😀

Happy dance! lol

Recap Stuff…

Now there’s some stuff I wanted to recap, that is you may have noticed that when I was resizing the Image, I needed the Control’s Height and Width, and where I have acquired those properties are in two different places on each Android and iOS renderers.

To be specific I have accessed the Control’s Width and Height on Android right from the OnElementChanged method, but on iOS renderer I have accessed those values from the  OnPropertyChanged method’s Height property event. 

This is because of the differences of the Rendering cycling of Android and iOS, whereas on Android right at the firing of the Custom Renderer it assigns itself Width and Height. But on iOS we have to access them indirectly by waiting till those properties are set, by listening to the OnPropertyChanged event.

Get it on Github! 😀 XFImprovedScrollView

Cheers everyone!

Pass this on to another developer to make them smile! 😀
– Udara Alwis

An awesome Image Helper to convert Xamarin Forms ImageSource to iOS UIImage or Android Bitmap…

The default Xamarin Forms ImageSource is good, but it doesn’t provide all the properties of an Image, not as much as native Image types of Android or iOS. This is why sometimes we need to drill down to the native level of Image handling sometimes, specially when you’re dealing with Custom Renderers, or complex Image manipulation stuff in Xamarin.

So yeah it’s no surprise you will run into the need of converting the default Xamarin Forms ImageSource to native Image type in iOS and Android, respectively UIImage or Bitmap types.

Well I know I did. lol 😛

How ? 😮

So how could you do this ? Well, something intermediate for both Xamarin Forms ImageSource and the native Image types is the byte[] array. 🙂 But I’m gonna take a pass on it, since it’s too much of trouble and process, which could lead to bad memory consumption. 😦 Instead, why don’t we deal with this straight away. 😀

This is how I did it.. 😉

Now when it comes to Xamarin Forms almost everything is handled by drilling down to the native levels of the platform. Likewise ImageSource  during the runtime is handled through three types of Native Handlers that are as follows,

  • ImageLoaderSourceHandler
  • FileImageSourceHandler
  • StreamImagesourceHandler

Now for each Native environment, these handlers implements a LoadImageAsync() method, which loads the type of Native Type image for a given ImageSource.

This is usually done under the hood, but we need to access this same functionality on the go for our own requirements, so let’s do it by our own implementation.

Let’s create our Android Image Helper…

So we are going to create a Public class with static methods that could be used as extension methods in our Native Project levels. So go ahead and create the AndroidImageHelper class in your Xamarin.Android project level.

sameple

 

public class AndroidImageHelper
{
	private static IImageSourceHandler GetHandler(ImageSource source)
	{
		IImageSourceHandler returnValue = null;
		if (source is UriImageSource)
		{
			returnValue = new ImageLoaderSourceHandler();
		}
		else if (source is FileImageSource)
		{
			returnValue = new FileImageSourceHandler();
		}
		else if (source is StreamImageSource)
		{
			returnValue = new StreamImagesourceHandler();
		}
		return returnValue;
	}

	/// <summary>
	/// For converting Xamarin Forms ImageSource object to Native Image type
	/// </summary>
	/// <param name="source"></param>
	/// <param name="context"></param>
	/// <returns></returns>
	public static async Task<Bitmap> GetBitmapFromImageSourceAsync(ImageSource source, Context context)
	{
		var handler = GetHandler(source);
		var returnValue = (Bitmap)null;

		returnValue = await handler.LoadImageAsync(source, context);

		return returnValue;
	}
}

 

Alright there we go, as you would have expected we are using the native level Handlers of the ImageSource and retrieving the native image type as I explained earlier through the LoadImageAsync() method. Of course you need to pass a reference of your current Context since Android requires the context reference to almost every execution related to the UI stuff.

First we are getting the GetHandler type by the ImageSource, then we are calling the method above to retrieve the Bitmap image and returns back to the caller.

Let’s create our iOS Image Helper…

So just like on Android let’s do the same on iOS and create the public class IosImageHelper in your Xamarin Forms iOS project level.

sameple

public class IosImageHelper
{
	private static IImageSourceHandler GetHandler(ImageSource source)
	{
		IImageSourceHandler returnValue = null;
		if (source is UriImageSource)
		{
			returnValue = new ImageLoaderSourceHandler();
		}
		else if (source is FileImageSource)
		{
			returnValue = new FileImageSourceHandler();
		}
		else if (source is StreamImageSource)
		{
			returnValue = new StreamImagesourceHandler();
		}
		return returnValue;
	}

	/// <summary>
	/// For converting Xamarin Forms ImageSource object to Native Image type
	/// </summary>
	/// <param name="source"></param>
	/// <returns></returns>
	public static async Task<UIImage> GetUIImageFromImageSourceAsync(ImageSource source)
	{
		var handler = GetHandler(source);
		var returnValue = (UIImage)null;

		returnValue = await handler.LoadImageAsync(source);

		return returnValue;
	}

}

 

So here also we are using the same implementation as we used on Android, instead the LoadImageAsync() returns an UIImage.

Now let’s use it… 😉

Alright let’s see how to use these extensions in our code. 🙂

// Useage in iOS

UIImage _uiImageconverted = await IosImageHelper.GetUIImageFromImageSourceAsync(yourImageSourceObject);

// Useage in Android

Bitmap _bitmapImageconverted = await AndroidImageHelper.GetBitmapFromImageSourceAsync(yourImageSourceObject, this.Context);

 

There you have it, now you have your Xamarin Forms ImageSource converted to the given Native Image type, either iOS UIImage or Android Bitmap Image type. 😀

Enjoy! 😀

Cheers everyone!