Ivan
Ivan

Reputation: 359

Unable to get File Uri for PutExtra method for camera

I am trying to build a camera activity that takes a photo and saves it to the SD card. But I found that my code is breaking at the method used to obtain the File Uri as well as the putExtra() method.

When the startCamera() function is called, the camera intent does not launch and kills the activity.

private void startCamera(int actionCode) {
    //Create a camera intent
    Intent camera_intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
    switch (actionCode) {
        case CAM_REQ_CODE:
        File photo_file = null;
        try {
            photo_file = setUpPhotoFile();
        } catch (IOException e) {
            e.printStackTrace();
            photo_file = null;
            photo_path = null;
        }
        // Continue only if the File was successfully created
        if (photo_file != null) {
            photo_path = photo_file.getAbsolutePath();
            Uri photoURI = Uri.fromFile(photo_file);  //works
            //Uri photoURI = FileProvider.getUriForFile(InStore.this,"babygroot.iamgroot.fileprovider", photo_file);
            // PROBLEM!! how to overcome putExtra method to pass photo URI to MediaStore.EXTRA_OUTPUT
            camera_intent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI);
            startActivityForResult(camera_intent, CAM_REQ_CODE);
        }
        break;
        default:
            break;
    }
}

And this is my manifest:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="babygroot.iamgroot">

    <!-- To auto-complete the email text field in the login form with the user's emails -->
    <uses-permission android:name="android.permission.GET_ACCOUNTS" />
    <uses-permission android:name="android.permission.READ_PROFILE" />
    <uses-permission android:name="android.permission.READ_CONTACTS" />
    <uses-permission android:name="android.permission.CAMERA" />
    <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" />
    <!--<uses-feature android:name="android.hardware.camera2" /> -->
    <uses-feature android:name="android.hardware.camera.autofocus" />


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

        <provider
            android:name="android.support.v4.content.FileProvider"
            android:authorities="babygroot.iamgroot.fileprovider"
            android:exported="false"
            android:grantUriPermissions="true">
            <meta-data
                android:name="android.support.FILE_PROVIDER_PATHS"
                android:resource="@xml/file_paths"></meta-data>
        </provider>

        <activity android:name=".LoginScreen">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity
            android:name=".QRCode"
            android:parentActivityName=".LoginScreen" />
        <activity
            android:name=".SignUp"
            android:parentActivityName=".LoginScreen" />
        <activity
            android:name=".InStore"
            android:parentActivityName=".QRCode" />
        <activity android:name=".CheckOut" />
    </application>

</manifest>

The InStore activity is where the camera function is used.

This is the stacktrace when it fails

Process: babygroot.iamgroot, PID: 26238
    java.lang.IllegalArgumentException: Failed to find configured root that contains /storage/emulated/0/Pictures/IAMGROOTPics/IMG_20171213_141445_787397456.jpg
                  at android.support.v4.content.FileProvider$SimplePathStrategy.getUriForFile(FileProvider.java:712)
                  at android.support.v4.content.FileProvider.getUriForFile(FileProvider.java:401)
                  at babygroot.iamgroot.InStore.startCamera(InStore.java:172)
                  at babygroot.iamgroot.InStore.showCameraPreview(InStore.java:111)
                  at babygroot.iamgroot.InStore.access$000(InStore.java:28)
                  at babygroot.iamgroot.InStore$1.onClick(InStore.java:63)
                  at android.view.View.performClick(View.java:5646)
                  at android.view.View$PerformClick.run(View.java:22459)
                  at android.os.Handler.handleCallback(Handler.java:761)
                  at android.os.Handler.dispatchMessage(Handler.java:98)
                  at android.os.Looper.loop(Looper.java:156)
                  at android.app.ActivityThread.main(ActivityThread.java:6523)
                  at java.lang.reflect.Method.invoke(Native Method)
                  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:942)
                  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:832)

res/xml/file_paths.xml:

<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <external-path name="my_images" path="Android/data/com.example.package.babygroot.iamgroot/files/Pictures" />
</paths>

<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <external-path name="my_images" path="Android/data/com.example.package.babygroot.iamgroot/files/Pictures" />
</paths>

Upvotes: 0

Views: 1357

Answers (2)

Shambhu
Shambhu

Reputation: 191

In my case

        ContentValues values = new ContentValues();
        values.put(MediaStore.Images.Media.TITLE, "Image File name");
        mCapturedImageURI = getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
        Intent intentPicture = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
        intentPicture.putExtra(MediaStore.EXTRA_OUTPUT, mCapturedImageURI);
        startActivityForResult(intentPicture,REQUEST_IMAGE_CAPTURE);

The above code is working fine.

Try replacing your code with this.

And handle the onActivityResult for getting back the image in your activity.

Hpe this helps!

Upvotes: 0

Umar Hussain
Umar Hussain

Reputation: 3527

The issue is android now does not allow files read of other applications so thats why your code is crashing. See this 7.0 behaviour changes

See this tutorial to do your task using FileProvider https://drivy.engineering/android-fileprovider/

You basically declare a shared file location so that apps can do read and write there. Then create a file there and use the Uri of that file to open camera intent.

<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <files-path name="shared" path="shared/"/>
</paths>

Menfiest File declaration

<provider
    android:name="android.support.v4.content.FileProvider"
    android:authorities="<your provider authority>"
    android:exported="false"
    android:grantUriPermissions="true">
  <meta-data
      android:name="android.support.FILE_PROVIDER_PATHS"
      android:resource="@xml/file_provider_paths"/>
</provider>

Finally

Uri sharedFileUri = FileProvider.getUriForFile(this, <your provider auhtority>, sharedFile);

Upvotes: 2

Related Questions