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

Android5调用openInputStream打开docx等文件报FileNotFoundException问题

问题根因

  • 该异常由Android 5.0(API 21)系统原生缺陷导致:系统Downloads文档提供者对非媒体类文件(docx、xlsx、mp3等不属于系统默认媒体库分类的文件)的Uri解析逻辑存在bug,直接传入ContentResolver.openInputStream()时无法正确映射到实际文件路径。图片、视频属于系统媒体库分类,返回的是媒体库Uri,不会触发该bug,因此运行正常。
  • 你的代码开启了EXTRA_ALLOW_MULTIPLE多选参数,当前仅通过data.data取Uri的逻辑在用户多选文件时会返回null,也可能引发同类异常。

修复步骤

  1. 补充存储权限声明,在AndroidManifest.xml中添加读外部存储权限:
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

Android 5.0访问非媒体类文件必须持有该权限,Android 6.0及以上版本需额外做动态权限申请。

  1. 修正onActivityResult中的Uri获取逻辑,兼容多选场景,同时对Android 5.0的Downloads Uri做特殊适配:
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
    super.onActivityResult(requestCode, resultCode, data)
    if (requestCode == FILE_REQUEST_CODE && resultCode == Activity.RESULT_OK && data != null) {
        val uriList = mutableListOf<Uri>()
        // 兼容多选场景取值
        data.clipData?.let { clipData ->
            for (i in 0 until clipData.itemCount) {
                uriList.add(clipData.getItemAt(i).uri)
            }
        } ?: run {
            data.data?.let { singleUri ->
                uriList.add(singleUri)
            }
        }
        // 遍历处理每个Uri
        uriList.forEach { uri ->
            try {
                val inputStream = if (Build.VERSION.SDK_INT == Build.VERSION_CODES.LOLLIPOP 
                    && uri.authority == "com.android.providers.downloads.documents") {
                    // 单独处理Android5.0 Downloads提供者的Uri
                    val docId = DocumentsContract.getDocumentId(uri)
                    val fileId = docId.split(":").last()
                    val downloadUri = ContentUris.withAppendedId(
                        Uri.parse("content://downloads/public_downloads"), 
                        fileId.toLong()
                    )
                    contentResolver.openInputStream(downloadUri)
                } else {
                    contentResolver.openInputStream(uri)
                }
                // 此处添加输入流后续处理逻辑
                inputStream?.close()
            } catch (e: FileNotFoundException) {
                e.printStackTrace()
                // 添加异常兜底逻辑
            }
        }
    }
}
  1. 可选优化方案:如果不需要兼容Android 4.4以下版本,可将Intent.ACTION_GET_CONTENT替换为Intent.ACTION_OPEN_DOCUMENT,该Action是Android 4.4之后官方推荐的文档访问方式,对系统文档提供者的适配兼容性更好,可避免该类原生缺陷。

内容的提问来源于stack exchange,提问作者Nadimuddin

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.08 17:39:04