András Tóth‘s professional blog
banditoth.net

Hey there 👋, I’m banditoth a .NET MAUI developer from Hungary.
I write about software development with .NET technologies.

You can find me on:
LinkedIn | Github | StackOverflow | X / Twitter | Threads

Tag: android

  • Xamarin Forms: White screen between page push and pop solved

    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.

    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

  • Xamarin Forms: Close applications programmatically

    This content has 4 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.

    In some scenarios, we need to programmatically close our application. We can do it in our common code with Xamarin Forms too. Buuuuuut …….

    Can we close an iOS application?

    There is no API provided for gracefully terminating an iOS application.

    In iOS, the user presses the Home button to close applications. Should your application have conditions in which it cannot provide its intended function, the recommended approach is to display an alert for the user that indicates the nature of the problem and possible actions the user could take — turning on WiFi, enabling Location Services, etc. Allow the user to terminate the application at their own discretion.

    Do not call the exit function. Applications calling exit will appear to the user to have crashed, rather than performing a graceful termination and animating back to the Home screen.

    Source: https://developer.apple.com/library/archive/qa/qa1561/_index.html

    Close on Android from Forms code

    There is one important place to implement closing apps from code: When you are handling back button presses by yourself.

    Imagine, that you have a main screen, which is the root page. When a users presses the hardware back button you should display a confirmer, that says “Do you really want to close the application?”

    If the user choose yes, you should make a call like this:

    					DependencyService.Get<IPlatformSpecificService>().CloseApplication();
    

    The definition of the IPlatformSpecificService should be look like this:

    	public interface IPlatformSpecificService
    	{
    		void CloseApplication();
    	}
    

    And the Android implementation of the IPlatformSpecificService should be something like:

    using Plugin.CurrentActivity;
    
    [assembly: Dependency(typeof(DeviceSpecificService))]
    namespace AnAwesomeCompany.AGreatProduct.Droid.DependencyServices
    {
    	public class PlatformSpecificService: IPlatformSpecificService
    	{
    		public void CloseApplication()
    		{
    			CrossCurrentActivity.Current.Activity.FinishAndRemoveTask();
    		}
    	}
    }
    

    Activity supports a lot of closing methods of the application. FinishAndRemoveTask will clear the app from the recents list too.

    Take a look at official Android documentation at: https://developer.android.com/reference/android/app/Activity#finishAndRemoveTask()

  • Xamarin.Android : Location of the keystore files

    This content has 4 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.

    The location of the keystores created in Visual Studio (Windows) is:

    %appdata%\..\Local\Xamarin\Mono for Android\Keystore
    

    Press CTRL + R (or get the Run window somehow), and enter the path above

  • Xamarin.Android: Missing aapt.exe

    This content has 4 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.

    When trying to deploy an application to simulator or device, Visual Studio gives the following error:

    Cannot find `aapt.exe`. Please install the Android SDK Build-Tools package with the `C:\Program Files (x86)\Android\android-sdk\tools\android.bat` program.
    

    To solve this problem you sould go to Visual Studio’s Tools then Android and select SDK Manager option.

    Navigate to this option

    It will give an error dialog, that the SDK tool files are corrupted. Click repair.

    Click on Repair

    The mentioned batch command in the error message is deprecated by the way.

    Microsoft Windows [Version 10.0.19042.804]
    (c) 2020 Microsoft Corporation. All rights reserved.
    
    C:\Users\banditoth>cd C:\Program Files (x86)\Android\android-sdk\tools\
    
    C:\Program Files (x86)\Android\android-sdk\tools>android.bat
    **************************************************************************
    The "android" command is deprecated.
    For manual SDK, AVD, and project management, please use Android Studio.
    For command-line tools, use tools\bin\sdkmanager.bat
    and tools\bin\avdmanager.bat
    **************************************************************************
    
    Invalid or unsupported command ""
    
    Supported commands are:
    android list target
    android list avd
    android list device
    android create avd
    android move avd
    android delete avd
    android list sdk
    android update sdk
    
    C:\Program Files (x86)\Android\android-sdk\tools>
    
    
  • [Fun] Android: My favourite exception ever

    This content has 4 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.
    10-12 11:31:09.871 E/AndroidRuntime(10069): DeadSystemException: The system died; earlier logs will point to the root cause