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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 01:45:35