.NET MAUI - “必须在主线程上调用权限请求”

ric*_*er1 3 c# android maui

我很困惑,如果需要异步,我应该如何在 Android 应用程序的主线程上请求权限访问。我想在我的应用程序打开后立即执行此操作,但我收到以下错误:"Permission request must be invoked on main thread."我该如何执行此操作?我的理解是,这RequestAsync需要一个单独的线程(因为它是一个异步方法调用)。

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

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>
Run Code Online (Sandbox Code Playgroud)

AppShell.xaml.cs:

namespace CellularSignal1;

#if ANDROID
public partial class AppShell : Shell
{
    public AppShell()
    {
        InitializeComponent();
    }
}
    
#endif
Run Code Online (Sandbox Code Playgroud)

Jul*_*ian 6

您应该OnAppearing()覆盖方法asyncawait调用。不需要通过以下方式创建的线程池Task.Run()线程:

protected override async void OnAppearing()
{
    var resultCheck = await CheckLocationPermission();
    var resultRequest = await RequestLocationPermission();
}
Run Code Online (Sandbox Code Playgroud)

一般来说,当你遇到像上面提到的主线程这样的错误时,并不意味着代码需要它自己的线程,而是代码必须在MainThread,这是一个特殊的线程上执行。

您可以从任何其他线程(不是主线程)调用线程上的代码,如下所示:

private async Task SomeMethodAsync()
{
    await MainThread.InvokeOnMainThreadAsync(async () => 
    {
        var resultCheck = await CheckLocationPermission();
        var resultRequest = await RequestLocationPermission();
    });
}
Run Code Online (Sandbox Code Playgroud)

注意:在您的情况下,后者不是必需的,因为它OnAppearing()已经在主线程上执行。