I am confused on how I am supposed to request permissions access on the main thread of an android app if it needs to be async. I want to do this as soon as my application opens, but as is I am getting the following error: "Permission request must be invoked on main thread." How do I do this? My understanding is that RequestAsync requires a separate thread (Since it's an async method call).
public partial class SplashPage : ContentPage
{
PermissionStatus LocationPermission;
public SplashPage()
{
InitializeComponent();
LocationPermission = PermissionStatus.Unknown;
}
protected override void OnAppearing()
{
var result = Task.Run(async () => await CheckLocationPermission());
result.Wait();
var resultval = result.Result;
result = Task.Run(async () => await RequestLocationPermission());
result.Wait();
}
public async Task<PermissionStatus> CheckLocationPermission()
{
LocationPermission = await Permissions.CheckStatusAsync<Permissions.LocationWhenInUse>();
return LocationPermission;
}
public async Task<PermissionStatus> RequestLocationPermission()
{
try
{
if (LocationPermission == PermissionStatus.Granted)
return LocationPermission;
if (Permissions.ShouldShowRationale<Permissions.LocationWhenInUse>())
{
await Shell.Current.DisplayAlert("Needs Permissions", "BECAUSE!!!", "OK");
}
LocationPermission = await Permissions.RequestAsync<Permissions.LocationWhenInUse>();
}
catch (Exception ex)
{
//Error that permissions request must be on main thread **
Console.WriteLine(ex.Message);
}
return LocationPermission;
}
}
AppShell.xaml:
<?xml version="1.0" encoding="UTF-8" ?>
<Shell
x:Class="CellularSignal1.AppShell"
xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:CellularSignal1"
Shell.FlyoutBehavior="Disabled">
<TabBar x:Name="MyTabBar">
<Tab x:Name="CellularInfo" Title="Cellular Info">
<ShellContent ContentTemplate="{DataTemplate local:SplashPage}" Route="SplashPage"/>
<ShellContent ContentTemplate="{DataTemplate local:CellularInfo}" Route="CellularInfo"/>
<ShellContent ContentTemplate="{DataTemplate local:BSInfo}" Route="BSInfo"/>
</Tab>
</TabBar>
</Shell>
AppShell.xaml.cs:
namespace CellularSignal1;
#if ANDROID
public partial class AppShell : Shell
{
public AppShell()
{
InitializeComponent();
}
}
#endif
You are using Essentials, so you could InvokeOnMainThreadAsync. I usually use this helper to do the same:
public static class PermissionsHelper
{
public static async Task<PermissionStatus> CheckAndRequestPermissionAsync<TPermission>()
where TPermission : BasePermission, new()
{
return await MainThread.InvokeOnMainThreadAsync(async () =>
{
TPermission permission = new TPermission();
var status = await permission.CheckStatusAsync();
if (status != PermissionStatus.Granted)
{
status = await permission.RequestAsync();
}
return status;
});
}
}
Usage:
var status = await PermissionsHelper.CheckAndRequestPermissionAsync<Permissions.LocationWhenInUse>();
if (status != PermissionStatus.Granted)
{
//whatever you like
}
You should make the OnAppearing() method override async and await the calls. There's no need for the thread pool thread created by Task.Run():
protected override async void OnAppearing()
{
var resultCheck = await CheckLocationPermission();
var resultRequest = await RequestLocationPermission();
}
In general, when you encounter an error like the one above referring to the main thread, it doesn't mean that the code requires its own thread, but rather that the code must be executed on the MainThread, which is a special thread.
You can invoke code on the main thread from any other thread, which isn't the main thread, like this:
private async Task SomeMethodAsync()
{
await MainThread.InvokeOnMainThreadAsync(async () =>
{
var resultCheck = await CheckLocationPermission();
var resultRequest = await RequestLocationPermission();
});
}
Note: In your case, the latter shouldn't be necessary, because OnAppearing() already executes on the main thread.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With