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