Android 12及以上版本如何从Drawable文件夹获取图片URI?
Android 12+ 替代废弃的insertImage()实现图片分享
原来的insertImage()方法在Android 12及以上版本完全失效,原因是Scoped Storage限制以及该方法本身的实现不符合新的存储规范,导致生成的URI无法被其他分享应用正常访问,进而引发崩溃。以下是适配Android 12+的完整解决方案:
步骤1:实现Bitmap到MediaStore的保存方法
这个方法会将Bitmap写入MediaStore的公共图片目录,生成符合Scoped Storage要求的可共享URI:
import android.content.ContentResolver import android.content.ContentValues import android.graphics.Bitmap import android.net.Uri import android.os.Build import android.provider.MediaStore import java.io.OutputStream fun saveBitmapToMediaStore(contentResolver: ContentResolver, bitmap: Bitmap, displayName: String): Uri? { val contentValues = ContentValues().apply { put(MediaStore.Images.Media.DISPLAY_NAME, displayName) put(MediaStore.Images.Media.MIME_TYPE, "image/png") if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { put(MediaStore.Images.Media.RELATIVE_PATH, "Pictures/YourAppName") put(MediaStore.Images.Media.IS_PENDING, 1) } } var uri: Uri? = null try { uri = contentResolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues) uri?.let { contentResolver.openOutputStream(it)?.use { outputStream -> if (!bitmap.compress(Bitmap.CompressFormat.PNG, 100, outputStream)) { throw Exception("Failed to compress bitmap") } } if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { contentValues.clear() contentValues.put(MediaStore.Images.Media.IS_PENDING, 0) contentResolver.update(it, contentValues, null, null) } } } catch (e: Exception) { uri?.let { contentResolver.delete(it, null, null) } e.printStackTrace() } return uri }
步骤2:修改分享Intent代码
使用上面的方法获取URI,并添加必要的权限标志,确保其他应用能访问该URI:
val bitmap = BitmapFactory.decodeResource(resources, R.drawable.share) val shareUri = saveBitmapToMediaStore(contentResolver, bitmap, "share_image.png") shareUri?.let { val shareIntent = Intent(Intent.ACTION_SEND).apply { putExtra(Intent.EXTRA_TEXT, "hi") putExtra(Intent.EXTRA_STREAM, shareUri) type = "image/*" flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_GRANT_READ_URI_PERMISSION } startActivity(Intent.createChooser(shareIntent, "分享到")) } ?: run { // 处理保存失败的情况,比如提示用户 }
注意事项
- Android 10(API 29)及以上版本无需申请
WRITE_EXTERNAL_STORAGE权限,系统会自动处理;Android 9及以下版本需要在Manifest中声明该权限并动态申请。 - 代码中
"Pictures/YourAppName"可以替换为你自己的应用目录名,用于区分其他应用的图片。 - 记得处理Bitmap的回收,避免内存泄漏:
bitmap.recycle()(如果不再使用该Bitmap)。
内容的提问来源于stack exchange,提问作者Hary Hillary
相关产品推荐
相关产品推荐

