.NET MAUI: Android Bug – Map’s MoveToRegion Method Not Updating Visible Region

In the realm of software development, encountering bugs is an inevitable part of the process. In this blog post, we will delve into a bug specific to the Android platform in .NET MAUI applications. This bug affects the Map control, where the MoveToRegion method fails to update the visible region under certain circumstances. We will explore the symptoms of this bug and present a workaround that involves creating a custom child class of the Map control and overriding the OnPropertyChanged method of the IsVisible property.

Symptoms

The bug we are addressing pertains to the Map control in .NET MAUI applications on the Android platform. In some cases, the MoveToRegion method fails to modify the visible region of the map, resulting in the region staying the same despite the attempted change. This issue can lead to inconsistencies in map display and user experience.

Workaround

To overcome this bug, we can implement a workaround that involves creating a custom child class of the Map control and overriding the OnPropertyChanged method of the IsVisible property. By introducing a small delay and invoking the MoveToRegion method on the UI thread, we can ensure that the visible region updates correctly.

Begin by creating a new class that derives from the Map control. This class will serve as a custom child class that incorporates the necessary workaround logic.

public class CustomMap : Map
{
    protected override void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        base.OnPropertyChanged(propertyName);

        if (propertyName == nameof(IsVisible))
        {
            if (IsVisible)
            {
                Task.Run(async () =>
                {
                    // Introduce a small delay before invoking MoveToRegion
                    await Task.Delay(1500);

                    Device.BeginInvokeOnMainThread(() =>
                    {
                        MoveToRegion(...);
                    });
                });
            }
        }
    }
}

Replace the Map control instances in your .NET MAUI application with instances of the newly created CustomMap control. This ensures that the workaround logic is applied.

<ContentPage ...
             xmlns:local="clr-namespace:YourNamespace"
             ...>
    <local:CustomMap ... />
</ContentPage>

The bug affecting the Map control on the Android platform in .NET MAUI applications, where the MoveToRegion method fails to update the visible region, can be frustrating for developers and users alike. However, by implementing the workaround provided in this blog post, which involves creating a custom child class of the Map control and overriding the OnPropertyChanged method of the IsVisible property, you can ensure that the visible region updates as intended.

It’s important to note that while this workaround provides a solution to the bug, it’s advisable to keep track of official .NET MAUI updates and bug resolutions. Check for any fixes or enhancements provided by the .NET MAUI team, as they may address this bug in future releases.

https://github.com/dotnet/maui/issues/12342

This content has 1 year. Some of the information in this post may be out of date or no longer work. Please, read this page keeping its age in your mind.

My flawless cross-platform data sync experiences

In this article, I would like to share my own experience of how I use different service providers to make sure that my files, music, passwords, emails are available on all my devices. Be it macOS, Windows, Android or iOS. The services detailed below reflect my personal preferences. It is possible that there are better providers that are cheaper or that offer more functionality. If you know of such, help readers by writing in to tell us what works for you. I personally do not like Google’s services. I will not recommend Google Drive, Authenticator and other services in this article, but I am sure that their solutions can solve the architecture I consider to be proven.

What I’d like to show you is how I manage in my daily life to make sure that all my data is in sync and accessible on all my devices, almost without exception.

File Storage and e-mail account. Notes, Calendar, Contacts.

I personally chose Microsoft’s OneDrive technology as my storage and email provider. They give you 5GB of cloud storage space in their free plan, and an extra 15 GB for emails. For a very long time I subscribed to Microsoft OneDrive +100GB for $2 per month, which is fair, but then recently I decided to subscribe to Microsoft Office 365. Partly so I could have a licensed Microsoft Office subscription of my own to access important files on my personal computer, and partly because they are increasing the cloud storage to 1TB. On top of that, we also get support for recovering our deleted, lost files, or if a file encryption caused by a ransomware virus happens, it can detect and stop the operation. The one terabyte package runs around $60 for a year (+VAT, which is 27% in Hungary). If you buy it, you’ll also no longer have to watch the notifications on the outlook.com web interface. You also get the desktop versions of these in addition to the web versions of Excel, Word, Powerpoint. You can install the desktop version of Microsoft Office on 5 computers with one license key.

OneDrive use pretty serious file encryption, so you can feel safe with your files here, but if you have something really personal in your cloud, there’s the safe feature, which uses an extra encryption algorithm in addition to a number of security requirements

On Windows the OneDrive client is integrated, on macOS it can be installed separately, it integrates quite nicely into the system. You can configure them not to download the entire cloud content to your computer unnecessarily, but to have a file available in the file structure in case you want to store it. What it does is download the file to the physical hard disk before use. This saves a lot of space.
On Android, the OneDrive client also integrates quite well with the operating system, but I don’t use an Android device on a daily basis, just an iPhone.
Mobile clients can automatically back up your camera roll. The upload is an interesting solution for iOS, as they couldn’t do it in the background: they developed a screen called “Night Backup”, which basically layers a wakelock on the display and takes the brightness off the phone. You can view files on your mobile “without downloading”. Handles the web client for the iPhone HEIC format.

