如何在Kotlin中实现图片编辑后保存至系统相册?(附已实现的图片选择功能代码)
解决Android保存图片到系统相册的问题
看起来你已经搞定了图片选择和展示的环节,接下来咱们一步步解决保存(包括编辑后)图片到系统相册的问题~
1. 先搞定权限适配
不同Android版本的存储权限规则不一样,得针对性处理:
- Android 13(API 33)及以上:保存到系统相册不需要额外申请
WRITE_EXTERNAL_STORAGE权限,直接通过MediaStore写入即可。 - Android 10(API 29)到Android 12(API 32):同样不需要
WRITE_EXTERNAL_STORAGE,但如果你的targetSdkVersion是29及以上,记得在AndroidManifest.xml里加一句兼容配置:<application ... android:requestLegacyExternalStorage="true"> </application> - Android 9(API 28)及以下:需要先在
AndroidManifest.xml声明权限,再动态申请:<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="28"/>
2. 通用保存图片核心方法
不管是用户选的原图,还是你编辑后的图片,都可以用这个方法保存到相册:
private fun saveImageToGallery(bitmap: Bitmap, context: Context) { // 配置图片的存储信息(文件名、格式、存储路径) val contentValues = ContentValues().apply { put(MediaStore.Images.Media.DISPLAY_NAME, "my_edited_photo_${System.currentTimeMillis()}.jpg") put(MediaStore.Images.Media.MIME_TYPE, "image/jpeg") // Android Q及以上可以指定自定义相册文件夹 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { put(MediaStore.Images.Media.RELATIVE_PATH, Environment.DIRECTORY_PICTURES + "/MyAppAlbum") } } val resolver = context.contentResolver // 向媒体库插入图片记录 val uri = resolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues) uri?.let { try { // 打开输出流写入Bitmap resolver.openOutputStream(it)?.use { outputStream -> bitmap.compress(Bitmap.CompressFormat.JPEG, 90, outputStream) // 通知系统相册刷新,让图片立刻显示 context.sendBroadcast(Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, uri)) Toast.makeText(context, "图片保存成功啦", Toast.LENGTH_SHORT).show() } } catch (e: IOException) { e.printStackTrace() Toast.makeText(context, "保存失败了...", Toast.LENGTH_SHORT).show() } } }
3. 两种场景的保存实现
场景1:保存用户选取的原图
你已经能拿到图片的URI了,先把URI转成Bitmap,再调用上面的保存方法就行:
// 把你的ActivityResultCallback改写成这样 val getaction = registerForActivityResult( ActivityResultContracts.GetContent(), ActivityResultCallback { uri -> uri?.let { photo.setImageURI(it) // 将URI转换为Bitmap val originalBitmap = MediaStore.Images.Media.getBitmap(contentResolver, it) // 这里可以绑定到保存按钮的点击事件,比如先存起来等用户点保存再调用 // saveImageToGallery(originalBitmap, this) } } )
场景2:保存编辑后的图片
等你加上编辑功能后,编辑完成会得到一个Bitmap对象,直接传给保存方法就好,给你个简单示例:
// 假设这是你添加的编辑按钮点击事件 val editBtn = findViewById<Button>(R.id.edit_btn) editBtn.setOnClickListener { // 先把ImageView里的图片转成Bitmap val originalBitmap = photo.drawable.toBitmap() // 这里写你的编辑逻辑,比如加水印、裁剪、滤镜等,得到编辑后的Bitmap val editedBitmap = addWatermarkToBitmap(originalBitmap) // 保存编辑后的图片 saveImageToGallery(editedBitmap, this) } // 简单的编辑示例:给图片加文字水印 private fun addWatermarkToBitmap(bitmap: Bitmap): Bitmap { val editedBitmap = Bitmap.createBitmap(bitmap.width, bitmap.height, bitmap.config) val canvas = Canvas(editedBitmap) // 先绘制原图 canvas.drawBitmap(bitmap, 0f, 0f, null) // 绘制水印文字 val paint = Paint().apply { color = Color.WHITE textSize = 60f isAntiAlias = true shadowLayer = 5f } canvas.drawText("Edited by MyApp", 60f, bitmap.height - 60f, paint) return editedBitmap }
小提醒
- 处理Bitmap后记得调用
bitmap.recycle()释放内存,避免OOM。 - 如果要保存PNG格式,把
CompressFormat.JPEG改成CompressFormat.PNG,MIME_TYPE改成image/png。 - Android Q及以上自定义的文件夹会直接显示在系统相册里,用户找起来更方便。
内容的提问来源于stack exchange,提问作者Jan-86




