140

I am trying to fix a problem after the new feature added in Android file system but I get this error:

android.os.FileUriExposedException: file:///storage/emulated/0/MyApp/Camera_20180105_172234.jpg exposed beyond app through ClipData.Item.getUri()

So I hope some one can help me fix this :)

Thanks

private Uri getTempUri() {
    // Create an image file name
    SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd_HHmmss");
    String dt = sdf.format(new Date());
    imageFile = null;
    imageFile = new File(Environment.getExternalStorageDirectory()
            + "/MyApp/", "Camera_" + dt + ".jpg");
    AppLog.Log(
            TAG,
            "New Camera Image Path:- "
                    + Environment.getExternalStorageDirectory()
                    + "/MyApp/" + "Camera_" + dt + ".jpg");
    File file = new File(Environment.getExternalStorageDirectory() + "/MyApp");
    if (!file.exists()) {
        file.mkdir();
    }
    imagePath = Environment.getExternalStorageDirectory() + "/MyApp/"
            + "Camera_" + dt + ".jpg";
    imageUri = Uri.fromFile(imageFile);
    return imageUri;
}
Zoe
  • 27,060
  • 21
  • 118
  • 148
JonathanNet
  • 1,637
  • 3
  • 15
  • 17
  • 3
    https://stackoverflow.com/questions/38200282/android-os-fileuriexposedexception-file-storage-emulated-0-test-txt-exposed – CommonsWare Jan 05 '18 at 16:32

4 Answers4

256

For sdk 24 and up, if you need to get the Uri of a file outside your app storage you have this error.
@eranda.del solutions let you change the policy to allow this and it works fine.

However if you want to follow the google guideline without having to change the API policy of your app you have to use a FileProvider.

At first to get the URI of a file you need to use FileProvider.getUriForFile() method:

Uri imageUri = FileProvider.getUriForFile(
            MainActivity.this,
            "com.example.homefolder.example.provider", //(use your app signature + ".provider" )
            imageFile);

Then you need to configure your provider in your android manifest :

<application>
  ...
     <provider
        android:name="android.support.v4.content.FileProvider"
        android:authorities="com.example.homefolder.example.provider"
        android:exported="false"
        android:grantUriPermissions="true">
        <!-- ressource file to create -->
        <meta-data
            android:name="android.support.FILE_PROVIDER_PATHS"
            android:resource="@xml/file_paths">  
        </meta-data>
    </provider>
</application>

(In "authorities" use the same value than the second argument of the getUriForFile() method (app signature + ".provider"))

And finally you need to create the ressources file: "file_paths". This file need to be created under the res/xml directory (you probably need to create this directory too) :

<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <external-path name="external_files" path="." />
</paths>
M.Sameer
  • 3,072
  • 1
  • 24
  • 37
Brendon
  • 2,808
  • 1
  • 9
  • 10
  • 161
    "Make developers life easier" - this is the tagline for every new API, right Google? – Kirill Karmazin Oct 10 '18 at 18:54
  • 17
    The solution provided by Brendon is the correct one but it's not copy-paste ready, you need to check if it suits your needs, for ex. ` – Kirill Karmazin Oct 10 '18 at 19:53
  • 10
    A reminder if you're using androidx (new support namespace), you can find here (https://developer.android.com/reference/androidx/core/content/FileProvider) the proper documentation. – Rodrigo García Nov 28 '18 at 01:29
  • 34
    Note that in `androidx` it is: `android:name="androidx.core.content.FileProvider"` – smörkex Sep 08 '19 at 21:25
176

Add following code block before start camera or file browsing

    StrictMode.VmPolicy.Builder builder = new StrictMode.VmPolicy.Builder();
    StrictMode.setVmPolicy(builder.build());

Please refer the referral link strict mode and its explained all the usage and technical details.

eranda.del
  • 2,775
  • 1
  • 15
  • 11
  • 33
    Its not the right way to solve this, this will basically remove the strictmode policies. and will ignore the security warning – Ahsan Zaheer Apr 03 '18 at 11:25
  • There are some pros and cons on this. Please refer the following to get more information https://stackoverflow.com/questions/18100161/strictmode-threadpolicy-builder-purpose-and-advantages – eranda.del Apr 18 '18 at 10:11
  • 1
    It works, if there is any draw back then please let me know :) – Hanan Jan 04 '19 at 06:00
  • The code solved the exception for me. However, the top comment here says how the code is not the correct way to solve this. Does anyone know what the proper method would be then? – Shane Sepac Apr 20 '19 at 22:07
  • 8
    Google hates programmers. – Joubert Vasconcelos Aug 10 '20 at 23:14
  • 3
    Thanks!!! It worked for me. But I will still investigate why the provider setting in the manifest is not working for me – Tony_Bielo Mar 22 '21 at 16:57
4

No required provider configuration into AndroidManifest only Camera and Storage permission should be permitted. Use the following code to start the camera:

final int REQUEST_ACTION_CAMERA = 9;
void openCamra() {
Intent cameraImgIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);

cameraImgIntent.putExtra(MediaStore.EXTRA_OUTPUT,
                FileProvider.getUriForFile(this, BuildConfig.APPLICATION_ID +".provider",
                new File("your_file_name_with_dir")));
startActivityForResult(cameraImgIntent, REQUEST_ACTION_CAMERA);
}

After capturing the image, you can find your captured image in:

"your_file_name_with_dir"
rainer
  • 3,295
  • 5
  • 34
  • 50
0

add a code in

onCreate(Budle savedInstancesState){
    if (Build.VERSION.SDK_INT >= 24) {
        try {
            Method m = StrictMode.class.getMethod("disableDeathOnFileUriExposure");
            m.invoke(null);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
Vladislav Varslavans
  • 2,775
  • 4
  • 18
  • 33
kocode
  • 11