Your Outlook email address can be accessed via an Exchange server, which also allows you to save Calendar and Reminders, Notes, Contacts. Personally, I have all syncing turned off in iCloud because I sync my notes to my Outlook account. If you set macOS and iOS to take your outlook email address as your Internet account, the built-in Notes, Email, Calendar app can handle it. This is good because in Windows it’s also built-in to sync everything to the outlook account, so you get a Notepad and Calendar on top of the emails. So if you add a meeting to your calendar, it’ll show up immediately on your iOS/Android device, and also on macOS. Of course it works in all directions. The only downside to the notepad is that on macOS you can’t bold letters, insert a diagram, etc. in the notes app. So if you have an iPad and an Apple Penciled, you’ll have to choose a different way to draw.

Plus one thing besides Outlook that I haven’t seen with any other provider: you can assign aliases to your email address. So you don’t have to register a new email address if you get bored of your old email, you can simply add another address to the account and use up to 10 email addresses with one mailbox.
You can find out more about the packages and their services here: https://www.microsoft.com/en-us/microsoft-365/onedrive/compare-onedrive-plans?activetab=tab%3aprimaryr1

Music

This is probably the subject I have dealt with the least. I spend about 80,000 minutes a year listening to music. I clearly chose an online music service provider. My choice was Spotify. Since then, I have tried a service called Tidal once, which is quasi the same as Spotify, but lossless music, but I didn’t feel it was worth the extra money, I couldn’t take advantage of it.
Spotify has the ability to sync playlists between all platforms. It has a relatively good algorithm for recommending music. You can download tracks of reasonable quality for offline listening on its mobile app. The radio in my car supports it natively. Of course, the 1TB of storage space could hold a lot of music, but you don’t have to worry about downloading it

More information about Spotify: https://www.spotify.com/us/premium/

Password management and two-factor authentication

I never use the same password on any service. In fact, it could be said that I don’t even use passwords, because I don’t know any of them by memory. This is because I let the computer generate super long and complicated passwords. That’s pretty much how to use a password manager effectively, and how to perhaps exist one step more securely on the Internet.

What was important to me was to make the password manager work on macOS and windows, and to be able to add passwords to iOS not only in safari, but also in the apps.

