6

I'm taking a picture on Android Nougat with FileProvider, that's my code

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

file_paths.xml:

<paths>
    <files-path name="img" path="images/" />
</paths>

Java:

 String fileName = "cameraOutput" + System.currentTimeMillis() + ".jpg";
 File imagePath = new File(getContext().getFilesDir(), "images");
 File file = new File(imagePath, fileName);
 Intent cameraIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);

 final Uri outputUri = FileProvider.getUriForFile(activity, "com.mypackage.fileprovider", file);
 cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, outputUri);
 getContext().grantUriPermission(
            "com.google.android.GoogleCamera",
            outputUri,
            Intent.FLAG_GRANT_WRITE_URI_PERMISSION | Intent.FLAG_GRANT_READ_URI_PERMISSION
 );
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            cameraIntent.setFlags(FLAG_GRANT_WRITE_URI_PERMISSION);
 activity.startActivityForResult(cameraIntent, ACTIVITY_REQUEST_CODE);

Camera activity starts, take picture successfully, but the Activity Result is not OK and the only thing I see in error logs is

CAM_StateSavePic: exception while saving result to URI: Optional.of(content://com.mypackage.fileprovider/img/cameraOutput1469383289530.jpg) FileNotFoundException: Is a directory

EDIT missed File#createNewFile();

Ihor Klimov
  • 898
  • 4
  • 15
  • 23

2 Answers2

12

The main thing to get camera and gallery URI working is provider paths.

you need to create a provider_paths.xml to /res/xml/ dir

<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-path name="external_files" path="."/>
</paths>

In your manifest file add this lines between

<provider
    android:name="android.support.v4.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>

One more thing, I've found that we need to set vmPolicy in Application class like this

@Override
public void onCreate() {
    super.onCreate();
   //Allowing Strict mode policy for Nougat support
   StrictMode.VmPolicy.Builder builder = new StrictMode.VmPolicy.Builder();
   StrictMode.setVmPolicy(builder.build());
}

Double check your camera and external storage permission in manifest file and there you go with nougat URI.

For more details check this link : Android N FileUriExposedException

Rahul Upadhyay
  • 3,493
  • 2
  • 21
  • 37
  • 1
    why do we need to set that vmPolicy? – Sree Mar 15 '17 at 14:39
  • 1
    @Sree, thanks for asking. We use it to prevent accidental crashes over phone at run time. StrictMode is a developer tool which detects things you might be doing by accident and brings them to your attention so you can fix them. For more information you can check android developer link : https://developer.android.com/reference/android/os/StrictMode.html – Rahul Upadhyay Mar 17 '17 at 04:19
  • 1
    Enable strict mode only in development – Ryan Amaral Apr 20 '17 at 19:54
  • How to get File from this uri? it says file not exist. Though by using Glide i'm able to show in ImageView – Usman Rana Dec 12 '17 at 20:58
0

if androidx was used in your project, you need replace dot(.) to slash(/).

<!--别用. 不然在androidx上面有问题-->
<external-path name="sdcard" path="/" /> 

works for me great!

hoot
  • 1,215
  • 14
  • 15