diff options
| author | 2016-04-22 13:34:20 +0100 | |
|---|---|---|
| committer | 2016-05-09 18:34:22 +0000 | |
| commit | 672b052115c1979520a9c3d5598039a595b9a42c (patch) | |
| tree | 0129fb8878bd84d32d140e13a239e683ab769794 | |
| parent | de5a7afc7989ecef051635fdc9ae52a69870c026 (diff) | |
Updates training/camera/photobasics.jd with FileProvider details
As of Android N, passing file:// URIs across package boundaries
throws a FileUriExposedException. This has caused frustration among
app developers trying to use our example as boilerplate code. This
patch replaces the "take picture" example with one that uses
content:// URIs and FileProvider instead.
Bug: 27636012
Change-Id: I9f0b4d9bbcd6b4bfa770dd1e4ad37f321e22195f
| -rw-r--r-- | docs/html/training/camera/photobasics.jd | 62 |
1 files changed, 57 insertions, 5 deletions
diff --git a/docs/html/training/camera/photobasics.jd b/docs/html/training/camera/photobasics.jd index efac54834676..bfea0f7463e2 100644 --- a/docs/html/training/camera/photobasics.jd +++ b/docs/html/training/camera/photobasics.jd @@ -175,7 +175,8 @@ attribute:</p> </pre> <p class="note"><strong>Note:</strong> 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.</p> <p>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); } } } </pre> +<p class="note"><strong>Note:</strong> We are using {@link +android.support.v4.content.FileProvider#getUriForFile} which returns a <code>content://</code> +URI. For more recent apps targeting Android N and higher, passing a <code>file://</code> 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}. +</p> + +Now, you need to configure the {@link android.support.v4.content.FileProvider +FileProvider}. In your app's manifest, add a provider to your application: + +<pre> +<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> +</pre> + +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, +<c>res/xml/file_paths.xml</c>. Here is the content required for this particular +example: + +<pre> +<?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> +</pre> + +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 +<code>com.example.package.name</code> 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 +<code>external-path</code>. <h2 id="TaskGallery">Add the Photo to a Gallery</h2> |