0

There are many questions and answers about this topic on the internet but unfortunately it didnt solve my problem.

I get a error every time I try to intent a Camera for a picture of video recording within my Fragment. The path where I want to save those files are in /data/data/com.example.testing/files/*

The error that I always get is: Failed to find configured root that "contains/data/data/com.example.testing/files/test.jpg" and "Failed to find configured root that contains/data/data/com.example.testing/files/test.mp4"

The complete error log:

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)

I tried different setups but unfortunately no luck.

This is my Manifest:

<?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>

I am using the following functions to call the camera:

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>

What am I doing wrong?

Thank you in advance.

Riccoh
  • 359
  • 1
  • 4
  • 19
  • Could you post a fuller stack trace? Also, are you using the right permissions in your Manifest? – Ivan Garza Dec 15 '20 at 18:13
  • .filesDir does not match external-path is the message. – blackapps Dec 15 '20 at 18:50
  • @blackapps If I am correctly I should have given the permission to write files from root(.) and above? filesDir would be the same as external_files right? – Riccoh Dec 15 '20 at 23:23
  • @IvanGarza I should have the right permissions in Manifest, I updated the topic and pasted the manifest and error log. I already tried different approaches, but no luck so far. – Riccoh Dec 15 '20 at 23:25

1 Answers1

1

Reading up on this question, it seems that you should be using Context.getExternalFilesDir() instead of Context.getFilesDir()` whenever you're creating the File to which to write to.

This would end up looking something like this:

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)
}

BONUS: I would recommend you take a look at the MediaStore class if you're planning on making a media-oriented app. Here's an official intro for it.

Ivan Garza
  • 553
  • 2
  • 14
  • Garzo Thank you very much, it worked like a charm. Is there any big difference between /data/data/com.example.testing/files/ and /storage/emulated/0/Android/data/com.example.testing/files/ ? – Riccoh Dec 16 '20 at 17:31
  • 1
    I believe the location you were using before is for temporal assets and it is mostly used by your app internally to say, download images or whatnot. Glad it worked! – Ivan Garza Dec 16 '20 at 18:10
  • I believe the location you were using before is for temporal assets and it is mostly used by your app internally to say, download images or whatnot. Glad it worked! – Ivan Garza Dec 16 '20 at 18:10