如何不使用insertImage()通过MediaStore获取ImageView的Bitmap路径实现分享
适配分区存储的Bitmap分享实现方案
错误原因
你的代码触发空指针的核心原因是:MediaStore.Images.Media.insertImage在Android 10(API 29)及以上版本已正式废弃,受分区存储规则限制,该方法会直接返回null,后续调用Uri.parse(null)就会抛出空指针异常。
实现步骤
1. 配置说明
无需申请额外读写存储权限,仅需确保AndroidManifest.xml中没有声明已过时的WRITE_EXTERNAL_STORAGE等权限(Android 10及以上写入公共媒体目录无需权限)。
2. 完整实现代码
binding.btnShareOne.setOnClickListener { val shareIntent = Intent(Intent.ACTION_SEND).apply { type = "image/*" // 给目标应用临时授予Uri读取权限,必须添加 addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) } // 从ImageView获取Bitmap val bitmap = binding.ivLayoutOne.drawable.toBitmap() // 构建MediaStore写入参数 val contentValues = ContentValues().apply { put(MediaStore.Images.Media.DISPLAY_NAME, "temp_share_${System.currentTimeMillis()}.png") put(MediaStore.Images.Media.MIME_TYPE, "image/png") if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { // 指定存储路径为公共相册下的TempShare目录 put(MediaStore.Images.Media.RELATIVE_PATH, "${Environment.DIRECTORY_PICTURES}/TempShare") // 标记图片为待写入状态,避免写入过程中被其他应用扫描到 put(MediaStore.Images.Media.IS_PENDING, 1) } } // 插入MediaStore获取Uri val contentResolver = contentResolver val imageUri = contentResolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues) imageUri?.let { uri -> // 将Bitmap写入到Uri对应的输出流 contentResolver.openOutputStream(uri)?.use { outputStream -> bitmap.compress(Bitmap.CompressFormat.PNG, 100, outputStream) } // 写入完成,更新标记允许其他应用访问 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { contentValues.clear() contentValues.put(MediaStore.Images.Media.IS_PENDING, 0) contentResolver.update(uri, contentValues, null, null) } // 携带Uri启动分享 shareIntent.putExtra(Intent.EXTRA_STREAM, uri) startActivity(Intent.createChooser(shareIntent, "Share Image")) } ?: run { // 处理Uri生成失败的情况,可自定义提示 Toast.makeText(this, "图片分享失败", Toast.LENGTH_SHORT).show() } }
可选优化
如果不需要长期保留分享的临时图片,可以在分享完成后调用contentResolver.delete(imageUri, null, null)删除对应文件,避免占用用户存储空间。
内容的提问来源于stack exchange,提问作者Debayan Ghosh Dastider
相关产品推荐
相关产品推荐

