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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 15:48:23