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

Xamarin.Android高版本权限请求弹窗不显示问题求助

权限请求弹窗在Android 10(MIUI 12.0.8)中无法弹出的排查方案

问题概述

在Xamarin.Android项目中,旧版Android系统可正常弹出位置权限请求窗口,但在Android 10(QP1A)、MIUI Global 12.0.8设备上完全无法触发权限请求弹窗。已尝试多种权限请求代码方案,均未解决问题。

项目权限相关代码

AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="1" android:versionName="1.0" package="game.cassinova" android:installLocation="preferExternal">
    <uses-sdk android:minSdkVersion="21" android:targetSdkVersion="33" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
    <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />

    
    <application android:allowBackup="true" android:debuggable="true" android:label="@string/app_name" android:supportsRtl="true" android:theme="@style/AppTheme" android:icon="@drawable/logo">
        <service android:name=".LocationService" android:foregroundServiceType="location" />
    </application>
</manifest>

MainActivity.cs(权限相关片段)

protected override async void OnCreate(Bundle savedInstanceState)
{
...
 //第一种权限请求方法:
    string[] locationPermissions = new string[] {
        Manifest.Permission.AccessBackgroundLocation,
        Manifest.Permission.AccessFineLocation,
        Manifest.Permission.AccessCoarseLocation
    };

    bool shouldShowRequestPermissionRationale = ActivityCompat.ShouldShowRequestPermissionRationale(this, Manifest.Permission.AccessFineLocation) ||
                                 ActivityCompat.ShouldShowRequestPermissionRationale(this, Manifest.Permission.AccessCoarseLocation) ||
                                 ActivityCompat.ShouldShowRequestPermissionRationale(this, Manifest.Permission.AccessBackgroundLocation);
    CoordinatorLayout constraintLayout = FindViewById<CoordinatorLayout>(Resource.Id.mainLayout);
    

    if (shouldShowRequestPermissionRationale)
    {
        Snackbar.Make(constraintLayout, "请授予所有权限以保证应用正常运行。",
            Snackbar.LengthIndefinite)
            .SetAction("确定", new Action<Android.Views.View>(delegate (Android.Views.View obj) {
                ActivityCompat.RequestPermissions(this, locationPermissions, LocationContactsId);
            }))
            .Show();
    }
    else
    {
        ActivityCompat.RequestPermissions(this, locationPermissions, LocationContactsId);
    }


    //第二种权限请求方法:
    if (CheckSelfPermission(Manifest.Permission.AccessBackgroundLocation) == Permission.Denied || CheckSelfPermission(Manifest.Permission.AccessFineLocation) == Permission.Denied || CheckSelfPermission(Manifest.Permission.AccessCoarseLocation) == Permission.Denied || CheckSelfPermission(Manifest.Permission.ReadContacts) == Permission.Denied || CheckSelfPermission(Manifest.Permission.WriteContacts) == Permission.Denied || CheckSelfPermission(Manifest.Permission.ReadPhoneState) == Permission.Denied)
    {
        RequestPermissions(locationPermissions, LocationContactsId);
    }
    else
    {
...


public override async void OnRequestPermissionsResult(int requestCode, string[] permissions, [GeneratedEnum] Android.Content.PM.Permission[] grantResults)
{
    Xamarin.Essentials.Platform.OnRequestPermissionsResult(requestCode, permissions, grantResults);

    base.OnRequestPermissionsResult(requestCode, permissions, grantResults);
//权限授予后执行位置服务代码,但弹窗未弹出,从未进入此代码块
...

核心问题排查点

  • 权限请求顺序违规:Android 10及以上版本要求ACCESS_BACKGROUND_LOCATION必须在用户授予前台位置权限(ACCESS_FINE_LOCATION/ACCESS_COARSE_LOCATION)之后单独请求,不能和前台权限一次性提交。当前代码同时请求三个权限,触发系统拦截,导致弹窗无法显示。
  • 重复请求逻辑冲突:代码中存在两套权限请求逻辑,重复调用权限请求方法会导致系统权限流程混乱,需保留一套规范的请求逻辑。
  • MIUI系统特殊管控:MIUI 12对应用权限请求有额外拦截机制,需检查应用是否被系统开启"权限请求拦截";同时避免在OnCreate中过早触发权限请求,可延迟到OnResume或使用PostDelayed确保Activity完全初始化。
  • 权限判断与请求不匹配:第二种方法中判断了通讯录、电话状态等权限,但请求数组仅包含位置权限,逻辑不一致导致代码分支混乱,干扰权限请求流程。
  • Xamarin.Essentials初始化缺失:需确保在OnCreate中调用Xamarin.Essentials.Platform.Init(this, savedInstanceState);,否则权限回调无法正常处理。

修正后的权限请求示例

protected override void OnCreate(Bundle savedInstanceState)
{
    base.OnCreate(savedInstanceState);
    Xamarin.Essentials.Platform.Init(this, savedInstanceState); // 初始化Xamarin.Essentials
    SetContentView(Resource.Layout.Main);

    // 先请求前台位置权限
    RequestForegroundLocationPermissions();
}

private void RequestForegroundLocationPermissions()
{
    string[] foregroundPermissions = new string[] {
        Manifest.Permission.AccessFineLocation,
        Manifest.Permission.AccessCoarseLocation
    };

    if (ActivityCompat.ShouldShowRequestPermissionRationale(this, Manifest.Permission.AccessFineLocation))
    {
        Snackbar.Make(FindViewById<CoordinatorLayout>(Resource.Id.mainLayout), 
                      "需要位置权限以提供核心功能", Snackbar.LengthIndefinite)
                .SetAction("确定", v => ActivityCompat.RequestPermissions(this, foregroundPermissions, 100))
                .Show();
    }
    else
    {
        ActivityCompat.RequestPermissions(this, foregroundPermissions, 100);
    }
}

public override void OnRequestPermissionsResult(int requestCode, string[] permissions, Android.Content.PM.Permission[] grantResults)
{
    Xamarin.Essentials.Platform.OnRequestPermissionsResult(requestCode, permissions, grantResults);
    base.OnRequestPermissionsResult(requestCode, permissions, grantResults);

    if (requestCode == 100)
    {
        // 前台权限全部授予后,再请求后台位置权限
        if (grantResults.All(result => result == Permission.Granted))
        {
            RequestBackgroundLocationPermission();
        }
    }
    else if (requestCode == 200)
    {
        // 处理后台权限授予结果
        if (grantResults[0] == Permission.Granted)
        {
            // 启动位置服务等逻辑
        }
    }
}

private void RequestBackgroundLocationPermission()
{
    if (ActivityCompat.ShouldShowRequestPermissionRationale(this, Manifest.Permission.AccessBackgroundLocation))
    {
        Snackbar.Make(FindViewById<CoordinatorLayout>(Resource.Id.mainLayout), 
                      "需要后台位置权限以持续提供服务", Snackbar.LengthIndefinite)
                .SetAction("确定", v => ActivityCompat.RequestPermissions(this, new[] { Manifest.Permission.AccessBackgroundLocation }, 200))
                .Show();
    }
    else
    {
        ActivityCompat.RequestPermissions(this, new[] { Manifest.Permission.AccessBackgroundLocation }, 200);
    }
}

内容的提问来源于stack exchange,提问作者ibrahim çoban

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 09:34:59