有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

安卓文件提供商java。lang.IllegalArgumentException:未能找到包含

我试图使用FileProvider公开URI,但始终遇到以下异常:

java.lang.IllegalArgumentException: Failed to find configured root that contains /data/data/com.example.安卓.development/cache/images/background.png

AndroidManifest。xml:

<provider
    安卓:name="安卓x.core.content.FileProvider"
    安卓:authorities="${applicationId}.provider"
    安卓:exported="false"
    安卓:grantUriPermissions="true">
    <meta-data
        安卓:name="安卓.support.FILE_PROVIDER_PATHS"
        安卓:resource="@xml/provider_paths"/>
</provider>

提供者路径。xml:

<paths>
    <cache-path name="images" path="images/"/>
</paths>

保存文件:

fun cache(context: Context, bitmap: Bitmap, fileName: String) {
    val filePath = File(context.cacheDir, "images")
    val file = File(filePath, fileName)
    try {
        filePath.mkdirs()
        val fos = FileOutputStream(file)
        bitmap.compress(Bitmap.CompressFormat.PNG, 100, fos)
        fos.close()
    } catch (e: IOException) {
        throw RuntimeException(e)
    }
}

获取URI:

fun getUri(context: Context, fileName: String): Uri {
    val filePath = File(context.cacheDir, "images")
    val file = File(filePath, fileName)
    return FileProvider.getUriForFile(context, "${context.applicationContext.packageName}.provider", file)
}

我进行了一些调试,似乎FileProvider{}函数首先将文件路径/data/user/0/com.example.安卓.development/cache/images/background.png转换为规范文件路径/data/data/com.example.安卓.development/cache/images/background.png,然后尝试将根路径/storage/emulated/0与规范文件路径匹配。当它没有找到匹配项时,它抛出异常。 我不确定我做错了什么导致了这个问题,或者如何解决这个问题

调试文件提供程序。java getUriForFile(文件):

@Override
public Uri getUriForFile(File file) { // file: "/data/user/0/com.example.安卓.development/cache/images/background.png"
    String path; // path: "/data/data/com.example.安卓.development/cache/images/background.png"
    try {
        path = file.getCanonicalPath();
    } catch (IOException e) {
        throw new IllegalArgumentException("Failed to resolve canonical path for " + file);
    }

    // Find the most-specific root path
    Map.Entry<String, File> mostSpecific = null;
    for (Map.Entry<String, File> root : mRoots.entrySet()) {
        final String rootPath = root.getValue().getPath(); // rootPath: "/storage/emulated/0"
        if (path.startsWith(rootPath) && (mostSpecific == null // path: "/data/data/com.example.安卓.development/cache/images/background.png"
                || rootPath.length() > mostSpecific.getValue().getPath().length())) {
            mostSpecific = root; // mostSpecific: null
        }
    }

    if (mostSpecific == null) {
        throw new IllegalArgumentException(
                "Failed to find configured root that contains " + path);
    }

    // Start at first char of path under root
    final String rootPath = mostSpecific.getValue().getPath();
    if (rootPath.endsWith("/")) {
        path = path.substring(rootPath.length());
    } else {
        path = path.substring(rootPath.length() + 1);
    }

    // Encode the tag and path separately
    path = Uri.encode(mostSpecific.getKey()) + '/' + Uri.encode(path, "/");
    return new Uri.Builder().scheme("content")
            .authority(mAuthority).encodedPath(path).build();
}

我已经尝试过的事情:

  1. <root-path name="root" path="." />添加到<paths>
  2. 尝试filesDir而不是cacheDir
  3. 在手机上运行应用程序,而不是在模拟器上运行

共 (1) 个答案

  1. # 1 楼答案

    您的项目有多个名为res/xml/provider_paths.xml的资源,而您最后得到的是一个用于其他FileProvider的资源

    例如,您可能有一个app/模块和一个something/依赖的app/库模块。如果它们都有res/xml/provider_paths.xml,那么IIRC app/“赢”,并且它的资源被包括在内

    最简单的解决方案是将资源重命名为其他名称(例如,res/xml/images_provider_paths.xml),并更新<provider>清单条目以指向新名称