无法找到包含 Intent 在片段中时的配置根

Posted

技术标签:

【中文标题】无法找到包含 Intent 在片段中时的配置根【英文标题】:Failed to find configured root that contains when Intent is in fragment 【发布时间】:2021-03-26 09:31:04 【问题描述】:

互联网上有很多关于这个话题的问题和答案,但不幸的是它没有解决我的问题。

每次我尝试在我的 Fragment 中使用相机拍摄视频录制图片时都会收到错误消息。 我要保存这些文件的路径在 /data/data/com.example.testing/files/*

我总是得到的错误是:找不到配置的根目录“包含/数据/数据/com.example.testing/files/test.jpg”和“找不到配置的根目录包含/数据/数据/ com.example.testing/files/test.mp4"

完整的错误日志:

2020-12-16 00:14:32.093 6473-6473/com.example.testing E/androidRuntime: FATAL EXCEPTION: main
    Process: com.example.testing, PID: 6473
    java.lang.IllegalArgumentException: Failed to find configured root that contains /data/data/com.example.testing/files/test.jpg
        at androidx.core.content.FileProvider$SimplePathStrategy.getUriForFile(FileProvider.java:744)
        at androidx.core.content.FileProvider.getUriForFile(FileProvider.java:418)
        at com.example.testing.fragments.InvitesCheck.capturePhoto(InvitesCheck.kt:141)
        at com.example.testing.fragments.InvitesCheck.access$capturePhoto(InvitesCheck.kt:32)
        at com.example.testing.fragments.InvitesCheck$onViewCreated$1.onClick(InvitesCheck.kt:53)
        at android.view.View.performClick(View.java:7192)
        at com.google.android.material.button.MaterialButton.performClick(MaterialButton.java:992)
        at android.view.View.performClickInternal(View.java:7166)
        at android.view.View.access$3500(View.java:824)
        at android.view.View$PerformClick.run(View.java:27592)
        at android.os.Handler.handleCallback(Handler.java:888)
        at android.os.Handler.dispatchMessage(Handler.java:100)
        at android.os.Looper.loop(Looper.java:213)
        at android.app.ActivityThread.main(ActivityThread.java:8178)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:513)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1101)

我尝试了不同的设置,但不幸的是没有运气。

这是我的清单:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.testing">
    <uses-permission android:name="android.permission.CAMERA"/>
    <uses-permission android:name="android.permission.WRITE_INTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
    <uses-feature android:name="android.hardware.camera" />

    <application
        android:allowBackup="false"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/Theme.Testing">

        <activity
            android:name=".MainActivity"
            android:windowSoftInputMode="adjustResize">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

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

    </application>

</manifest>

我正在使用以下函数来调用相机:

private fun capturePhoto() 
    val file = File(requireContext().filesDir.path, "test.jpg")
    val uri = FileProvider.getUriForFile(requireActivity(), BuildConfig.APPLICATION_ID.toString() + ".provider", file)
    val intent = Intent(MediaStore.ACTION_IMAGE_CAPTURE)
    intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
    intent.putExtra(MediaStore.EXTRA_OUTPUT, uri)
    startActivityForResult(intent, REQUEST_CODE)


private fun captureVideo() 
    val file = File(requireContext().filesDir.path, "test.mp4")
    val uri = FileProvider.getUriForFile(requireActivity(), BuildConfig.APPLICATION_ID.toString() + ".provider", file)
    val intent = Intent(MediaStore.ACTION_VIDEO_CAPTURE)
    intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
    intent.putExtra(MediaStore.EXTRA_DURATION_LIMIT, 10);
    intent.putExtra(MediaStore.EXTRA_OUTPUT, uri)
    startActivityForResult(intent, REQUEST_VIDEO)

xml/provider_paths.xml

<?xml version="1.0" encoding="utf-8"?>
<paths>
    <external-path name="external_files" path="."/>
</paths>

我做错了什么?

提前谢谢你。

【问题讨论】:

你能发布更完整的堆栈跟踪吗?另外,您是否在清单中使用了正确的权限? .filesDir 不匹配外部路径是消息。 @blackapps 如果我是正确的,我应该授予从 root(.) 及更高版本写入文件的权限? filesDir 会和 external_files 一样吗? @IvanGarza 我应该在 Manifest 中拥有正确的权限,我更新了主题并粘贴了 manifest 和错误日志。我已经尝试了不同的方法,但到目前为止没有运气。 【参考方案1】:

阅读此question,您似乎应该在创建要写入的文件时使用Context.getExternalFilesDir() 而不是 Context.getFilesDir()`。

这最终会看起来像这样:

private fun capturePhoto() 
    val file = File(requireContext().getExternalFilesDir(null).path, "test.jpg")
    val uri = FileProvider.getUriForFile(requireActivity(), BuildConfig.APPLICATION_ID.toString() + ".provider", file)
    val intent = Intent(MediaStore.ACTION_IMAGE_CAPTURE)
    intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
    intent.putExtra(MediaStore.EXTRA_OUTPUT, uri)
    startActivityForResult(intent, REQUEST_CODE)

奖励:如果您打算制作面向媒体的应用程序,我建议您看看 MediaStore 课程。 Here's an official intro for it.

【讨论】:

Garzo 非常感谢你,它就像一个魅力。 /data/data/com.example.testing/files/ 和 /storage/emulated/0/Android/data/com.example.testing/files/ 之间有什么大区别吗? 我相信您之前使用的位置是用于临时资产的,它主要由您的应用程序内部使用,例如下载图像或诸如此类的东西。很高兴它成功了! 我相信您之前使用的位置是用于临时资产的,它主要由您的应用程序内部使用,例如下载图像或诸如此类的东西。很高兴它成功了!

以上是关于无法找到包含 Intent 在片段中时的配置根的主要内容,如果未能解决你的问题,请参考以下文章

使用 FileProvider 加载照片导致 java.lang.IllegalArgumentException:无法找到包含的已配置根

片段创建的 Intent 不会触发 onNewIntent

PHP如何找到应用程序根?

使用BroadcastReciever传递Intent.EXTRAS

当我从用户获取数据并将其保存到 SQLite 数据库中时,我应该怎么做才能使列表视图在片段中工作

导航组件:找不到NavController