166516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey/* 266516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey * Copyright (C) 2013 The Android Open Source Project 366516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey * 466516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey * Licensed under the Apache License, Version 2.0 (the "License"); 566516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey * you may not use this file except in compliance with the License. 666516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey * You may obtain a copy of the License at 766516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey * 866516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey * http://www.apache.org/licenses/LICENSE-2.0 966516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey * 1066516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey * Unless required by applicable law or agreed to in writing, software 1166516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey * distributed under the License is distributed on an "AS IS" BASIS, 1266516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1366516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey * See the License for the specific language governing permissions and 1466516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey * limitations under the License. 1566516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey */ 1666516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey 1766516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkeypackage com.android.documentsui; 1866516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey 1958efce36cd1b26006e08ddd696292bf06fc34c81Steve McKayimport static com.android.documentsui.Shared.TAG; 207aa7601c09ab5d87cc15a0ed9a8f511d494a4cbcJeff Sharkey 2166516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkeyimport android.app.AlertDialog; 2266516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkeyimport android.app.Dialog; 2366516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkeyimport android.app.DialogFragment; 2466516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkeyimport android.app.FragmentManager; 257aa7601c09ab5d87cc15a0ed9a8f511d494a4cbcJeff Sharkeyimport android.content.ContentProviderClient; 2666516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkeyimport android.content.ContentResolver; 2766516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkeyimport android.content.Context; 2866516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkeyimport android.content.DialogInterface; 2966516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkeyimport android.content.DialogInterface.OnClickListener; 3066516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkeyimport android.net.Uri; 316efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkeyimport android.os.AsyncTask; 3266516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkeyimport android.os.Bundle; 33aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkeyimport android.provider.DocumentsContract; 34ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkeyimport android.provider.DocumentsContract.Document; 357e392b78451373c83367691b86ba14c8710d1030Steve McKayimport android.support.annotation.Nullable; 3694b486d32c10d5ffbd8627977ca4759c246ecf4bBen Kwaimport android.support.design.widget.Snackbar; 377aa7601c09ab5d87cc15a0ed9a8f511d494a4cbcJeff Sharkeyimport android.util.Log; 38a521d0d318f867ee65d86b8749f6da3c13ebd9a4Steve McKayimport android.view.KeyEvent; 39404168096789c6dde4db82dc6360a1a25e6ff636Aga Wronskaimport android.view.inputmethod.EditorInfo; 4066516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkeyimport android.view.LayoutInflater; 4166516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkeyimport android.view.View; 4266516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkeyimport android.widget.EditText; 43a521d0d318f867ee65d86b8749f6da3c13ebd9a4Steve McKayimport android.widget.TextView; 44a521d0d318f867ee65d86b8749f6da3c13ebd9a4Steve McKayimport android.widget.TextView.OnEditorActionListener; 4566516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey 46ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkeyimport com.android.documentsui.model.DocumentInfo; 4766516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey 4866516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey/** 4966516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey * Dialog to create a new directory. 5066516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey */ 5166516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkeypublic class CreateDirectoryFragment extends DialogFragment { 5266516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey private static final String TAG_CREATE_DIRECTORY = "create_directory"; 5366516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey 5466516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey public static void show(FragmentManager fm) { 5566516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey final CreateDirectoryFragment dialog = new CreateDirectoryFragment(); 5666516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey dialog.show(fm, TAG_CREATE_DIRECTORY); 5766516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey } 5866516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey 5966516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey @Override 6066516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey public Dialog onCreateDialog(Bundle savedInstanceState) { 6166516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey final Context context = getActivity(); 6266516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey final ContentResolver resolver = context.getContentResolver(); 6366516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey 645527f6457ed78771fe27352533cdc0f7123bd6e6Tomasz Mikolajewski final AlertDialog.Builder builder = new AlertDialog.Builder(context); 6566516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey final LayoutInflater dialogInflater = LayoutInflater.from(builder.getContext()); 6666516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey 673b327ef9f9dec19612202b4b0b450966870a077fAga Wronska final View view = dialogInflater.inflate(R.layout.dialog_file_name, null, false); 68a521d0d318f867ee65d86b8749f6da3c13ebd9a4Steve McKay final EditText editText = (EditText) view.findViewById(android.R.id.text1); 6966516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey 7066516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey builder.setTitle(R.string.menu_create_dir); 7166516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey builder.setView(view); 7266516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey 73a521d0d318f867ee65d86b8749f6da3c13ebd9a4Steve McKay builder.setPositiveButton( 74a521d0d318f867ee65d86b8749f6da3c13ebd9a4Steve McKay android.R.string.ok, 75a521d0d318f867ee65d86b8749f6da3c13ebd9a4Steve McKay new OnClickListener() { 76a521d0d318f867ee65d86b8749f6da3c13ebd9a4Steve McKay @Override 77a521d0d318f867ee65d86b8749f6da3c13ebd9a4Steve McKay public void onClick(DialogInterface dialog, int which) { 78a521d0d318f867ee65d86b8749f6da3c13ebd9a4Steve McKay createDirectory(editText.getText().toString()); 79a521d0d318f867ee65d86b8749f6da3c13ebd9a4Steve McKay } 80a521d0d318f867ee65d86b8749f6da3c13ebd9a4Steve McKay }); 81d01571e6d4e1c403534e19142720530d324eac9bJeff Sharkey 8266516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey builder.setNegativeButton(android.R.string.cancel, null); 83a521d0d318f867ee65d86b8749f6da3c13ebd9a4Steve McKay final AlertDialog dialog = builder.create(); 84a521d0d318f867ee65d86b8749f6da3c13ebd9a4Steve McKay 8502c532fb54ff1aaad0bdcbbd3f1fee21d4e5dcdeAga Wronska // Workaround for the problem - virtual keyboard doesn't show on the phone. 8602c532fb54ff1aaad0bdcbbd3f1fee21d4e5dcdeAga Wronska Shared.ensureKeyboardPresent(context, dialog); 8702c532fb54ff1aaad0bdcbbd3f1fee21d4e5dcdeAga Wronska 88a521d0d318f867ee65d86b8749f6da3c13ebd9a4Steve McKay editText.setOnEditorActionListener( 89a521d0d318f867ee65d86b8749f6da3c13ebd9a4Steve McKay new OnEditorActionListener() { 90a521d0d318f867ee65d86b8749f6da3c13ebd9a4Steve McKay @Override 917e392b78451373c83367691b86ba14c8710d1030Steve McKay public boolean onEditorAction( 927e392b78451373c83367691b86ba14c8710d1030Steve McKay TextView view, int actionId, @Nullable KeyEvent event) { 93404168096789c6dde4db82dc6360a1a25e6ff636Aga Wronska if ((actionId == EditorInfo.IME_ACTION_DONE) || (event != null 947e392b78451373c83367691b86ba14c8710d1030Steve McKay && event.getKeyCode() == KeyEvent.KEYCODE_ENTER 95404168096789c6dde4db82dc6360a1a25e6ff636Aga Wronska && event.hasNoModifiers())) { 96a521d0d318f867ee65d86b8749f6da3c13ebd9a4Steve McKay createDirectory(editText.getText().toString()); 97a521d0d318f867ee65d86b8749f6da3c13ebd9a4Steve McKay dialog.dismiss(); 98a521d0d318f867ee65d86b8749f6da3c13ebd9a4Steve McKay return true; 99a521d0d318f867ee65d86b8749f6da3c13ebd9a4Steve McKay } 100a521d0d318f867ee65d86b8749f6da3c13ebd9a4Steve McKay return false; 101a521d0d318f867ee65d86b8749f6da3c13ebd9a4Steve McKay } 102a521d0d318f867ee65d86b8749f6da3c13ebd9a4Steve McKay }); 103a521d0d318f867ee65d86b8749f6da3c13ebd9a4Steve McKay 104a521d0d318f867ee65d86b8749f6da3c13ebd9a4Steve McKay 105a521d0d318f867ee65d86b8749f6da3c13ebd9a4Steve McKay return dialog; 106a521d0d318f867ee65d86b8749f6da3c13ebd9a4Steve McKay } 107a521d0d318f867ee65d86b8749f6da3c13ebd9a4Steve McKay 108a521d0d318f867ee65d86b8749f6da3c13ebd9a4Steve McKay private void createDirectory(String name) { 109a521d0d318f867ee65d86b8749f6da3c13ebd9a4Steve McKay final BaseActivity activity = (BaseActivity) getActivity(); 110a521d0d318f867ee65d86b8749f6da3c13ebd9a4Steve McKay final DocumentInfo cwd = activity.getCurrentDirectory(); 11166516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey 112a521d0d318f867ee65d86b8749f6da3c13ebd9a4Steve McKay new CreateDirectoryTask(activity, cwd, name).executeOnExecutor( 113a521d0d318f867ee65d86b8749f6da3c13ebd9a4Steve McKay ProviderExecutor.forAuthority(cwd.authority)); 11466516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey } 1156efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey 1166efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey private class CreateDirectoryTask extends AsyncTask<Void, Void, DocumentInfo> { 117e934ce6f8430f50d1d22bccd3b341b982f5541eeSteve McKay private final BaseActivity mActivity; 11878b137030864c028920046a38b5a040f5920fddfJeff Sharkey private final DocumentInfo mCwd; 1196efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey private final String mDisplayName; 1206efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey 12178b137030864c028920046a38b5a040f5920fddfJeff Sharkey public CreateDirectoryTask( 122e934ce6f8430f50d1d22bccd3b341b982f5541eeSteve McKay BaseActivity activity, DocumentInfo cwd, String displayName) { 12378b137030864c028920046a38b5a040f5920fddfJeff Sharkey mActivity = activity; 12478b137030864c028920046a38b5a040f5920fddfJeff Sharkey mCwd = cwd; 1256efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey mDisplayName = displayName; 1266efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey } 1276efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey 1286efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey @Override 12904d45a0bdd47c243ad7ccb179aa52a83e7bf45dbJeff Sharkey protected void onPreExecute() { 13004d45a0bdd47c243ad7ccb179aa52a83e7bf45dbJeff Sharkey mActivity.setPending(true); 13104d45a0bdd47c243ad7ccb179aa52a83e7bf45dbJeff Sharkey } 13204d45a0bdd47c243ad7ccb179aa52a83e7bf45dbJeff Sharkey 13304d45a0bdd47c243ad7ccb179aa52a83e7bf45dbJeff Sharkey @Override 1346efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey protected DocumentInfo doInBackground(Void... params) { 13578b137030864c028920046a38b5a040f5920fddfJeff Sharkey final ContentResolver resolver = mActivity.getContentResolver(); 1367aa7601c09ab5d87cc15a0ed9a8f511d494a4cbcJeff Sharkey ContentProviderClient client = null; 1376efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey try { 1387aa7601c09ab5d87cc15a0ed9a8f511d494a4cbcJeff Sharkey client = DocumentsApplication.acquireUnstableProviderOrThrow( 13978b137030864c028920046a38b5a040f5920fddfJeff Sharkey resolver, mCwd.derivedUri.getAuthority()); 1407aa7601c09ab5d87cc15a0ed9a8f511d494a4cbcJeff Sharkey final Uri childUri = DocumentsContract.createDocument( 14178b137030864c028920046a38b5a040f5920fddfJeff Sharkey client, mCwd.derivedUri, Document.MIME_TYPE_DIR, mDisplayName); 1426efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey return DocumentInfo.fromUri(resolver, childUri); 1437aa7601c09ab5d87cc15a0ed9a8f511d494a4cbcJeff Sharkey } catch (Exception e) { 1447aa7601c09ab5d87cc15a0ed9a8f511d494a4cbcJeff Sharkey Log.w(TAG, "Failed to create directory", e); 1456efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey return null; 1467aa7601c09ab5d87cc15a0ed9a8f511d494a4cbcJeff Sharkey } finally { 1477aa7601c09ab5d87cc15a0ed9a8f511d494a4cbcJeff Sharkey ContentProviderClient.releaseQuietly(client); 1486efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey } 1496efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey } 1506efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey 1516efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey @Override 1526efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey protected void onPostExecute(DocumentInfo result) { 1536efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey if (result != null) { 1546efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey // Navigate into newly created child 1556eaf3863c81779233c032b7f7fc5b90e94f5f70aSteve McKay mActivity.onDirectoryCreated(result); 1564e8c7f61bea7c8a3dd750db13b6319a7bd84dc3cAga Wronska Metrics.logCreateDirOperation(getContext()); 1576efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey } else { 1584e8c7f61bea7c8a3dd750db13b6319a7bd84dc3cAga Wronska Snackbars.makeSnackbar(mActivity, R.string.create_error, Snackbar.LENGTH_SHORT) 1594e8c7f61bea7c8a3dd750db13b6319a7bd84dc3cAga Wronska .show(); 1604e8c7f61bea7c8a3dd750db13b6319a7bd84dc3cAga Wronska Metrics.logCreateDirError(getContext()); 1616efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey } 16204d45a0bdd47c243ad7ccb179aa52a83e7bf45dbJeff Sharkey mActivity.setPending(false); 1636efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey } 1646efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey } 16566516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey} 166