Xamarin.Android应用适配SDK30存储权限被拒及Android11崩溃求助
Xamarin.Android SDK30适配+上架+Android11兼容解决方案
第一步:清理AndroidManifest配置
直接修改你的清单文件如下,删除不必要的权限和配置:
<!-- 移除以下4行配置 --> <!-- <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> --> <!-- <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> --> <!-- <uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" /> --> <!-- <protected-broadcast android:name="android.intent.action.MEDIA_MOUNTED" /> --> <!-- 保留业务需要的其他权限 --> <uses-permission android:name="android.permission.CAMERA" /> <uses-permission android:name="android.permission.FLASHLIGHT" /> <uses-permission android:name="android.permission.ACCESS_MOCK_LOCATION" /> <application android:allowBackup="true" android:label="AppName" android:icon="@mipmap/logoIconWhite" android:requestLegacyExternalStorage="true"> <!-- 补全FileProvider配置,${applicationId}会自动替换为你的应用包名 --> <provider android:name="androidx.core.content.FileProvider" android:authorities="${applicationId}.fileprovider" android:exported="false" android:grantUriPermissions="true"> <meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/file_paths" /> </provider> </application>
在Resources/xml文件夹下新建file_paths.xml文件,内容如下:
<?xml version="1.0" encoding="utf-8"?> <paths xmlns:android="http://schemas.android.com/apk/res/android"> <external-files-path name="AppName" path="AppName" /> </paths>
第二步:清理冗余业务代码
你原有代码中大量对公共存储根目录的操作是Android11崩溃的直接原因,且这些逻辑完全冗余,你实际存储PDF用的是应用专属目录,不需要读写公共存储。修改后的PDFDrawer方法如下:
private async void PDFDrawer(int pos) { UI ui = new UI(this); ui.ShowProgressDialog("", "Laden"); Console.WriteLine(invoices[pos].Obj["InvoiceID"].ToString()); // 原有的PDF获取逻辑保留 JsonValue json = await getPDFTask(invoices[pos].Obj["InvoiceID"].ToString()); var PDFResults = json["InvoicePDFResponse_InvoicePDF"]; var pdf = (string)PDFResults[0]["PDFString"]; byte[] pdfAsBytes = Convert.FromBase64String(pdf); // GetExternalFilesDir为应用专属目录,无需申请任何存储权限即可读写,符合谷歌存储政策 var pdfDir = Android.App.Application.Context.GetExternalFilesDir("AppName"); if (!pdfDir.Exists()) { pdfDir.Mkdirs(); } var externalPath = Path.Combine(pdfDir.AbsolutePath, "invoice.pdf"); File.WriteAllBytes(externalPath, pdfAsBytes); // 打开PDF OpenFile(externalPath); ui.HideProgressDialog(); }
第三步:适配文件打开逻辑
你需要通过FileProvider给第三方PDF阅读器授予文件访问权限,修改OpenFile方法如下:
private void OpenFile(string filePath) { var file = new Java.IO.File(filePath); var uri = FileProvider.GetUriForFile(this, PackageName + ".fileprovider", file); var intent = new Intent(Intent.ActionView); intent.SetDataAndType(uri, "application/pdf"); intent.AddFlags(ActivityFlags.GrantReadUriPermission); intent.AddFlags(ActivityFlags.NewTask); StartActivity(intent); }
适配说明
- 应用专属目录仅你的应用可访问,无需申请任何存储权限,完全符合谷歌存储政策,不会触发权限相关审核驳回
- 移除了所有公共存储读写操作,Android11及以上系统不会再出现权限异常崩溃
- 无敏感权限申请,审核通过率高
内容的提问来源于stack exchange,提问作者Justin van Brecht
相关产品推荐
相关产品推荐

