1 /* 2 * Copyright 2014 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.example.android.directoryselection; 18 19 import android.app.Activity; 20 import android.app.AlertDialog; 21 import android.content.ContentResolver; 22 import android.content.DialogInterface; 23 import android.content.Intent; 24 import android.database.Cursor; 25 import android.net.Uri; 26 import android.os.Bundle; 27 import android.provider.DocumentsContract; 28 import android.provider.DocumentsContract.Document; 29 import android.support.v4.app.Fragment; 30 import android.support.v7.widget.RecyclerView; 31 import android.util.Log; 32 import android.view.LayoutInflater; 33 import android.view.View; 34 import android.view.ViewGroup; 35 import android.widget.Button; 36 import android.widget.EditText; 37 import android.widget.TextView; 38 import android.widget.Toast; 39 40 import java.util.ArrayList; 41 import java.util.List; 42 43 /** 44 * Fragment that demonstrates how to use Directory Selection API. 45 */ 46 public class DirectorySelectionFragment extends Fragment { 47 48 private static final String TAG = DirectorySelectionFragment.class.getSimpleName(); 49 50 public static final int REQUEST_CODE_OPEN_DIRECTORY = 1; 51 52 Uri mCurrentDirectoryUri; 53 TextView mCurrentDirectoryTextView; 54 Button mCreateDirectoryButton; 55 RecyclerView mRecyclerView; 56 DirectoryEntryAdapter mAdapter; 57 RecyclerView.LayoutManager mLayoutManager; 58 59 /** 60 * Use this factory method to create a new instance of 61 * this fragment using the provided parameters. 62 * 63 * @return A new instance of fragment {@link DirectorySelectionFragment}. 64 */ newInstance()65 public static DirectorySelectionFragment newInstance() { 66 DirectorySelectionFragment fragment = new DirectorySelectionFragment(); 67 return fragment; 68 } 69 DirectorySelectionFragment()70 public DirectorySelectionFragment() { 71 // Required empty public constructor 72 } 73 74 @Override onCreate(Bundle savedInstanceState)75 public void onCreate(Bundle savedInstanceState) { 76 super.onCreate(savedInstanceState); 77 } 78 79 @Override onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)80 public View onCreateView(LayoutInflater inflater, ViewGroup container, 81 Bundle savedInstanceState) { 82 // Inflate the layout for this fragment 83 return inflater.inflate(R.layout.fragment_directory_selection, container, false); 84 } 85 86 @Override onViewCreated(View rootView, Bundle savedInstanceState)87 public void onViewCreated(View rootView, Bundle savedInstanceState) { 88 super.onViewCreated(rootView, savedInstanceState); 89 90 rootView.findViewById(R.id.button_open_directory) 91 .setOnClickListener(new View.OnClickListener() { 92 @Override 93 public void onClick(View v) { 94 Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE); 95 startActivityForResult(intent, REQUEST_CODE_OPEN_DIRECTORY); 96 } 97 }); 98 99 mCurrentDirectoryTextView = (TextView) rootView 100 .findViewById(R.id.textview_current_directory); 101 mCreateDirectoryButton = (Button) rootView.findViewById(R.id.button_create_directory); 102 mCreateDirectoryButton.setOnClickListener(new View.OnClickListener() { 103 @Override 104 public void onClick(View v) { 105 final EditText editView = new EditText(getActivity()); 106 new AlertDialog.Builder(getActivity()) 107 .setTitle(R.string.create_directory) 108 .setView(editView) 109 .setPositiveButton(android.R.string.ok, 110 new DialogInterface.OnClickListener() { 111 public void onClick(DialogInterface dialog, int whichButton) { 112 createDirectory(mCurrentDirectoryUri, 113 editView.getText().toString()); 114 updateDirectoryEntries(mCurrentDirectoryUri); 115 } 116 }) 117 .setNegativeButton(android.R.string.cancel, 118 new DialogInterface.OnClickListener() { 119 public void onClick(DialogInterface dialog, int whichButton) { 120 } 121 }) 122 .show(); 123 } 124 }); 125 mRecyclerView = (RecyclerView) rootView.findViewById(R.id.recyclerview_directory_entries); 126 mLayoutManager = mRecyclerView.getLayoutManager(); 127 mRecyclerView.scrollToPosition(0); 128 mAdapter = new DirectoryEntryAdapter(new ArrayList<DirectoryEntry>()); 129 mRecyclerView.setAdapter(mAdapter); 130 } 131 132 @Override onActivityResult(int requestCode, int resultCode, Intent data)133 public void onActivityResult(int requestCode, int resultCode, Intent data) { 134 super.onActivityResult(requestCode, resultCode, data); 135 if (requestCode == REQUEST_CODE_OPEN_DIRECTORY && resultCode == Activity.RESULT_OK) { 136 Log.d(TAG, String.format("Open Directory result Uri : %s", data.getData())); 137 updateDirectoryEntries(data.getData()); 138 mAdapter.notifyDataSetChanged(); 139 } 140 } 141 142 143 /** 144 * Updates the current directory of the uri passed as an argument and its children directories. 145 * And updates the {@link #mRecyclerView} depending on the contents of the children. 146 * 147 * @param uri The uri of the current directory. 148 */ 149 //VisibileForTesting updateDirectoryEntries(Uri uri)150 void updateDirectoryEntries(Uri uri) { 151 ContentResolver contentResolver = getActivity().getContentResolver(); 152 Uri docUri = DocumentsContract.buildDocumentUriUsingTree(uri, 153 DocumentsContract.getTreeDocumentId(uri)); 154 Uri childrenUri = DocumentsContract.buildChildDocumentsUriUsingTree(uri, 155 DocumentsContract.getTreeDocumentId(uri)); 156 157 Cursor docCursor = contentResolver.query(docUri, new String[]{ 158 Document.COLUMN_DISPLAY_NAME, Document.COLUMN_MIME_TYPE}, null, null, null); 159 try { 160 while (docCursor.moveToNext()) { 161 Log.d(TAG, "found doc =" + docCursor.getString(0) + ", mime=" + docCursor 162 .getString(1)); 163 mCurrentDirectoryUri = uri; 164 mCurrentDirectoryTextView.setText(docCursor.getString(0)); 165 mCreateDirectoryButton.setEnabled(true); 166 } 167 } finally { 168 closeQuietly(docCursor); 169 } 170 171 Cursor childCursor = contentResolver.query(childrenUri, new String[]{ 172 Document.COLUMN_DISPLAY_NAME, Document.COLUMN_MIME_TYPE}, null, null, null); 173 try { 174 List<DirectoryEntry> directoryEntries = new ArrayList<>(); 175 while (childCursor.moveToNext()) { 176 Log.d(TAG, "found child=" + childCursor.getString(0) + ", mime=" + childCursor 177 .getString(1)); 178 DirectoryEntry entry = new DirectoryEntry(); 179 entry.fileName = childCursor.getString(0); 180 entry.mimeType = childCursor.getString(1); 181 directoryEntries.add(entry); 182 } 183 mAdapter.setDirectoryEntries(directoryEntries); 184 mAdapter.notifyDataSetChanged(); 185 } finally { 186 closeQuietly(childCursor); 187 } 188 } 189 190 /** 191 * Creates a directory under the directory represented as the uri in the argument. 192 * 193 * @param uri The uri of the directory under which a new directory is created. 194 * @param directoryName The directory name of a new directory. 195 */ 196 //VisibileForTesting createDirectory(Uri uri, String directoryName)197 void createDirectory(Uri uri, String directoryName) { 198 ContentResolver contentResolver = getActivity().getContentResolver(); 199 Uri docUri = DocumentsContract.buildDocumentUriUsingTree(uri, 200 DocumentsContract.getTreeDocumentId(uri)); 201 Uri directoryUri = DocumentsContract 202 .createDocument(contentResolver, docUri, Document.MIME_TYPE_DIR, directoryName); 203 if (directoryUri != null) { 204 Log.i(TAG, String.format( 205 "Created directory : %s, Document Uri : %s, Created directory Uri : %s", 206 directoryName, docUri, directoryUri)); 207 Toast.makeText(getActivity(), String.format("Created a directory [%s]", 208 directoryName), Toast.LENGTH_SHORT).show(); 209 } else { 210 Log.w(TAG, String.format("Failed to create a directory : %s, Uri %s", directoryName, 211 docUri)); 212 Toast.makeText(getActivity(), String.format("Failed to created a directory [%s] : ", 213 directoryName), Toast.LENGTH_SHORT).show(); 214 } 215 216 } 217 closeQuietly(AutoCloseable closeable)218 public void closeQuietly(AutoCloseable closeable) { 219 if (closeable != null) { 220 try { 221 closeable.close(); 222 } catch (RuntimeException rethrown) { 223 throw rethrown; 224 } catch (Exception ignored) { 225 } 226 } 227 } 228 } 229 230