Xamarin Android如何实现将ImageView图片保存到系统相册
Xamarin.Android 图片保存功能实现方案
1 前置配置
- 新增字符串资源:在
Resources/values/Strings.xml中添加保存按钮的文本定义
<string name="Lbl_Save">保存图片</string>
- 权限配置:在
AndroidManifest.xml中添加对应存储权限,适配不同安卓版本:- Android 12及以下:添加
android.permission.WRITE_EXTERNAL_STORAGE权限 - Android 13及以上:添加
android.permission.READ_MEDIA_IMAGES权限
- Android 12及以下:添加
- 注意需要在调用保存功能前动态申请所需权限,权限通过后再执行保存逻辑。
2 核心代码修改
2.1 扩展OnSelection方法分支
在原有分享逻辑的后面新增保存功能的判断分支:
public async void OnSelection(MaterialDialog dialog, View itemView, int position, string itemString) { try { if (itemString == GetText(Resource.String.Lbl_MessageInfo)) { var intent = new Intent(this, typeof(MessageInfoActivity)); intent.PutExtra("UserId", Id); intent.PutExtra("MainChatColor", !string.IsNullOrEmpty(MesData.ChatColor) ? MesData.ChatColor : AppSettings.MainColor ?? AppSettings.MainColor); intent.PutExtra("SelectedItem", JsonConvert.SerializeObject(MesData)); StartActivity(intent); } else if (itemString == GetText(Resource.String.Lbl_Forward)) { var intent = new Intent(this, typeof(ForwardMessagesActivity)); intent.PutExtra("SelectedItem", JsonConvert.SerializeObject(MesData)); StartActivity(intent); } else if (itemString == GetText(Resource.String.Lbl_Share)) { string urlImage = MediaFile; var fileName = urlImage?.Split('/').Last(); await ShareFileImplementation.ShareRemoteFile(urlImage, urlImage, fileName, GetText(Resource.String.Lbl_SendTo)); } // 新增保存图片分支 else if (itemString == GetText(Resource.String.Lbl_Save)) { // 先检查权限,已授权再执行保存 if (CheckStoragePermission()) { string urlImage = MediaFile; var fileName = urlImage?.Split('/').Last(); await SaveImageToGallery(urlImage, fileName); Toast.MakeText(this, "图片已保存到相册", ToastLength.Short)?.Show(); } else { // 调用动态权限申请逻辑,申请通过后再触发保存即可 RequestStoragePermission(); } } } catch (Exception e) { Methods.DisplayReportResultTrack(e); Toast.MakeText(this, "保存失败,请重试", ToastLength.Short)?.Show(); } }
2.2 新增图片保存方法
在同一个Activity类中添加保存图片到系统相册的异步方法:
private async Task SaveImageToGallery(string imageUrl, string fileName) { using var httpClient = new HttpClient(); // 下载远程图片字节流 var imageBytes = await httpClient.GetByteArrayAsync(imageUrl); // 适配分区存储,插入到公共相册目录 var contentValues = new ContentValues(); contentValues.Put(MediaStore.Images.Media.InterfaceConsts.DisplayName, fileName); contentValues.Put(MediaStore.Images.Media.InterfaceConsts.MimeType, "image/jpeg"); if (Build.VERSION.SdkInt >= BuildVersionCodes.Q) { contentValues.Put(MediaStore.Images.Media.InterfaceConsts.RelativePath, "DCIM/" + GetString(Resource.String.ApplicationName)); contentValues.Put(MediaStore.Images.Media.InterfaceConsts.IsPending, true); } var resolver = ContentResolver; var uri = resolver.Insert(MediaStore.Images.Media.ExternalContentUri, contentValues); if (uri == null) return; // 写入图片数据 await using var stream = resolver.OpenOutputStream(uri); await stream.WriteAsync(imageBytes, 0, imageBytes.Length); if (Build.VERSION.SdkInt >= BuildVersionCodes.Q) { contentValues.Clear(); contentValues.Put(MediaStore.Images.Media.InterfaceConsts.IsPending, false); resolver.Update(uri, contentValues, null, null); } }
2.3 权限检查/申请辅助方法
如果项目没有现成的权限处理逻辑,可以添加以下简易实现:
private const int StoragePermissionRequestCode = 1001; private bool CheckStoragePermission() { if (Build.VERSION.SdkInt >= BuildVersionCodes.Tiramisu) { return CheckSelfPermission(Manifest.Permission.ReadMediaImages) == Permission.Granted; } return CheckSelfPermission(Manifest.Permission.WriteExternalStorage) == Permission.Granted; } private void RequestStoragePermission() { string[] permissions; if (Build.VERSION.SdkInt >= BuildVersionCodes.Tiramisu) { permissions = new[] { Manifest.Permission.ReadMediaImages }; } else { permissions = new[] { Manifest.Permission.WriteExternalStorage }; } RequestPermissions(permissions, StoragePermissionRequestCode); } // 重写权限申请结果回调 public override void OnRequestPermissionsResult(int requestCode, string[] permissions, [GeneratedEnum] Permission[] grantResults) { base.OnRequestPermissionsResult(requestCode, permissions, grantResults); if (requestCode == StoragePermissionRequestCode && grantResults.All(p => p == Permission.Granted)) { // 权限申请通过,重新触发保存逻辑 string urlImage = MediaFile; var fileName = urlImage?.Split('/').Last(); _ = SaveImageToGallery(urlImage, fileName); Toast.MakeText(this, "图片已保存到相册", ToastLength.Short)?.Show(); } else { Toast.MakeText(this, "需要存储权限才能保存图片", ToastLength.Short)?.Show(); } }
3 最后操作
在你生成圆点菜单的代码中,把"保存图片"的选项加入菜单列表即可完成功能接入。
内容的提问来源于stack exchange,提问作者user3261054
相关产品推荐
相关产品推荐

