From 672b052115c1979520a9c3d5598039a595b9a42c Mon Sep 17 00:00:00 2001
From: Janis Danisevskis
Note: Files you save in the directories provided by -{@link android.content.Context#getExternalFilesDir getExternalFilesDir()} are deleted +{@link android.content.Context#getExternalFilesDir getExternalFilesDir()} or +{@link android.content.Context#getFilesDir getFilesDir()} are deleted when the user uninstalls your app.
Once you decide the directory for the file, you need to create a @@ -190,8 +191,7 @@ private File createImageFile() throws IOException { // Create an image file name String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date()); String imageFileName = "JPEG_" + timeStamp + "_"; - File storageDir = Environment.getExternalStoragePublicDirectory( - Environment.DIRECTORY_PICTURES); + File storageDir = getExternalFilesDir(Environment.DIRECTORY_PICTURES); File image = File.createTempFile( imageFileName, /* prefix */ ".jpg", /* suffix */ @@ -225,14 +225,66 @@ private void dispatchTakePictureIntent() { } // Continue only if the File was successfully created if (photoFile != null) { - takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, - Uri.fromFile(photoFile)); + Uri photoURI = FileProvider.getUriForFile(this, + "com.example.android.fileprovider", + photoFile); + takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI); startActivityForResult(takePictureIntent, REQUEST_TAKE_PHOTO); } } } +
Note: We are using {@link
+android.support.v4.content.FileProvider#getUriForFile} which returns a content://
+URI. For more recent apps targeting Android N and higher, passing a file:// URI
+across a package boundary causes a {@link android.os.FileUriExposedException
+FileUriExposedException}.
+Therefore, we now present a more generic way of storing images using a
+{@link android.support.v4.content.FileProvider FileProvider}.
+
+<application> + ... + <provider + android:name="android.support.v4.content.FileProvider" + android:authorities="com.example.android.fileprovider" + android:exported="false" + android:grantUriPermissions="true"> + <meta-data + android:name="android.support.FILE_PROVIDER_PATHS" + android:resource="@xml/file_paths"></meta-data> + </provider> + ... +</application> ++ +Make sure that the authorities string matches the second argument to {@link +android.support.v4.content.FileProvider#getUriForFile}. +In the meta-data section of the provider definition, you can see that +the provider expects eligible paths to be configured in a dedicated resource file, +
+<?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.name/files/Pictures" /> +</paths> ++ +The path component corresponds to the path that is returned by +{@link android.content.Context#getExternalFilesDir getExternalFilesDir()} +when called with {@link android.os.Environment#DIRECTORY_PICTURES +Environment.DIRECTORY_PICTURES}. Make sure that you replace +
com.example.package.name with the actual package name of your
+app. Also, checkout the documentation of {@link android.support.v4.content.FileProvider} for
+an extensive description of path specifiers that you can use besides
+external-path.