1761122118b2437aee3a44e9263b73766986c12b8Jeff Sharkey/* 2761122118b2437aee3a44e9263b73766986c12b8Jeff Sharkey * Copyright (C) 2013 The Android Open Source Project 3761122118b2437aee3a44e9263b73766986c12b8Jeff Sharkey * 4761122118b2437aee3a44e9263b73766986c12b8Jeff Sharkey * Licensed under the Apache License, Version 2.0 (the "License"); 5761122118b2437aee3a44e9263b73766986c12b8Jeff Sharkey * you may not use this file except in compliance with the License. 6761122118b2437aee3a44e9263b73766986c12b8Jeff Sharkey * You may obtain a copy of the License at 7761122118b2437aee3a44e9263b73766986c12b8Jeff Sharkey * 8761122118b2437aee3a44e9263b73766986c12b8Jeff Sharkey * http://www.apache.org/licenses/LICENSE-2.0 9761122118b2437aee3a44e9263b73766986c12b8Jeff Sharkey * 10761122118b2437aee3a44e9263b73766986c12b8Jeff Sharkey * Unless required by applicable law or agreed to in writing, software 11761122118b2437aee3a44e9263b73766986c12b8Jeff Sharkey * distributed under the License is distributed on an "AS IS" BASIS, 12761122118b2437aee3a44e9263b73766986c12b8Jeff Sharkey * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13761122118b2437aee3a44e9263b73766986c12b8Jeff Sharkey * See the License for the specific language governing permissions and 14761122118b2437aee3a44e9263b73766986c12b8Jeff Sharkey * limitations under the License. 15761122118b2437aee3a44e9263b73766986c12b8Jeff Sharkey */ 16761122118b2437aee3a44e9263b73766986c12b8Jeff Sharkey 17761122118b2437aee3a44e9263b73766986c12b8Jeff Sharkeypackage com.android.documentsui; 18761122118b2437aee3a44e9263b73766986c12b8Jeff Sharkey 19d9caa6ab53aa784acaf241c0ded3c4ae2d342bf8Steve McKayimport static com.android.documentsui.base.Shared.TAG; 203fd11777c7eab734919efa4d8e7755aef803c19fJeff Sharkey 21761122118b2437aee3a44e9263b73766986c12b8Jeff Sharkeyimport android.app.AlertDialog; 22761122118b2437aee3a44e9263b73766986c12b8Jeff Sharkeyimport android.app.Dialog; 23761122118b2437aee3a44e9263b73766986c12b8Jeff Sharkeyimport android.app.DialogFragment; 24761122118b2437aee3a44e9263b73766986c12b8Jeff Sharkeyimport android.app.FragmentManager; 253fd11777c7eab734919efa4d8e7755aef803c19fJeff Sharkeyimport android.content.ContentProviderClient; 26761122118b2437aee3a44e9263b73766986c12b8Jeff Sharkeyimport android.content.ContentResolver; 27761122118b2437aee3a44e9263b73766986c12b8Jeff Sharkeyimport android.content.Context; 28761122118b2437aee3a44e9263b73766986c12b8Jeff Sharkeyimport android.content.DialogInterface; 29761122118b2437aee3a44e9263b73766986c12b8Jeff Sharkeyimport android.content.DialogInterface.OnClickListener; 30761122118b2437aee3a44e9263b73766986c12b8Jeff Sharkeyimport android.net.Uri; 319dd02629d12d05c2e77780dc6b9fcc7639192de6Jeff Sharkeyimport android.os.AsyncTask; 32761122118b2437aee3a44e9263b73766986c12b8Jeff Sharkeyimport android.os.Bundle; 33b6a7f2cd05f8c507dfac684aa4c693088e8c01c7Jeff Sharkeyimport android.provider.DocumentsContract; 34724deeb5558a517471e9bf7168b456e6daec62f8Jeff Sharkeyimport android.provider.DocumentsContract.Document; 35e9ec61ee67fa6ed49b56f0ae9af90e6d6f9b9f4eSteve McKayimport android.support.annotation.Nullable; 36c4693349d1a49dec8fd203f2c7adce18eee28b0aBen Kwaimport android.support.design.widget.Snackbar; 373fd11777c7eab734919efa4d8e7755aef803c19fJeff Sharkeyimport android.util.Log; 38ceeb3f7d93d1667243c2ad4b743e5c78add29261Steve McKayimport android.view.KeyEvent; 39279ec317f58ac335abd7d0beab70401ef430d4fdAga Wronskaimport android.view.inputmethod.EditorInfo; 40761122118b2437aee3a44e9263b73766986c12b8Jeff Sharkeyimport android.view.LayoutInflater; 41761122118b2437aee3a44e9263b73766986c12b8Jeff Sharkeyimport android.view.View; 42761122118b2437aee3a44e9263b73766986c12b8Jeff Sharkeyimport android.widget.EditText; 43ceeb3f7d93d1667243c2ad4b743e5c78add29261Steve McKayimport android.widget.TextView; 44ceeb3f7d93d1667243c2ad4b743e5c78add29261Steve McKayimport android.widget.TextView.OnEditorActionListener; 45761122118b2437aee3a44e9263b73766986c12b8Jeff Sharkey 46d080506e3aa8547605cd4783eb660775d7d2b8eeSteve McKayimport com.android.documentsui.base.DocumentInfo; 47d9caa6ab53aa784acaf241c0ded3c4ae2d342bf8Steve McKayimport com.android.documentsui.base.Shared; 48c8889af6757ecb348fb8fd6dadf84d67d3478cbfSteve McKayimport com.android.documentsui.ui.Snackbars; 49761122118b2437aee3a44e9263b73766986c12b8Jeff Sharkey 50761122118b2437aee3a44e9263b73766986c12b8Jeff Sharkey/** 51761122118b2437aee3a44e9263b73766986c12b8Jeff Sharkey * Dialog to create a new directory. 52761122118b2437aee3a44e9263b73766986c12b8Jeff Sharkey */ 53761122118b2437aee3a44e9263b73766986c12b8Jeff Sharkeypublic class CreateDirectoryFragment extends DialogFragment { 54761122118b2437aee3a44e9263b73766986c12b8Jeff Sharkey private static final String TAG_CREATE_DIRECTORY = "create_directory"; 55761122118b2437aee3a44e9263b73766986c12b8Jeff Sharkey 56761122118b2437aee3a44e9263b73766986c12b8Jeff Sharkey public static void show(FragmentManager fm) { 57761122118b2437aee3a44e9263b73766986c12b8Jeff Sharkey final CreateDirectoryFragment dialog = new CreateDirectoryFragment(); 58761122118b2437aee3a44e9263b73766986c12b8Jeff Sharkey dialog.show(fm, TAG_CREATE_DIRECTORY); 59761122118b2437aee3a44e9263b73766986c12b8Jeff Sharkey } 60761122118b2437aee3a44e9263b73766986c12b8Jeff Sharkey 61761122118b2437aee3a44e9263b73766986c12b8Jeff Sharkey @Override 62761122118b2437aee3a44e9263b73766986c12b8Jeff Sharkey public Dialog onCreateDialog(Bundle savedInstanceState) { 63761122118b2437aee3a44e9263b73766986c12b8Jeff Sharkey final Context context = getActivity(); 64761122118b2437aee3a44e9263b73766986c12b8Jeff Sharkey final ContentResolver resolver = context.getContentResolver(); 65761122118b2437aee3a44e9263b73766986c12b8Jeff Sharkey 66137437e161f23b8a2ecea1cb9d5826c65b1d9537Tomasz Mikolajewski final AlertDialog.Builder builder = new AlertDialog.Builder(context); 67761122118b2437aee3a44e9263b73766986c12b8Jeff Sharkey final LayoutInflater dialogInflater = LayoutInflater.from(builder.getContext()); 68761122118b2437aee3a44e9263b73766986c12b8Jeff Sharkey 693c23718ad126b4cc4f0a80dd29f0d4e411ccc1d3Aga Wronska final View view = dialogInflater.inflate(R.layout.dialog_file_name, null, false); 70ceeb3f7d93d1667243c2ad4b743e5c78add29261Steve McKay final EditText editText = (EditText) view.findViewById(android.R.id.text1); 71761122118b2437aee3a44e9263b73766986c12b8Jeff Sharkey 72761122118b2437aee3a44e9263b73766986c12b8Jeff Sharkey builder.setTitle(R.string.menu_create_dir); 73761122118b2437aee3a44e9263b73766986c12b8Jeff Sharkey builder.setView(view); 74761122118b2437aee3a44e9263b73766986c12b8Jeff Sharkey 75ceeb3f7d93d1667243c2ad4b743e5c78add29261Steve McKay builder.setPositiveButton( 76ceeb3f7d93d1667243c2ad4b743e5c78add29261Steve McKay android.R.string.ok, 77ceeb3f7d93d1667243c2ad4b743e5c78add29261Steve McKay new OnClickListener() { 78ceeb3f7d93d1667243c2ad4b743e5c78add29261Steve McKay @Override 79ceeb3f7d93d1667243c2ad4b743e5c78add29261Steve McKay public void onClick(DialogInterface dialog, int which) { 80ceeb3f7d93d1667243c2ad4b743e5c78add29261Steve McKay createDirectory(editText.getText().toString()); 81ceeb3f7d93d1667243c2ad4b743e5c78add29261Steve McKay } 82ceeb3f7d93d1667243c2ad4b743e5c78add29261Steve McKay }); 83f63b77709fb5b4de618e3699506f7710f62d551aJeff Sharkey 84761122118b2437aee3a44e9263b73766986c12b8Jeff Sharkey builder.setNegativeButton(android.R.string.cancel, null); 85ceeb3f7d93d1667243c2ad4b743e5c78add29261Steve McKay final AlertDialog dialog = builder.create(); 86ceeb3f7d93d1667243c2ad4b743e5c78add29261Steve McKay 87741ac6fffb3ee2441569412a28a1c4f3c2160d87Aga Wronska // Workaround for the problem - virtual keyboard doesn't show on the phone. 88741ac6fffb3ee2441569412a28a1c4f3c2160d87Aga Wronska Shared.ensureKeyboardPresent(context, dialog); 89741ac6fffb3ee2441569412a28a1c4f3c2160d87Aga Wronska 90ceeb3f7d93d1667243c2ad4b743e5c78add29261Steve McKay editText.setOnEditorActionListener( 91ceeb3f7d93d1667243c2ad4b743e5c78add29261Steve McKay new OnEditorActionListener() { 92ceeb3f7d93d1667243c2ad4b743e5c78add29261Steve McKay @Override 93e9ec61ee67fa6ed49b56f0ae9af90e6d6f9b9f4eSteve McKay public boolean onEditorAction( 94e9ec61ee67fa6ed49b56f0ae9af90e6d6f9b9f4eSteve McKay TextView view, int actionId, @Nullable KeyEvent event) { 95279ec317f58ac335abd7d0beab70401ef430d4fdAga Wronska if ((actionId == EditorInfo.IME_ACTION_DONE) || (event != null 96e9ec61ee67fa6ed49b56f0ae9af90e6d6f9b9f4eSteve McKay && event.getKeyCode() == KeyEvent.KEYCODE_ENTER 97279ec317f58ac335abd7d0beab70401ef430d4fdAga Wronska && event.hasNoModifiers())) { 98ceeb3f7d93d1667243c2ad4b743e5c78add29261Steve McKay createDirectory(editText.getText().toString()); 99ceeb3f7d93d1667243c2ad4b743e5c78add29261Steve McKay dialog.dismiss(); 100ceeb3f7d93d1667243c2ad4b743e5c78add29261Steve McKay return true; 101ceeb3f7d93d1667243c2ad4b743e5c78add29261Steve McKay } 102ceeb3f7d93d1667243c2ad4b743e5c78add29261Steve McKay return false; 103ceeb3f7d93d1667243c2ad4b743e5c78add29261Steve McKay } 104ceeb3f7d93d1667243c2ad4b743e5c78add29261Steve McKay }); 105ceeb3f7d93d1667243c2ad4b743e5c78add29261Steve McKay 106ceeb3f7d93d1667243c2ad4b743e5c78add29261Steve McKay 107ceeb3f7d93d1667243c2ad4b743e5c78add29261Steve McKay return dialog; 108ceeb3f7d93d1667243c2ad4b743e5c78add29261Steve McKay } 109ceeb3f7d93d1667243c2ad4b743e5c78add29261Steve McKay 110ceeb3f7d93d1667243c2ad4b743e5c78add29261Steve McKay private void createDirectory(String name) { 111ceeb3f7d93d1667243c2ad4b743e5c78add29261Steve McKay final BaseActivity activity = (BaseActivity) getActivity(); 112ceeb3f7d93d1667243c2ad4b743e5c78add29261Steve McKay final DocumentInfo cwd = activity.getCurrentDirectory(); 113761122118b2437aee3a44e9263b73766986c12b8Jeff Sharkey 114ceeb3f7d93d1667243c2ad4b743e5c78add29261Steve McKay new CreateDirectoryTask(activity, cwd, name).executeOnExecutor( 115ceeb3f7d93d1667243c2ad4b743e5c78add29261Steve McKay ProviderExecutor.forAuthority(cwd.authority)); 116761122118b2437aee3a44e9263b73766986c12b8Jeff Sharkey } 1179dd02629d12d05c2e77780dc6b9fcc7639192de6Jeff Sharkey 1189dd02629d12d05c2e77780dc6b9fcc7639192de6Jeff Sharkey private class CreateDirectoryTask extends AsyncTask<Void, Void, DocumentInfo> { 119d0a2a2c4e061da0de1b0008b841cacd9fc4416edSteve McKay private final BaseActivity mActivity; 1200aa2692b5f9eb9d0a7b2cb763dcfb75bb728f31aJeff Sharkey private final DocumentInfo mCwd; 1219dd02629d12d05c2e77780dc6b9fcc7639192de6Jeff Sharkey private final String mDisplayName; 1229dd02629d12d05c2e77780dc6b9fcc7639192de6Jeff Sharkey 1230aa2692b5f9eb9d0a7b2cb763dcfb75bb728f31aJeff Sharkey public CreateDirectoryTask( 124d0a2a2c4e061da0de1b0008b841cacd9fc4416edSteve McKay BaseActivity activity, DocumentInfo cwd, String displayName) { 1250aa2692b5f9eb9d0a7b2cb763dcfb75bb728f31aJeff Sharkey mActivity = activity; 1260aa2692b5f9eb9d0a7b2cb763dcfb75bb728f31aJeff Sharkey mCwd = cwd; 1279dd02629d12d05c2e77780dc6b9fcc7639192de6Jeff Sharkey mDisplayName = displayName; 1289dd02629d12d05c2e77780dc6b9fcc7639192de6Jeff Sharkey } 1299dd02629d12d05c2e77780dc6b9fcc7639192de6Jeff Sharkey 1309dd02629d12d05c2e77780dc6b9fcc7639192de6Jeff Sharkey @Override 1314be51f196d60ba23856b646de3091364230258b0Jeff Sharkey protected void onPreExecute() { 1324be51f196d60ba23856b646de3091364230258b0Jeff Sharkey mActivity.setPending(true); 1334be51f196d60ba23856b646de3091364230258b0Jeff Sharkey } 1344be51f196d60ba23856b646de3091364230258b0Jeff Sharkey 1354be51f196d60ba23856b646de3091364230258b0Jeff Sharkey @Override 1369dd02629d12d05c2e77780dc6b9fcc7639192de6Jeff Sharkey protected DocumentInfo doInBackground(Void... params) { 1370aa2692b5f9eb9d0a7b2cb763dcfb75bb728f31aJeff Sharkey final ContentResolver resolver = mActivity.getContentResolver(); 1383fd11777c7eab734919efa4d8e7755aef803c19fJeff Sharkey ContentProviderClient client = null; 1399dd02629d12d05c2e77780dc6b9fcc7639192de6Jeff Sharkey try { 1403fd11777c7eab734919efa4d8e7755aef803c19fJeff Sharkey client = DocumentsApplication.acquireUnstableProviderOrThrow( 1410aa2692b5f9eb9d0a7b2cb763dcfb75bb728f31aJeff Sharkey resolver, mCwd.derivedUri.getAuthority()); 1423fd11777c7eab734919efa4d8e7755aef803c19fJeff Sharkey final Uri childUri = DocumentsContract.createDocument( 1430aa2692b5f9eb9d0a7b2cb763dcfb75bb728f31aJeff Sharkey client, mCwd.derivedUri, Document.MIME_TYPE_DIR, mDisplayName); 1449dd02629d12d05c2e77780dc6b9fcc7639192de6Jeff Sharkey return DocumentInfo.fromUri(resolver, childUri); 1453fd11777c7eab734919efa4d8e7755aef803c19fJeff Sharkey } catch (Exception e) { 1463fd11777c7eab734919efa4d8e7755aef803c19fJeff Sharkey Log.w(TAG, "Failed to create directory", e); 1479dd02629d12d05c2e77780dc6b9fcc7639192de6Jeff Sharkey return null; 1483fd11777c7eab734919efa4d8e7755aef803c19fJeff Sharkey } finally { 1493fd11777c7eab734919efa4d8e7755aef803c19fJeff Sharkey ContentProviderClient.releaseQuietly(client); 1509dd02629d12d05c2e77780dc6b9fcc7639192de6Jeff Sharkey } 1519dd02629d12d05c2e77780dc6b9fcc7639192de6Jeff Sharkey } 1529dd02629d12d05c2e77780dc6b9fcc7639192de6Jeff Sharkey 1539dd02629d12d05c2e77780dc6b9fcc7639192de6Jeff Sharkey @Override 1549dd02629d12d05c2e77780dc6b9fcc7639192de6Jeff Sharkey protected void onPostExecute(DocumentInfo result) { 1559dd02629d12d05c2e77780dc6b9fcc7639192de6Jeff Sharkey if (result != null) { 1569dd02629d12d05c2e77780dc6b9fcc7639192de6Jeff Sharkey // Navigate into newly created child 157351a749751bc501c9d7c0f03ee5b542f0e7a7d7cSteve McKay mActivity.onDirectoryCreated(result); 15846a868a96931a097d098ce3b76068b4946e38662Aga Wronska Metrics.logCreateDirOperation(getContext()); 1599dd02629d12d05c2e77780dc6b9fcc7639192de6Jeff Sharkey } else { 16046a868a96931a097d098ce3b76068b4946e38662Aga Wronska Snackbars.makeSnackbar(mActivity, R.string.create_error, Snackbar.LENGTH_SHORT) 16146a868a96931a097d098ce3b76068b4946e38662Aga Wronska .show(); 16246a868a96931a097d098ce3b76068b4946e38662Aga Wronska Metrics.logCreateDirError(getContext()); 1639dd02629d12d05c2e77780dc6b9fcc7639192de6Jeff Sharkey } 1644be51f196d60ba23856b646de3091364230258b0Jeff Sharkey mActivity.setPending(false); 1659dd02629d12d05c2e77780dc6b9fcc7639192de6Jeff Sharkey } 1669dd02629d12d05c2e77780dc6b9fcc7639192de6Jeff Sharkey } 167761122118b2437aee3a44e9263b73766986c12b8Jeff Sharkey} 168