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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 05:00:14