docs: Migrating Scoped Dir Access preview docs into DAC
For Android N release, migrating and updating Scoped Directory Access docs into regular DAC docs. Updated TOC and added redirect. Removed preview/features doc. Updated and moved images. Bug: 30257320 Change-Id: I3440fe1b74947cbfbd1ada6f5d6bee5e49847927
@@ -1214,3 +1214,5 @@ redirects:
|
|||||||
to: /training/tv/tif/content-recording.html
|
to: /training/tv/tif/content-recording.html
|
||||||
- from: /preview/features/direct-boot.html
|
- from: /preview/features/direct-boot.html
|
||||||
to: /training/articles/direct-boot.html
|
to: /training/articles/direct-boot.html
|
||||||
|
- from: /preview/features/scoped-folder-access.html
|
||||||
|
to: /training/articles/scoped-directory-access.html
|
||||||
|
|||||||
@@ -252,6 +252,17 @@ external storage on a computer or removes the media, and there's no security enf
|
|||||||
save to the external storage. All applications can read and write files placed on the external
|
save to the external storage. All applications can read and write files placed on the external
|
||||||
storage and the user can remove them.</p>
|
storage and the user can remove them.</p>
|
||||||
|
|
||||||
|
<h3 id="ScopedDirAccess">Using Scoped Directory Access</h3>
|
||||||
|
|
||||||
|
On Android 7.0 or later, if you need access to a specific directory on
|
||||||
|
external storage, use scoped directory access. Scoped directory access
|
||||||
|
simplifies how your application accesses standard external storage directories,
|
||||||
|
such as the <code>Pictures</code> directory, and provides a simple
|
||||||
|
permissions UI that clearly details what directory the application is
|
||||||
|
requesting access to. For more details on scoped directory access, see
|
||||||
|
<a href="{@docRoot}training/articles/scoped-directory-access.html">Using
|
||||||
|
Scoped Directory Access</a>.
|
||||||
|
|
||||||
<h3 id="ExternalPermissions">Getting access to external storage</h3>
|
<h3 id="ExternalPermissions">Getting access to external storage</h3>
|
||||||
|
|
||||||
<p>In order to read or write files on the external storage, your app must acquire the
|
<p>In order to read or write files on the external storage, your app must acquire the
|
||||||
|
|||||||
|
After Width: | Height: | Size: 65 KiB |
|
After Width: | Height: | Size: 242 KiB |
BIN
docs/html/images/android-7.0/scoped-directory-access-framed.png
Normal file
|
After Width: | Height: | Size: 64 KiB |
|
After Width: | Height: | Size: 239 KiB |
|
Before Width: | Height: | Size: 66 KiB |
|
Before Width: | Height: | Size: 221 KiB |
|
Before Width: | Height: | Size: 68 KiB |
|
Before Width: | Height: | Size: 249 KiB |
@@ -1397,6 +1397,11 @@ toc:
|
|||||||
path_attributes:
|
path_attributes:
|
||||||
- name: description
|
- name: description
|
||||||
value: How use device encrypted storage during Direct Boot mode.
|
value: How use device encrypted storage during Direct Boot mode.
|
||||||
|
- title: Using Scoped Directory Access
|
||||||
|
path: /training/articles/scoped-directory-access.html
|
||||||
|
path_attributes:
|
||||||
|
- name: description
|
||||||
|
value: How to use scoped directory access to request access to external storage directories.
|
||||||
|
|
||||||
- title: Best Practices for Permissions & Identifiers
|
- title: Best Practices for Permissions & Identifiers
|
||||||
path: /training/best-permissions-ids.html
|
path: /training/best-permissions-ids.html
|
||||||
|
|||||||
@@ -1,11 +1,10 @@
|
|||||||
page.title=Scoped Directory Access
|
page.title=Using Scoped Directory Access
|
||||||
page.keywords=preview,sdk,scoped directory access
|
page.keywords=scoped directory access
|
||||||
page.tags=androidn
|
|
||||||
|
|
||||||
@jd:body
|
@jd:body
|
||||||
|
|
||||||
<div id="qv-wrapper">
|
<div id="tb-wrapper">
|
||||||
<div id="qv">
|
<div id="tb">
|
||||||
<h2>In this document</h2>
|
<h2>In this document</h2>
|
||||||
<ol>
|
<ol>
|
||||||
<li><a href="#accessing">Accessing an External Storage Directory</a></li>
|
<li><a href="#accessing">Accessing an External Storage Directory</a></li>
|
||||||
@@ -32,29 +31,37 @@ via a system UI, which is unnecessary if your app always accesses the same
|
|||||||
external directory.</li>
|
external directory.</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<p>Android N provides a new simplified API to access
|
<p>Android 7.0 provides a simplified API to access common external storage
|
||||||
common external storage directories. </p>
|
directories.</p>
|
||||||
|
|
||||||
<h2 id="accessing">Accessing an External Storage Directory</h2>
|
<h2 id="accessing">Accessing an External Storage Directory</h2>
|
||||||
|
|
||||||
<p>Use the <code>StorageManager</code> class to get the appropriate
|
<p>Use the {@link android.os.storage.StorageManager} class to get the
|
||||||
<code>StorageVolume</code> instance. Then, create an intent by calling the
|
appropriate {@link android.os.storage.StorageVolume} instance. Then, create
|
||||||
<code>StorageVolume.createAccessIntent()</code> method of that instance.
|
an intent by calling the
|
||||||
|
{@link android.os.storage.StorageVolume#createAccessIntent
|
||||||
|
StorageVolume.createAccessIntent()} method of that instance.
|
||||||
Use this intent to access external storage directories. To get a list of
|
Use this intent to access external storage directories. To get a list of
|
||||||
all available volumes, including removable media volumes, use
|
all available volumes, including removable media
|
||||||
<code>StorageManager.getVolumesList()</code>.</p>
|
volumes, use {@link android.os.storage.StorageManager#getStorageVolumes
|
||||||
|
StorageManager.getStorageVolumes()}.</p>
|
||||||
|
|
||||||
<p>If you have information about a specific file, use
|
<p>If you have information about a specific file, use
|
||||||
<code>StorageManager.getStorageVolume(File)</code> to get the
|
{@link android.os.storage.StorageManager#getStorageVolume
|
||||||
<code>StorageVolume</code> that contains the file. Call
|
StorageManager.getStorageVolume(File)} to get the
|
||||||
<code>createAccessIntent()</code> on this <code>StorageVolume</code> to access
|
{@link android.os.storage.StorageVolume} that contains the file. Call
|
||||||
|
{@link android.os.storage.StorageVolume#createAccessIntent
|
||||||
|
createAccessIntent()} on this
|
||||||
|
{@link android.os.storage.StorageVolume} to access
|
||||||
the external storage directory for the file.</p>
|
the external storage directory for the file.</p>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
On secondary volumes, such as external SD cards, pass in null when calling
|
On secondary volumes, such as external SD cards, pass in null when calling
|
||||||
<code>StorageVolume.createAccessIntent()</code> to request access to the entire
|
{@link android.os.storage.StorageVolume#createAccessIntent
|
||||||
|
createAccessIntent()} to request access to the entire
|
||||||
volume, instead of a specific directory.
|
volume, instead of a specific directory.
|
||||||
<code>StorageVolume.createAccessIntent()</code> returns null if you pass in
|
{@link android.os.storage.StorageVolume#createAccessIntent
|
||||||
|
createAccessIntent()} returns null if you pass in
|
||||||
null to the primary volume, or if you pass in an invalid directory name.
|
null to the primary volume, or if you pass in an invalid directory name.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
@@ -63,7 +70,7 @@ null to the primary volume, or if you pass in an invalid directory name.
|
|||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
StorageManager sm = (StorageManager)getSystemService(Context.STORAGE_SERVICE);
|
StorageManager sm = (StorageManager)getSystemService(Context.STORAGE_SERVICE);
|
||||||
StorageVolume volume = sm.getPrimaryVolume();
|
StorageVolume volume = sm.getPrimaryStorageVolume();
|
||||||
Intent intent = volume.createAccessIntent(Environment.DIRECTORY_PICTURES);
|
Intent intent = volume.createAccessIntent(Environment.DIRECTORY_PICTURES);
|
||||||
startActivityForResult(intent, request_code);
|
startActivityForResult(intent, request_code);
|
||||||
</pre>
|
</pre>
|
||||||
@@ -71,25 +78,27 @@ startActivityForResult(intent, request_code);
|
|||||||
<p>The system attempts to grant access to the external directory, and if
|
<p>The system attempts to grant access to the external directory, and if
|
||||||
necessary confirms access with the user using a simplified UI:</p>
|
necessary confirms access with the user using a simplified UI:</p>
|
||||||
|
|
||||||
<img src="{@docRoot}preview/images/scoped-folder-access-framed.png"
|
<img src="{@docRoot}images/android-7.0/scoped-directory-access-framed.png"
|
||||||
srcset="{@docRoot}preview/images/scoped-folder-access-framed.png 1x,
|
srcset="{@docRoot}images/android-7.0/scoped-directory-access-framed.png 1x,
|
||||||
{@docRoot}preview/images/scoped-folder-access-framed_2x.png 2x" />
|
{@docRoot}images/android-7.0/scoped-directory-access-framed_2x.png 2x" />
|
||||||
<p class="img-caption"><strong>Figure 1.</strong> An application requesting
|
<p class="img-caption"><strong>Figure 1.</strong> An application requesting
|
||||||
access to the Pictures directory.</p>
|
access to the Pictures directory.</p>
|
||||||
|
|
||||||
<p>If the user grants access, the system calls your
|
<p>If the user grants access, the system calls your
|
||||||
<code>onActivityResult()</code> override with a result code of
|
{@link android.app.Activity#onActivityResult onActivityResult()} override
|
||||||
<code>Activity.RESULT_OK</code>, and intent data that contains the URI. Use
|
with a result code of {@link android.app.Activity#RESULT_OK
|
||||||
|
RESULT_OK}, and intent data that contains the URI. Use
|
||||||
the provided URI to access directory information, similar to using URIs
|
the provided URI to access directory information, similar to using URIs
|
||||||
returned by the
|
returned by the
|
||||||
<a href="{@docRoot}guide/topics/providers/document-provider.html">Storage
|
<a href="{@docRoot}guide/topics/providers/document-provider.html">Storage
|
||||||
Access Framework</a>.</p>
|
Access Framework</a>.</p>
|
||||||
|
|
||||||
<p>If the user doesn't grant access, the system calls your
|
<p>If the user doesn't grant access, the system calls your
|
||||||
<code>onActivityResult()</code> override with a result code of
|
{@link android.app.Activity#onActivityResult onActivityResult()} override
|
||||||
<code>Activity.RESULT_CANCELED</code>, and null intent data.</p>
|
with a result code of {@link android.app.Activity#RESULT_CANCELED
|
||||||
|
RESULT_CANCELED}, and null intent data.</p>
|
||||||
|
|
||||||
<p class="note"><b>Note</b>: Getting access to a specific external directory
|
<p>Getting access to a specific external directory
|
||||||
also gains access to subdirectories within that directory.</p>
|
also gains access to subdirectories within that directory.</p>
|
||||||
|
|
||||||
<h2 id="removable">Accessing a Directory on Removable Media</h2>
|
<h2 id="removable">Accessing a Directory on Removable Media</h2>
|
||||||
@@ -112,9 +121,9 @@ first add a {@link android.content.BroadcastReceiver} that listens for the
|
|||||||
|
|
||||||
<p>When the user mounts removable media, like an SD card, the system sends a
|
<p>When the user mounts removable media, like an SD card, the system sends a
|
||||||
{@link android.os.Environment#MEDIA_MOUNTED} notification. This notification
|
{@link android.os.Environment#MEDIA_MOUNTED} notification. This notification
|
||||||
provides a <code>StorageVolume</code> object in the intent data that you can
|
provides a {@link android.os.storage.StorageVolume} object in the intent data
|
||||||
use to access directories on the removable media. The following example
|
that you can use to access directories on the removable media. The following
|
||||||
accesses the <code>Pictures</code> directory on removable media:</p>
|
example accesses the <code>Pictures</code> directory on removable media:</p>
|
||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
// BroadcastReceiver has already cached the MEDIA_MOUNTED
|
// BroadcastReceiver has already cached the MEDIA_MOUNTED
|
||||||
@@ -129,19 +138,22 @@ startActivityForResult(intent, request_code);
|
|||||||
|
|
||||||
<p>Where possible, persist the external directory access URI so you don't have
|
<p>Where possible, persist the external directory access URI so you don't have
|
||||||
to repeatedly ask the user for access. Once the user has granted access, call
|
to repeatedly ask the user for access. Once the user has granted access, call
|
||||||
<code>getContentResolver().takePersistableUriPermssion()</code> with the
|
{@link android.content.Context#getContentResolver getContentResolver()} and
|
||||||
directory access URI. The system will persist the URI and subsequent access
|
with the returned {@link android.content.ContentResolver} call
|
||||||
requests will return <code>RESULT_OK</code> and not show confirmation UI to the
|
{@link android.content.ContentResolver#takePersistableUriPermission
|
||||||
user.</p>
|
takePersistableUriPermission()} with the directory access URI. The system will
|
||||||
|
persist the URI and subsequent access requests will return
|
||||||
|
{@link android.app.Activity#RESULT_OK RESULT_OK} and not show confirmation
|
||||||
|
UI to the user.</p>
|
||||||
|
|
||||||
<p>If the user denies access to an external directory, do not immediately
|
<p>If the user denies access to an external directory, do not immediately
|
||||||
request access again. Repeatedly insisting on access results in a poor user
|
request access again. Repeatedly insisting on access results in a poor user
|
||||||
experience. If a request is denied by the user, and the app requests access
|
experience. If a request is denied by the user, and the app requests access
|
||||||
again, the UI displays a <b>Don't ask again</b> checkbox:</p>
|
again, the UI displays a <b>Don't ask again</b> checkbox:</p>
|
||||||
|
|
||||||
<img src="{@docRoot}preview/images/scoped-folder-access-dont-ask.png"
|
<img src="{@docRoot}images/android-7.0/scoped-directory-access-dont-ask.png"
|
||||||
srcset="{@docRoot}preview/images/scoped-folder-access-dont-ask.png 1x,
|
srcset="{@docRoot}images/android-7.0/scoped-directory-access-dont-ask.png 1x,
|
||||||
{@docRoot}preview/images/scoped-folder-access-dont-ask_2x.png 2x" />
|
{@docRoot}images/android-7.0/scoped-directory-access-dont-ask_2x.png 2x" />
|
||||||
<p class="img-caption"><strong>Figure 1.</strong> An application making a
|
<p class="img-caption"><strong>Figure 1.</strong> An application making a
|
||||||
second request for access to removable media.</p>
|
second request for access to removable media.</p>
|
||||||
|
|
||||||