Xamarin Forms图片下载至设备问题:Android12及iOS适配异常
Xamarin Forms 图片下载问题解决方案
Android 12+ 下载失败修复
- 适配Scoped Storage机制:Android 10及以上启用了Scoped Storage,12+对文件访问限制更严格,不能再用旧方式直接写入公共目录,必须通过
MediaStore操作媒体文件。 - 权限适配:Android 13+需申请
READ_MEDIA_IMAGES权限,12及以下保留WRITE_EXTERNAL_STORAGE权限;android:requestLegacyExternalStorage="true"仅兼容到Android 11,12+必须弃用。 - 修改
AndroidDownloader实现:public async Task DownloadImageAsync(string url, string fileName) { using (var httpClient = new HttpClient()) { var imageBytes = await httpClient.GetByteArrayAsync(url); var contentResolver = Android.App.Application.Context.ContentResolver; var imageUri = MediaStore.Images.Media.ExternalContentUri; var values = new ContentValues(); values.Put(MediaStore.Images.Media.Columns.DisplayName, fileName); values.Put(MediaStore.Images.Media.Columns.MimeType, "image/jpeg"); values.Put(MediaStore.Images.Media.Columns.RelativePath, "Pictures/YourAppFolder"); var targetUri = contentResolver.Insert(imageUri, values); using (var stream = contentResolver.OpenOutputStream(targetUri)) { await stream.WriteAsync(imageBytes, 0, imageBytes.Length); } // 通知系统扫描文件,让图库立即识别 MediaScannerConnection.ScanFile(Android.App.Application.Context, new[] { targetUri.Path }, null, null); } } - 动态权限申请:下载前需根据系统版本动态申请对应权限,确保权限通过后再执行下载逻辑。
iOS 下载失败修复
- 路径与权限调整:iOS需将图片保存到系统相册才能在图库显示,需确保
Info.plist已配置NSPhotoLibraryAddUsageDescription权限描述。 - 修改
IosDownloader实现:public async Task DownloadImageAsync(string url, string fileName) { using (var httpClient = new HttpClient()) { var imageBytes = await httpClient.GetByteArrayAsync(url); var tempPath = Path.Combine(Path.GetTempPath(), fileName); File.WriteAllBytes(tempPath, imageBytes); // 请求相册权限并保存图片 var authStatus = await PHPhotoLibrary.RequestAuthorizationAsync(); if (authStatus == PHAuthorizationStatus.Authorized) { PHPhotoLibrary.SharedPhotoLibrary.PerformChanges(() => { var creationRequest = PHAssetCreationRequest.CreateAsset(); creationRequest.AddResource(PHAssetResourceType.Photo, NSData.FromFile(tempPath), null); }, (success, error) => { if (!success) { // 处理保存失败逻辑 } // 删除临时文件 File.Delete(tempPath); }); } } }
确保图片在图库/文件管理器可见
- Android:通过
MediaScannerConnection.ScanFile通知系统扫描新增文件,强制图库刷新显示。 - iOS:直接保存到系统相册,图库默认会显示;若需在文件管理器访问,可开启
UIFileSharingEnabled(Info.plist中设为YES),将图片保存到Documents目录,但此方式图库不会识别,建议优先保存到相册。 - Xamarin Forms端权限校验优化:
private async void DownloadBtn_Clicked(object sender, EventArgs e) { bool hasPermission = false; if (DeviceInfo.Platform == DevicePlatform.Android) { if (Android.OS.Build.VERSION.SdkInt >= Android.OS.BuildVersionCodes.Tiramisu) { hasPermission = await Permissions.CheckStatusAsync<Permissions.MediaWrite>() == PermissionStatus.Granted; if (!hasPermission) hasPermission = await Permissions.RequestAsync<Permissions.MediaWrite>() == PermissionStatus.Granted; } else { hasPermission = await Permissions.CheckStatusAsync<Permissions.StorageWrite>() == PermissionStatus.Granted; if (!hasPermission) hasPermission = await Permissions.RequestAsync<Permissions.StorageWrite>() == PermissionStatus.Granted; } } else if (DeviceInfo.Platform == DevicePlatform.iOS) { var status = await Permissions.CheckStatusAsync<Permissions.PhotosAddOnly>(); hasPermission = status == PermissionStatus.Granted; if (!hasPermission) hasPermission = await Permissions.RequestAsync<Permissions.PhotosAddOnly>() == PermissionStatus.Granted; } if (hasPermission) { var downloader = DependencyService.Get<IDownloader>(); await downloader.DownloadImageAsync("https://your-image-url.jpg", "saved-image.jpg"); } else { await DisplayAlert("提示", "需要存储/相册权限才能完成下载", "确定"); } }
内容的提问来源于stack exchange,提问作者Sreejith Sree
相关产品推荐
相关产品推荐

