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

Android 13中使用FileProvider打开文件遇「文件未找到」错误求助

问题原因分析
  • FileProvider路径配置错误:你的FileProvider可能未正确映射公共Download目录。Android 10及以上版本中,公共存储目录需要使用<external-public-path>标签配置,若paths.xml里用了错误的标签(比如<external-path>),会导致FileProvider生成的URI无法被正确解析——即便本地文件存在,第三方应用也找不到对应资源。
  • 系统应用对自定义FileProvider的兼容性问题:部分系统自带的HTML查看器仅信任系统级Content Provider(如MediaStore)的URI,对第三方App的FileProvider URI支持不足,导致无法识别路径。
  • Android 13存储权限限制:Android 13收紧了公共存储非媒体文件的访问权限,仅通过已废弃的READ_EXTERNAL_STORAGE无法直接访问Download目录的文本文件;file.exists()能检测到文件是因为该方法不严格校验权限,但实际读取时会被系统限制。
解决方案建议

1. 修正FileProvider的路径配置

确保res/xml/file_paths.xml正确映射公共Download目录:

<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <!-- 映射公共Download目录 -->
    <external-public-path 
        android:name="Download" 
        android:path="Download" />
</paths>

同时确认AndroidManifest中FileProvider的配置正确引用该文件:

<provider
    android:name="androidx.core.content.FileProvider"
    android:authorities="com.telit.downloaddemo.fileprovider"
    android:exported="false"
    android:grantUriPermissions="true">
    <meta-data
        android:name="android.support.FILE_PROVIDER_PATHS"
        android:resource="@xml/file_paths" />
</provider>

2. 改用MediaStore获取系统信任的Content URI

系统应用对MediaStore生成的URI兼容性更好,通过查询MediaStore获取Download目录下文件的URI:

private fun openFile(fileName: String) {
    // 先通过MediaStore获取文件URI
    val mediaUri = getMediaStoreDownloadUri(fileName)
    if (mediaUri != null) {
        val intent = Intent(Intent.ACTION_VIEW).apply {
            setDataAndType(mediaUri, "text/plain")
            addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
        }
        try {
            startActivity(intent)
        } catch (e: ActivityNotFoundException) {
            Toast.makeText(this, "无可用应用打开文件", Toast.LENGTH_SHORT).show()
        } catch (e: Exception) {
            Log.e(TAG, "打开文件失败: ${e.message}", e)
        }
    } else {
        Toast.makeText(this, "文件未找到", Toast.LENGTH_SHORT).show()
    }
}

private fun getMediaStoreDownloadUri(fileName: String): Uri? {
    val projection = arrayOf(MediaStore.Downloads._ID)
    val selection = "${MediaStore.Downloads.DISPLAY_NAME} = ?"
    val selectionArgs = arrayOf(fileName)
    val sortOrder = "${MediaStore.Downloads.DATE_ADDED} DESC"

    contentResolver.query(
        MediaStore.Downloads.EXTERNAL_CONTENT_URI,
        projection,
        selection,
        selectionArgs,
        sortOrder
    )?.use { cursor ->
        if (cursor.moveToFirst()) {
            val id = cursor.getLong(cursor.getColumnIndexOrThrow(MediaStore.Downloads._ID))
            return ContentUris.withAppendedId(MediaStore.Downloads.EXTERNAL_CONTENT_URI, id)
        }
    }
    return null
}

该方法无需额外申请特殊权限,且系统应用能正常识别URI。

3. 备选:申请MANAGE_EXTERNAL_STORAGE权限(不推荐)

若上述方法无效,可申请全文件访问权限,但该权限属于特殊权限,需要用户手动在设置中开启,且Google Play审核可能限制此类权限的使用:

  • 在AndroidManifest中添加权限:
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />
  • 代码中引导用户开启权限:
if (!Environment.isExternalStorageManager()) {
    val intent = Intent(Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION)
    intent.data = Uri.parse("package:$packageName")
    startActivity(intent)
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 08:34:58