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
相关产品推荐
相关产品推荐

