Home | History | Annotate | Download | only in DirectorySelection
      1 <?xml version="1.0" encoding="UTF-8"?>
      2 <!--
      3  Copyright 2014 The Android Open Source Project
      4 
      5  Licensed under the Apache License, Version 2.0 (the "License");
      6  you may not use this file except in compliance with the License.
      7  You may obtain a copy of the License at
      8 
      9      http://www.apache.org/licenses/LICENSE-2.0
     10 
     11  Unless required by applicable law or agreed to in writing, software
     12  distributed under the License is distributed on an "AS IS" BASIS,
     13  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14  See the License for the specific language governing permissions and
     15  limitations under the License.
     16 -->
     17 <sample>
     18     <name>DirectorySelection</name>
     19     <group>Content</group>
     20     <package>com.example.android.directoryselection</package>
     21 
     22     <dependency>com.android.support:recyclerview-v7:+</dependency>
     23 
     24     <!-- change minSdk if needed-->
     25     <minSdk>21</minSdk>
     26 
     27     <strings>
     28         <intro>
     29             <![CDATA[
     30             This sample explains how to use Directory selection API, which was introduced
     31             in Android 5.0.
     32             ]]>
     33         </intro>
     34     </strings>
     35 
     36     <template src="base" />
     37 
     38     <metadata>
     39         <status>PUBLISHED</status>
     40         <categories>Content</categories>
     41         <technologies>Android</technologies>
     42         <languages>Java</languages>
     43         <solutions>Mobile</solutions>
     44         <level>INTERMEDIATE</level>
     45         <icon>screenshots/web-icon.png</icon>
     46         <screenshots>
     47             <img>screenshots/screenshot-1.png</img>
     48             <img>screenshots/screenshot-2.png</img>
     49             <img>screenshots/screenshot-3.png</img>
     50         </screenshots>
     51         <api_refs>
     52             <android>android.content.ContentResolver</android>
     53             <android>android.provider.DocumentsContract</android>
     54         </api_refs>
     55 
     56         <description>
     57 <![CDATA[
     58 A basic app showing how to use Directory Selection API to let users
     59 select an entire directory subtree, which extends the Storage Access Framework
     60 introduced in Android 4.4 (API level 19).
     61 ]]>
     62         </description>
     63 
     64         <intro>
     65 <![CDATA[
     66 The [Directory Selection][1] API, which was introduced in Android 5.0 (API level 21)
     67 extends the [Storage Access Framework][2] to let users select an entire directory subtree,
     68 giving apps read/write access to all contained documents without requiring user
     69 confirmation for each item.
     70 
     71 To select a directory subtree, build and send an [OPEN_DOCUMENT_TREE intent][3] like in the
     72 following code:
     73 
     74 ```java
     75 Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE);
     76 startActivityForResult(intent, REQUEST_CODE_OPEN_DIRECTORY);
     77 ```
     78 
     79 The system displays all [DocumentsProvider][4] instances that support subtree selection,
     80  letting the user browse and select a directory.
     81 
     82 The returned URI represents access to the selected subtree. You can then use
     83 [buildChildDocumentsUriUsingTree()][5] to access to the child documents and
     84 [buildDocumentUriUsingTree()][6] to access to the selected directory itself along with [query()][7]
     85 to explore the subtree.
     86 
     87 This example explores the child documents and the selected document by following code:
     88 
     89 ```java
     90 @Override
     91 public void onActivityResult(int requestCode, int resultCode, Intent data) {
     92     super.onActivityResult(requestCode, resultCode, data);
     93     if (requestCode == REQUEST_CODE_OPEN_DIRECTORY && resultCode == Activity.RESULT_OK) {
     94         updateDirectoryEntries(data.getData());
     95     }
     96 }
     97 
     98 void updateDirectoryEntries(Uri uri) {
     99     ContentResolver contentResolver = getActivity().getContentResolver();
    100     Uri docUri = DocumentsContract.buildDocumentUriUsingTree(uri,
    101             DocumentsContract.getTreeDocumentId(uri));
    102     Uri childrenUri = DocumentsContract.buildChildDocumentsUriUsingTree(uri,
    103             DocumentsContract.getTreeDocumentId(uri));
    104 
    105     Cursor docCursor = contentResolver.query(docUri, new String[]{
    106             Document.COLUMN_DISPLAY_NAME, Document.COLUMN_MIME_TYPE}, null, null, null);
    107     try {
    108         while (docCursor.moveToNext()) {
    109             Log.d(TAG, "found doc =" + docCursor.getString(0) + ", mime=" + docCursor
    110                     .getString(1));
    111             mCurrentDirectoryUri = uri;
    112             mCurrentDirectoryTextView.setText(docCursor.getString(0));
    113             mCreateDirectoryButton.setEnabled(true);
    114         }
    115     } finally {
    116         closeQuietly(docCursor);
    117     }
    118 
    119     Cursor childCursor = contentResolver.query(childrenUri, new String[]{
    120             Document.COLUMN_DISPLAY_NAME, Document.COLUMN_MIME_TYPE}, null, null, null);
    121     try {
    122         List<DirectoryEntry> directoryEntries = new ArrayList<>();
    123         while (childCursor.moveToNext()) {
    124             Log.d(TAG, "found child=" + childCursor.getString(0) + ", mime=" + childCursor
    125                     .getString(1));
    126             DirectoryEntry entry = new DirectoryEntry();
    127             entry.fileName = childCursor.getString(0);
    128             entry.mimeType = childCursor.getString(1);
    129             directoryEntries.add(entry);
    130         }
    131         mAdapter.setDirectoryEntries(directoryEntries);
    132         mAdapter.notifyDataSetChanged();
    133     } finally {
    134         closeQuietly(childCursor);
    135     }
    136 }
    137 ```
    138 
    139 Also, the new [createDocument()][8] method lets you create new documents or directories
    140 anywhere under the subtree.
    141 
    142 This example creates a new directory by following code:
    143 
    144 ```java
    145 ContentResolver contentResolver = getActivity().getContentResolver();
    146 Uri docUri = DocumentsContract.buildDocumentUriUsingTree(uri,
    147         DocumentsContract.getTreeDocumentId(uri));
    148 Uri directoryUri = DocumentsContract
    149         .createDocument(contentResolver, docUri, Document.MIME_TYPE_DIR, directoryName);
    150 ```
    151 
    152 [1]: https://developer.android.com/about/versions/android-5.0.html#Storage
    153 [2]: https://developer.android.com/guide/topics/providers/document-provider.html
    154 [3]: https://developer.android.com/reference/android/content/Intent.html#ACTION_OPEN_DOCUMENT_TREE
    155 [4]: https://developer.android.com/reference/android/provider/DocumentsProvider.html
    156 [5]: https://developer.android.com/reference/android/provider/DocumentsContract.html#buildChildDocumentsUriUsingTree(android.net.Uri%2C%20java.lang.String)
    157 [6]: https://developer.android.com/reference/android/provider/DocumentsContract.html#buildDocumentUriUsingTree(android.net.Uri%2C%20java.lang.String)
    158 [7]: https://developer.android.com/reference/android/content/ContentResolver.html#query(android.net.Uri%2C%20java.lang.String%5B%5D%2C%20java.lang.String%2C%20java.lang.String%5B%5D%2C%20java.lang.String)
    159 [8]: https://developer.android.com/reference/android/provider/DocumentsContract.html#createDocument(android.content.ContentResolver%2C%20android.net.Uri%2C%20java.lang.String%2C%20java.lang.String)
    160 ]]>
    161         </intro>
    162     </metadata>
    163 </sample>
    164