Microsoft Authenticator could have been the perfect solution, but it wasn’t. (https://www.microsoft.com/en-us/security/mobile-authenticator-app) As I am logged in to my work account on my devices, where the password storage functionality of the Authenticator application is disabled by policy, I cannot add passwords to my personal account. But maybe that’s okay, it’s less responsibility on my Microsoft account. After much searching, I found LastPass to be the most sensible password management application. It works on mac on windows, in all browsers, and integrates with iOS. And it can also fill in passwords in apps. https://www.lastpass.com/pricing.

Another very important thing is to protect your account from unauthorised access. Almost all websites can be set up with two-factor authentication, be it Instagram, Facebook, GitHub, etc. Lastpass also has an Authenticator application that can generate such two-factor passcodes. Just like Microsoft authenticator. I’ve set up two-factor authentication everywhere.

This content has 2 years. Some of the information in this post may be out of date or no longer work. Please, read this page keeping its age in your mind.

Xamarin.Android get resource id without ResourceManager.

If calling ResourceManager.GetResource(“resourceName”) doesn’t work because the framework doesn’t return the resource you want, you can bypass it with the following code snippet:

            string audioFileNameWithoutExtension = System.IO.Path.GetFileNameWithoutExtension(audiofile);
            int audioResourceId = (int)typeof(Resource.Raw).GetField(audioFileNameWithoutExtension).GetValue(null);
            Android.Net.Uri audioUri = Android.Net.Uri.Parse(ContentResolver.SchemeAndroidResource + "://" + Application.Context.PackageName + "/" + audioResourceId);

            channel.SetSound(audioUri, audioAttributes);

I used this code snippet to set a custom push notification sound

This content has 3 years. Some of the information in this post may be out of date or no longer work. Please, read this page keeping its age in your mind.

Android: Get keys signature from keystore

On Windows change directory to:

C:\Program Files (x86)\Java\jre1.8.0_271\bin

Give out the following command for keytool

keytool -list -keystore "C:\source_to_keystorw\keystorefilename.keystore" -storepass supersecurepassword

Results the following:

Keystore type: jks
Keystore provider: SUN

Your keystore contains 1 entry

com.companyname.projectname.appdeliverykey, 2021.05.20., PrivateKeyEntry,
Certificate fingerprint (SHA-256): 44:58:C2:B6:84:0A:9C:E0:09:8A:DD:ED:8C:EC:E7:BD:3D:0F:CC:17:32:BC:77:D6:BB:32:E8:5B:43:25:84:DF

This content has 3 years. Some of the information in this post may be out of date or no longer work. Please, read this page keeping its age in your mind.

Xamarin Forms: White screen between page push and pop solved

If you are experiencing white screen when pushing to Navigation or Modal stack on Android, read on.

I’m not sure is this a bug in Xamarin Forms or not, but I guess this is, because it comes only in certain scenarios, and not always.

What is happening, how do you notice this error?

You have got a NavigationPage. You are pushing a new page to the navigationstack, and the page is not getting rendered, only a blank white screen displays.

If you are rotating the device, the page is getting rendered well.

My environment was:
Xamarin.Forms: 4.8 up to 5.0
Device: Samsung Galaxy A12
Visual Studio 2019 Professional with Xamarin.Android SDK 11.4.0.5

Solution

Always invoke the INavigation’s methods on the applications Main Thread. UI changes must go always on the UI thread of the application.

Create a class which wraps the INavigation presented by your Views. It’s handy to store a reference in this class to the Applications Current MainPage’s INavigation instance, so try to build your code to supply the actual INavigation Instance every time to this class when the application’s mainpage is set.

	public class NavigationDispatcher : INavigation
	{
		private INavigation _navigation;

		public IReadOnlyList<Page> ModalStack => _navigation?.ModalStack;

		public IReadOnlyList<Page> NavigationStack => _navigation?.NavigationStack;

		private void SetNavigation(INavigation navigation)
		{
			_navigation = navigation;
		}

		public void InsertPageBefore(Page page, Page before)
		{
			_ = Xamarin.Essentials.MainThread.InvokeOnMainThreadAsync(() =>
			  {
				  _navigation.InsertPageBefore(page, before);
			  });
		}

		public Task<Page> PopAsync()
		{
			return Xamarin.Essentials.MainThread.InvokeOnMainThreadAsync(async () =>
			{
				return await _navigation.PopAsync();
			});
		}

		public Task<Page> PopAsync(bool animated)
		{
			return Xamarin.Essentials.MainThread.InvokeOnMainThreadAsync(async () =>
			{
				return await _navigation.PopAsync(animated);
			});
		}

		public Task<Page> PopModalAsync()
		{
			return Xamarin.Essentials.MainThread.InvokeOnMainThreadAsync(async () =>
			{
				return await _navigation.PopModalAsync();
			});
		}

		public Task<Page> PopModalAsync(bool animated)
		{
			return Xamarin.Essentials.MainThread.InvokeOnMainThreadAsync(async () =>
			{
				return await _navigation.PopModalAsync(animated);
			});
		}

		public Task PopToRootAsync()
		{
			return Xamarin.Essentials.MainThread.InvokeOnMainThreadAsync(async () =>
			{
				await _navigation.PopToRootAsync();
			});
		}

		public Task PopToRootAsync(bool animated)
		{
			return Xamarin.Essentials.MainThread.InvokeOnMainThreadAsync(async () =>
			{
				await _navigation.PopToRootAsync(animated);
			});
		}

		public Task PushAsync(Page page)
		{
			return Xamarin.Essentials.MainThread.InvokeOnMainThreadAsync(async () =>
			{
				await _navigation.PushAsync(page);
			});
		}

		public Task PushAsync(Page page, bool animated)
		{
			return Xamarin.Essentials.MainThread.InvokeOnMainThreadAsync(async () =>
			{
				await _navigation.PushAsync(page, animated);
			});
		}

		public Task PushModalAsync(Page page)
		{
			return Xamarin.Essentials.MainThread.InvokeOnMainThreadAsync(async () =>
			{
				await _navigation.PushModalAsync(page);
			});
		}

		public Task PushModalAsync(Page page, bool animated)
		{
			return Xamarin.Essentials.MainThread.InvokeOnMainThreadAsync(async () =>
			{
				await _navigation.PushModalAsync(page, animated);
			});
		}

		public void RemovePage(Page page)
		{
			_ = Xamarin.Essentials.MainThread.InvokeOnMainThreadAsync(() =>
			  {
				  _navigation.RemovePage(page);
			  });
		}
	}

Remarks

Consider a check for the current thread in the methods body.
If they are being executed in the main thread, you won’t need to switch to the main again
.

Bug is reported on Github: https://github.com/xamarin/Xamarin.Forms/issues/11993

This content has 3 years. Some of the information in this post may be out of date or no longer work. Please, read this page keeping its age in your mind.