Xamarin Forms中Android 11用FilePicker上传PDF/DOC报空指针异常求助
Xamarin Forms Android 11 FilePicker 空指针异常解决方案
1 权限配置修正
该异常核心触发原因是Android 11(API 30+)引入了分区存储机制,旧版权限配置无法正常获取文件URI,首先需要在Android项目的AndroidManifest.xml中添加适配配置:
<!-- 基础文件读取权限 --> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <!-- Android 11+ 访问公共目录文件可选配置,上架应用商店需额外说明用途 --> <uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" /> <application android:requestLegacyExternalStorage="true" <!-- 其余原有application配置保持不变 --> > </application>
注意:如果应用需要上架Google Play,使用
MANAGE_EXTERNAL_STORAGE权限需要向平台说明应用核心功能必须用到所有文件访问权限,否则会被驳回。仅选择文档类文件时可只保留基础读取权限。
2 运行时权限申请
调用FilePicker前必须主动申请动态存储权限,不能依赖安装时授权,可直接使用Xamarin.Essentials的Permissions API实现:
// 检查读取权限 var readStatus = await Permissions.CheckStatusAsync<Permissions.StorageRead>(); if (readStatus != PermissionStatus.Granted) { readStatus = await Permissions.RequestAsync<Permissions.StorageRead>(); } // Android 11+ 特殊权限校验 if (DeviceInfo.Version.Major >= 11 && !Android.OS.Environment.IsExternalStorageManager) { // 跳转到系统设置页引导用户授权文件访问权限 var intent = new Android.Content.Intent(Android.Provider.Settings.ActionManageAppAllFilesAccessPermission); intent.SetData(Android.Net.Uri.Parse($"package:{Android.App.Application.Context.PackageName}")); Android.App.Application.Context.StartActivity(intent); } // 确认权限授予后再调用FilePicker逻辑 if (readStatus == PermissionStatus.Granted) { PickFile(); }
3 FilePicker调用逻辑修正
Android 11以上FilePicker返回的URI默认只有临时访问权限,且FullPath属性返回的是content协议URI而非本地真实路径,直接读取路径会触发空指针,需按如下方式调整:
async void PickFile() { var pickResult = await FilePicker.PickAsync(new PickOptions { // 配置允许选择的文件格式 FileTypes = new FilePickerFileType(new Dictionary<DevicePlatform, IEnumerable<string>> { { DevicePlatform.Android, new[] { "application/pdf", "application/msword", "application/vnd.openxmlformats-officedocument.wordprocessingml.document" } } }) }); if (pickResult != null) { #if ANDROID // 申请URI持久化访问权限,避免退出应用后权限失效 var uri = Android.Net.Uri.Parse(pickResult.FullPath); Android.App.Application.Context.ContentResolver.TakePersistableUriPermission( uri, Android.Content.ActivityFlags.GrantReadUriPermission | Android.Content.ActivityFlags.GrantWriteUriPermission ); #endif // 直接通过OpenReadAsync获取文件流用于上传,不要自行读取文件路径 using var fileStream = await pickResult.OpenReadAsync(); // 此处添加你的文件上传逻辑 } }
内容的提问来源于stack exchange,提问作者gadda raju
相关产品推荐
相关产品推荐

