You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

MAUI多权限请求失败问题(原Xamarin.Essentials可正常运行)

MAUI权限请求RequestAsync await后无响应,需多次启动才能正常执行

问题现象

从Xamarin.Essentials迁移至MAUI后,调用Permissions.RequestAsync时,await之后的代码完全不执行(示例中的Serilog.Log.Error("This is never run!")从未输出)。每次启动应用仅能完成一个权限的请求流程,需连续启动4次后,所有权限都被授予,代码才能完整执行。

调用代码:

await Utilities.AppPermissions.RequestAppPermissions();

权限请求代码:

public static async Task<bool> RequestAppPermissions()
{
    try
    {
        //First round of location permissions
        Serilog.Log.Debug($"Check 'LocationWhenInUse' Permission");
        if (await Permissions.CheckStatusAsync<Permissions.LocationWhenInUse>() != PermissionStatus.Granted)
        {
            Serilog.Log.Debug($"Request'LocationWhenInUse' Permission");
            await Permissions.RequestAsync<Permissions.LocationWhenInUse>();
            Serilog.Log.Error("This is never run!");
        }
       
        //Request LocationAlways Permission
        Serilog.Log.Debug($"Check 'LocationAlways' Permission");
        if (await Permissions.CheckStatusAsync<Permissions.LocationAlways>() != PermissionStatus.Granted)
        {
            Serilog.Log.Debug($"Request 'LocationAlways' Permission");
            await Permissions.RequestAsync<Permissions.LocationAlways>();
            Serilog.Log.Error("This is never run!");
        }

        //Notifications
        if (OperatingSystem.IsAndroidVersionAtLeast(33))
        {
            Serilog.Log.Debug($"Check 'PostNotifications' Permission");
            if (await Permissions.CheckStatusAsync<Permissions.PostNotifications>() != PermissionStatus.Granted)
            {
                Serilog.Log.Debug($"Request 'PostNotifications' Permission");
                await Permissions.RequestAsync<Permissions.PostNotifications>();
            }
        }

        return true;
    }
    catch (Exception ex)
    {
        Serilog.Log.Fatal(ex, "Failed to request permissions");
        return false;
    }
}

环境信息:

  • 所有NuGet包已更新至最新版本(截至9月15日)
  • Visual Studio 2022 17.11.3

问题分析

  • UI线程上下文缺失:MAUI的权限请求API必须在UI主线程执行,若调用时处于非UI线程,await后无法正确切换回原上下文,导致后续代码挂起。
  • 权限依赖未处理:LocationAlways权限需要LocationWhenInUse已被授予,连续无依赖的请求会打乱MAUI的权限处理逻辑,引发阻塞。
  • 无状态反馈处理:原代码未接收RequestAsync的返回状态,也未处理用户拒绝权限的场景,导致流程中断后无法继续。

解决方案

1. 强制在UI主线程执行权限请求

用MainThread.InvokeOnMainThreadAsync包装整个权限请求逻辑,确保上下文正确:

public static async Task<bool> RequestAppPermissions()
{
    return await MainThread.InvokeOnMainThreadAsync(async () =>
    {
        try
        {
            // 处理LocationWhenInUse权限
            var locationWhenInUseStatus = await Permissions.CheckStatusAsync<Permissions.LocationWhenInUse>();
            Serilog.Log.Debug($"Check 'LocationWhenInUse' Permission: {locationWhenInUseStatus}");
            if (locationWhenInUseStatus != PermissionStatus.Granted)
            {
                Serilog.Log.Debug($"Request 'LocationWhenInUse' Permission");
                locationWhenInUseStatus = await Permissions.RequestAsync<Permissions.LocationWhenInUse>();
                Serilog.Log.Debug($"LocationWhenInUse Permission Result: {locationWhenInUseStatus}");
                if (locationWhenInUseStatus == PermissionStatus.Denied)
                {
                    Serilog.Log.Warning("LocationWhenInUse permission denied");
                    return false;
                }
            }

            // 依赖LocationWhenInUse授予后,再请求LocationAlways
            if (locationWhenInUseStatus == PermissionStatus.Granted)
            {
                var locationAlwaysStatus = await Permissions.CheckStatusAsync<Permissions.LocationAlways>();
                Serilog.Log.Debug($"Check 'LocationAlways' Permission: {locationAlwaysStatus}");
                if (locationAlwaysStatus != PermissionStatus.Granted)
                {
                    Serilog.Log.Debug($"Request 'LocationAlways' Permission");
                    locationAlwaysStatus = await Permissions.RequestAsync<Permissions.LocationAlways>();
                    Serilog.Log.Debug($"LocationAlways Permission Result: {locationAlwaysStatus}");
                }
            }

            // 处理Android 13+通知权限
            if (OperatingSystem.IsAndroidVersionAtLeast(33))
            {
                var notificationStatus = await Permissions.CheckStatusAsync<Permissions.PostNotifications>();
                Serilog.Log.Debug($"Check 'PostNotifications' Permission: {notificationStatus}");
                if (notificationStatus != PermissionStatus.Granted)
                {
                    Serilog.Log.Debug($"Request 'PostNotifications' Permission");
                    notificationStatus = await Permissions.RequestAsync<Permissions.PostNotifications>();
                    Serilog.Log.Debug($"PostNotifications Permission Result: {notificationStatus}");
                }
            }

            return true;
        }
        catch (Exception ex)
        {
            Serilog.Log.Fatal(ex, "Failed to request permissions");
            return false;
        }
    });
}

2. 修正Android权限配置

确认Platforms/Android/Properties/AndroidManifest.xml已添加完整权限声明:

<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />

3. 验证步骤

  1. 清理解决方案并重新生成
  2. 卸载设备上的现有应用(避免缓存权限状态干扰)
  3. 重新部署应用,观察权限请求流程及日志输出
  4. 确认每个权限请求后的后续代码正常执行

内容的提问来源于stack exchange,提问作者JohnJore

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.18 07:02:03