Android笔记分享异常:重启APP后含图片笔记无法分享
问题核心原因
你保存的是第三方应用(如MIUI图库)提供的content://类型URI,这类URI的临时读取权限仅在你的APP进程存活期间有效。当APP重启后,系统会回收这些临时权限,导致分享时目标应用无法访问图片资源,进而出现无法打开的问题。
解决方案
以下两种方案均可解决问题,优先推荐方案1,因为兼容性和可靠性更强:
方案1:将图片复制到APP私有目录,用FileProvider生成持久URI
把第三方URI对应的图片复制到你的APP外部私有目录,再通过FileProvider生成可持久访问的URI,这样APP重启后权限依然有效。
1. 编写文件复制工具方法
private fun copyFileToPrivateDir(context: Context, sourceUri: Uri): File? { return try { val inputStream = context.contentResolver.openInputStream(sourceUri) ?: return null // 生成唯一文件名避免重复 val fileName = "shared_note_${System.currentTimeMillis()}.jpg" // 保存到APP外部私有图片目录 val destDir = context.getExternalFilesDir(Environment.DIRECTORY_PICTURES) ?: return null val destFile = File(destDir, fileName) inputStream.copyTo(FileOutputStream(destFile)) inputStream.close() destFile } catch (e: Exception) { e.printStackTrace() null } }
2. 修改分享方法
private fun shareNote(title: String, description: String, imageUriList: MutableList<String>) { val shareIntent: Intent = Intent().apply { action = Intent.ACTION_SEND_MULTIPLE putExtra(Intent.EXTRA_SUBJECT, title) putExtra(Intent.EXTRA_TEXT, "$title\n\n$description") val uriList = ArrayList<Uri>() if (imageUriList.isNotEmpty()) { imageUriList.forEach { uriString -> val sourceUri = Uri.parse(uriString) val destFile = copyFileToPrivateDir(requireContext(), sourceUri) destFile?.let { // 用FileProvider生成合法的content URI val fileUri = FileProvider.getUriForFile( requireContext(), "com.notes.purenoteit.fileprovider", it ) uriList.add(fileUri) addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) } } type = "image/*" putParcelableArrayListExtra(Intent.EXTRA_STREAM, uriList) } else { type = "text/plain" } } try { startActivity(Intent.createChooser(shareIntent, "Share Note")) } catch (e: Exception) { e.printStackTrace() requireContext().showToastShort("Sharing failed") } }
方案2:保存文件绝对路径而非第三方Content URI
如果图片来自本地存储,可通过ContentResolver获取文件的绝对路径并保存,分享时再转成FileProvider的URI:
1. 获取文件绝对路径工具方法
private fun getFilePathFromUri(context: Context, uri: Uri): String? { val cursor = context.contentResolver.query(uri, null, null, null, null) cursor?.use { if (it.moveToFirst()) { val columnIndex = it.getColumnIndexOrThrow(MediaStore.Images.Media.DATA) return it.getString(columnIndex) } } return null }
2. 分享时转换URI
在处理图片URI时,替换为绝对路径生成的FileProvider URI:
val sourceUri = Uri.parse(uriString) val filePath = getFilePathFromUri(requireContext(), sourceUri) filePath?.let { val file = File(it) val fileUri = FileProvider.getUriForFile( requireContext(), "com.notes.purenoteit.fileprovider", file ) uriList.add(fileUri) }
注意事项
- 定期清理APP私有目录下的复制文件,避免占用过多存储
- 确保
AndroidManifest.xml中FileProvider的authorities与代码中一致 - Android 10及以上版本,直接访问文件路径可能受限,优先使用方案1
内容的提问来源于stack exchange,提问作者Ömer Seyfettin Yavuzyiğit
相关产品推荐
相关产品推荐

