如何获取Android drawable资源的file://格式Uri适配Firebase Storage
Android Drawable资源转file协议Uri方案(无Bitmap OOM风险)
核心思路
直接通过IO流将APK内的drawable资源拷贝到应用私有缓存目录,全程不加载Bitmap,内存占用极低,完全避免OOM问题,最终生成的缓存文件可直接输出file://开头的Uri供Firebase Storage使用。
实现代码
import android.content.Context import android.net.Uri import androidx.annotation.DrawableRes import java.io.File import java.io.FileOutputStream import java.io.InputStream fun getDrawableAsFileUri(context: Context, @DrawableRes drawableResId: Int): Uri { // 以drawable资源名作为缓存文件名,避免重复生成 val fileName = context.resources.getResourceEntryName(drawableResId) val cacheFile = File(context.cacheDir, "$fileName.png") // 已生成过的缓存直接复用,减少IO操作 if (!cacheFile.exists()) { var inputStream: InputStream? = null var outputStream: FileOutputStream? = null try { inputStream = context.resources.openRawResource(drawableResId) outputStream = FileOutputStream(cacheFile) val buffer = ByteArray(8 * 1024) // 8KB缓冲区,内存占用极低 var readLength: Int while (inputStream.read(buffer).also { readLength = it } != -1) { outputStream.write(buffer, 0, readLength) } outputStream.flush() } finally { inputStream?.close() outputStream?.close() } } return Uri.fromFile(cacheFile) }
注意事项
- 该方案仅对png、jpg、gif等位图格式的drawable资源有效,如果是矢量图(VectorDrawable)需要先渲染成位图再写入缓存,该场景下不可避免要用到Bitmap操作,可通过控制采样率降低OOM风险
- 缓存文件会长期存在于应用缓存目录,如果需要清理可在应用启动时统一删除缓存目录下的对应资源文件
- 仅用于Firebase Storage上传场景时,生成的
file://Uri无需额外适配Android 7.0的FileProvider规则,可直接传入Firebase Storage的上传接口使用
内容的提问来源于stack exchange,提问作者Bitwise DEVS
相关产品推荐
相关产品推荐

