Loading packages/DocumentsUI/res/menu/mode_directory.xml +4 −0 Original line number Original line Diff line number Diff line Loading @@ -37,4 +37,8 @@ android:id="@+id/menu_copy" android:id="@+id/menu_copy" android:title="@string/menu_copy" android:title="@string/menu_copy" android:showAsAction="never" /> android:showAsAction="never" /> <item android:id="@+id/menu_move" android:title="@string/menu_move" android:showAsAction="never" /> </menu> </menu> packages/DocumentsUI/res/values/strings.xml +6 −0 Original line number Original line Diff line number Diff line Loading @@ -50,6 +50,8 @@ <string name="menu_select_all">Select All</string> <string name="menu_select_all">Select All</string> <!-- Menu item title that copies the selected documents [CHAR LIMIT=24] --> <!-- Menu item title that copies the selected documents [CHAR LIMIT=24] --> <string name="menu_copy">Copy to\u2026</string> <string name="menu_copy">Copy to\u2026</string> <!-- Menu item title that moves the selected documents [CHAR LIMIT=24] --> <string name="menu_move">Move to\u2026</string> <!-- Menu item that reveals internal storage built into the device [CHAR LIMIT=24] --> <!-- Menu item that reveals internal storage built into the device [CHAR LIMIT=24] --> <string name="menu_advanced_show" product="nosdcard">Show internal storage</string> <string name="menu_advanced_show" product="nosdcard">Show internal storage</string> Loading Loading @@ -124,6 +126,10 @@ <item quantity="one">Copying <xliff:g id="count" example="1">%1$d</xliff:g> file.</item> <item quantity="one">Copying <xliff:g id="count" example="1">%1$d</xliff:g> file.</item> <item quantity="other">Copying <xliff:g id="count" example="3">%1$d</xliff:g> files.</item> <item quantity="other">Copying <xliff:g id="count" example="3">%1$d</xliff:g> files.</item> </plurals> </plurals> <plurals name="move_begin"> <item quantity="one">Moving <xliff:g id="count" example="1">%1$d</xliff:g> file.</item> <item quantity="other">Moving <xliff:g id="count" example="3">%1$d</xliff:g> files.</item> </plurals> <!-- Text shown on the copy notification while DocumentsUI performs setup in preparation for copying files [CHAR LIMIT=32] --> <!-- Text shown on the copy notification while DocumentsUI performs setup in preparation for copying files [CHAR LIMIT=32] --> <string name="copy_preparing">Preparing for copy\u2026</string> <string name="copy_preparing">Preparing for copy\u2026</string> <!-- Title of the copy error notification [CHAR LIMIT=48] --> <!-- Title of the copy error notification [CHAR LIMIT=48] --> Loading packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java +10 −8 Original line number Original line Diff line number Diff line Loading @@ -269,14 +269,16 @@ abstract class BaseActivity extends Activity { /** Derived after loader */ /** Derived after loader */ public int derivedSortOrder = SORT_ORDER_DISPLAY_NAME; public int derivedSortOrder = SORT_ORDER_DISPLAY_NAME; public boolean allowMultiple = false; public boolean allowMultiple; public boolean showSize = false; public boolean showSize; public boolean localOnly = false; public boolean localOnly ; public boolean forceAdvanced = false; public boolean forceAdvanced ; public boolean showAdvanced = false; public boolean showAdvanced ; public boolean stackTouched = false; public boolean stackTouched ; public boolean restored = false; public boolean restored ; public boolean directoryCopy = false; public boolean directoryCopy ; /** Transfer mode for file copy/move operations. */ public int transferMode; /** Current user navigation stack; empty implies recents. */ /** Current user navigation stack; empty implies recents. */ public DocumentStack stack = new DocumentStack(); public DocumentStack stack = new DocumentStack(); Loading packages/DocumentsUI/src/com/android/documentsui/CopyService.java +45 −14 Original line number Original line Diff line number Diff line Loading @@ -61,6 +61,11 @@ public class CopyService extends IntentService { public static final String EXTRA_SRC_LIST = "com.android.documentsui.SRC_LIST"; public static final String EXTRA_SRC_LIST = "com.android.documentsui.SRC_LIST"; public static final String EXTRA_STACK = "com.android.documentsui.STACK"; public static final String EXTRA_STACK = "com.android.documentsui.STACK"; public static final String EXTRA_FAILURE = "com.android.documentsui.FAILURE"; public static final String EXTRA_FAILURE = "com.android.documentsui.FAILURE"; public static final String EXTRA_TRANSFER_MODE = "com.android.documentsui.TRANSFER_MODE"; public static final int TRANSFER_MODE_NONE = 0; public static final int TRANSFER_MODE_COPY = 1; public static final int TRANSFER_MODE_MOVE = 2; // TODO: Move it to a shared file when more operations are implemented. // TODO: Move it to a shared file when more operations are implemented. public static final int FAILURE_COPY = 1; public static final int FAILURE_COPY = 1; Loading Loading @@ -101,15 +106,19 @@ public class CopyService extends IntentService { * @param srcDocs A list of src files to copy. * @param srcDocs A list of src files to copy. * @param dstStack The copy destination stack. * @param dstStack The copy destination stack. */ */ public static void start(Context context, List<DocumentInfo> srcDocs, DocumentStack dstStack) { public static void start(Context context, List<DocumentInfo> srcDocs, DocumentStack dstStack, int mode) { final Resources res = context.getResources(); final Resources res = context.getResources(); final Intent copyIntent = new Intent(context, CopyService.class); final Intent copyIntent = new Intent(context, CopyService.class); copyIntent.putParcelableArrayListExtra( copyIntent.putParcelableArrayListExtra( EXTRA_SRC_LIST, new ArrayList<DocumentInfo>(srcDocs)); EXTRA_SRC_LIST, new ArrayList<DocumentInfo>(srcDocs)); copyIntent.putExtra(EXTRA_STACK, (Parcelable) dstStack); copyIntent.putExtra(EXTRA_STACK, (Parcelable) dstStack); copyIntent.putExtra(EXTRA_TRANSFER_MODE, mode); int toastMessage = (mode == TRANSFER_MODE_COPY) ? R.plurals.copy_begin : R.plurals.move_begin; Toast.makeText(context, Toast.makeText(context, res.getQuantityString(R.plurals.copy_begin, srcDocs.size(), srcDocs.size()), res.getQuantityString(toastMessage, srcDocs.size(), srcDocs.size()), Toast.LENGTH_SHORT).show(); Toast.LENGTH_SHORT).show(); context.startService(copyIntent); context.startService(copyIntent); } } Loading @@ -131,6 +140,8 @@ public class CopyService extends IntentService { final ArrayList<DocumentInfo> srcs = intent.getParcelableArrayListExtra(EXTRA_SRC_LIST); final ArrayList<DocumentInfo> srcs = intent.getParcelableArrayListExtra(EXTRA_SRC_LIST); final DocumentStack stack = intent.getParcelableExtra(EXTRA_STACK); final DocumentStack stack = intent.getParcelableExtra(EXTRA_STACK); // Copy by default. final int transferMode = intent.getIntExtra(EXTRA_TRANSFER_MODE, TRANSFER_MODE_COPY); try { try { // Acquire content providers. // Acquire content providers. Loading @@ -142,7 +153,7 @@ public class CopyService extends IntentService { setupCopyJob(srcs, stack); setupCopyJob(srcs, stack); for (int i = 0; i < srcs.size() && !mIsCancelled; ++i) { for (int i = 0; i < srcs.size() && !mIsCancelled; ++i) { copy(srcs.get(i), stack.peek()); copy(srcs.get(i), stack.peek(), transferMode); } } } catch (Exception e) { } catch (Exception e) { // Catch-all to prevent any copy errors from wedging the app. // Catch-all to prevent any copy errors from wedging the app. Loading Loading @@ -173,8 +184,6 @@ public class CopyService extends IntentService { .setAutoCancel(true); .setAutoCancel(true); mNotificationManager.notify(mJobId, 0, errorBuilder.build()); mNotificationManager.notify(mJobId, 0, errorBuilder.build()); } } // TODO: Display a toast if the copy was cancelled. } } } } Loading Loading @@ -377,7 +386,8 @@ public class CopyService extends IntentService { * @param dstDirInfo The destination directory. * @param dstDirInfo The destination directory. * @throws RemoteException * @throws RemoteException */ */ private void copy(DocumentInfo srcInfo, DocumentInfo dstDirInfo) throws RemoteException { private void copy(DocumentInfo srcInfo, DocumentInfo dstDirInfo, int mode) throws RemoteException { final Uri dstUri = DocumentsContract.createDocument(mDstClient, dstDirInfo.derivedUri, final Uri dstUri = DocumentsContract.createDocument(mDstClient, dstDirInfo.derivedUri, srcInfo.mimeType, srcInfo.displayName); srcInfo.mimeType, srcInfo.displayName); if (dstUri == null) { if (dstUri == null) { Loading @@ -388,9 +398,9 @@ public class CopyService extends IntentService { } } if (Document.MIME_TYPE_DIR.equals(srcInfo.mimeType)) { if (Document.MIME_TYPE_DIR.equals(srcInfo.mimeType)) { copyDirectoryHelper(srcInfo.derivedUri, dstUri); copyDirectoryHelper(srcInfo.derivedUri, dstUri, mode); } else { } else { copyFileHelper(srcInfo.derivedUri, dstUri); copyFileHelper(srcInfo.derivedUri, dstUri, mode); } } } } Loading @@ -403,7 +413,8 @@ public class CopyService extends IntentService { * @param dstDirUri URI of the directory to copy to. Must be created beforehand. * @param dstDirUri URI of the directory to copy to. Must be created beforehand. * @throws RemoteException * @throws RemoteException */ */ private void copyDirectoryHelper(Uri srcDirUri, Uri dstDirUri) throws RemoteException { private void copyDirectoryHelper(Uri srcDirUri, Uri dstDirUri, int mode) throws RemoteException { // Recurse into directories. Copy children into the new subdirectory. // Recurse into directories. Copy children into the new subdirectory. final String queryColumns[] = new String[] { final String queryColumns[] = new String[] { Document.COLUMN_DISPLAY_NAME, Document.COLUMN_DISPLAY_NAME, Loading @@ -424,9 +435,20 @@ public class CopyService extends IntentService { final Uri childUri = DocumentsContract.buildDocumentUri(srcDirUri.getAuthority(), final Uri childUri = DocumentsContract.buildDocumentUri(srcDirUri.getAuthority(), getCursorString(cursor, Document.COLUMN_DOCUMENT_ID)); getCursorString(cursor, Document.COLUMN_DOCUMENT_ID)); if (Document.MIME_TYPE_DIR.equals(childMimeType)) { if (Document.MIME_TYPE_DIR.equals(childMimeType)) { copyDirectoryHelper(childUri, dstUri); copyDirectoryHelper(childUri, dstUri, mode); } else { } else { copyFileHelper(childUri, dstUri); copyFileHelper(childUri, dstUri, mode); } } if (mode == TRANSFER_MODE_MOVE) { try { DocumentsContract.deleteDocument(mSrcClient, srcDirUri); } catch (RemoteException e) { // RemoteExceptions usually signal that the connection is dead, so there's no // point attempting to continue. Propagate the exception up so the copy job is // cancelled. Log.w(TAG, "Failed to clean up after move: " + srcDirUri, e); throw e; } } } } } finally { } finally { Loading @@ -441,7 +463,8 @@ public class CopyService extends IntentService { * @param dstUri URI of the *file* to copy to. Must be created beforehand. * @param dstUri URI of the *file* to copy to. Must be created beforehand. * @throws RemoteException * @throws RemoteException */ */ private void copyFileHelper(Uri srcUri, Uri dstUri) throws RemoteException { private void copyFileHelper(Uri srcUri, Uri dstUri, int mode) throws RemoteException { // Copy an individual file. // Copy an individual file. CancellationSignal canceller = new CancellationSignal(); CancellationSignal canceller = new CancellationSignal(); ParcelFileDescriptor srcFile = null; ParcelFileDescriptor srcFile = null; Loading Loading @@ -494,11 +517,19 @@ public class CopyService extends IntentService { try { try { DocumentsContract.deleteDocument(mDstClient, dstUri); DocumentsContract.deleteDocument(mDstClient, dstUri); } catch (RemoteException e) { } catch (RemoteException e) { Log.w(TAG, "Failed to clean up: " + srcUri, e); Log.w(TAG, "Failed to clean up after copy error: " + dstUri, e); // RemoteExceptions usually signal that the connection is dead, so there's no point // RemoteExceptions usually signal that the connection is dead, so there's no point // attempting to continue. Propagate the exception up so the copy job is cancelled. // attempting to continue. Propagate the exception up so the copy job is cancelled. throw e; throw e; } } } else if (mode == TRANSFER_MODE_MOVE) { // Clean up src files after a successful move. try { DocumentsContract.deleteDocument(mSrcClient, srcUri); } catch (RemoteException e) { Log.w(TAG, "Failed to clean up after move: " + srcUri, e); throw e; } } } } } } } packages/DocumentsUI/src/com/android/documentsui/DirectoryFragment.java +13 −5 Original line number Original line Diff line number Diff line Loading @@ -369,7 +369,8 @@ public class DirectoryFragment extends Fragment { } } CopyService.start(getActivity(), getDisplayState(this).selectedDocumentsForCopy, CopyService.start(getActivity(), getDisplayState(this).selectedDocumentsForCopy, (DocumentStack) data.getParcelableExtra(CopyService.EXTRA_STACK)); (DocumentStack) data.getParcelableExtra(CopyService.EXTRA_STACK), data.getIntExtra(CopyService.EXTRA_TRANSFER_MODE, CopyService.TRANSFER_MODE_NONE)); } } @Override @Override Loading Loading @@ -502,6 +503,7 @@ public class DirectoryFragment extends Fragment { final MenuItem share = menu.findItem(R.id.menu_share); final MenuItem share = menu.findItem(R.id.menu_share); final MenuItem delete = menu.findItem(R.id.menu_delete); final MenuItem delete = menu.findItem(R.id.menu_delete); final MenuItem copy = menu.findItem(R.id.menu_copy); final MenuItem copy = menu.findItem(R.id.menu_copy); final MenuItem move = menu.findItem(R.id.menu_move); final boolean manageOrBrowse = (state.action == ACTION_MANAGE final boolean manageOrBrowse = (state.action == ACTION_MANAGE || state.action == ACTION_BROWSE || state.action == ACTION_BROWSE_ALL); || state.action == ACTION_BROWSE || state.action == ACTION_BROWSE_ALL); Loading @@ -511,7 +513,7 @@ public class DirectoryFragment extends Fragment { delete.setVisible(manageOrBrowse); delete.setVisible(manageOrBrowse); // Disable copying from the Recents view. // Disable copying from the Recents view. copy.setVisible(manageOrBrowse && mType != TYPE_RECENT_OPEN); copy.setVisible(manageOrBrowse && mType != TYPE_RECENT_OPEN); move.setVisible(SystemProperties.getBoolean("debug.documentsui.enable_move", false)); return true; return true; } } Loading @@ -536,7 +538,12 @@ public class DirectoryFragment extends Fragment { return true; return true; } else if (id == R.id.menu_copy) { } else if (id == R.id.menu_copy) { onCopyDocuments(docs); onTransferDocuments(docs, CopyService.TRANSFER_MODE_COPY); mode.finish(); return true; } else if (id == R.id.menu_move) { onTransferDocuments(docs, CopyService.TRANSFER_MODE_MOVE); mode.finish(); mode.finish(); return true; return true; Loading Loading @@ -665,7 +672,7 @@ public class DirectoryFragment extends Fragment { } } } } private void onCopyDocuments(List<DocumentInfo> docs) { private void onTransferDocuments(List<DocumentInfo> docs, int mode) { getDisplayState(this).selectedDocumentsForCopy = docs; getDisplayState(this).selectedDocumentsForCopy = docs; // Pop up a dialog to pick a destination. This is inadequate but works for now. // Pop up a dialog to pick a destination. This is inadequate but works for now. Loading @@ -683,6 +690,7 @@ public class DirectoryFragment extends Fragment { } } } } intent.putExtra(BaseActivity.DocumentsIntent.EXTRA_DIRECTORY_COPY, directoryCopy); intent.putExtra(BaseActivity.DocumentsIntent.EXTRA_DIRECTORY_COPY, directoryCopy); intent.putExtra(CopyService.EXTRA_TRANSFER_MODE, mode); startActivityForResult(intent, REQUEST_COPY_DESTINATION); startActivityForResult(intent, REQUEST_COPY_DESTINATION); } } Loading Loading @@ -1241,7 +1249,7 @@ public class DirectoryFragment extends Fragment { tmpStack = curStack; tmpStack = curStack; } } CopyService.start(getActivity(), srcDocs, tmpStack); CopyService.start(getActivity(), srcDocs, tmpStack, CopyService.TRANSFER_MODE_COPY); } } private List<DocumentInfo> getDocumentsFromClipData(ClipData clipData) { private List<DocumentInfo> getDocumentsFromClipData(ClipData clipData) { Loading Loading
packages/DocumentsUI/res/menu/mode_directory.xml +4 −0 Original line number Original line Diff line number Diff line Loading @@ -37,4 +37,8 @@ android:id="@+id/menu_copy" android:id="@+id/menu_copy" android:title="@string/menu_copy" android:title="@string/menu_copy" android:showAsAction="never" /> android:showAsAction="never" /> <item android:id="@+id/menu_move" android:title="@string/menu_move" android:showAsAction="never" /> </menu> </menu>
packages/DocumentsUI/res/values/strings.xml +6 −0 Original line number Original line Diff line number Diff line Loading @@ -50,6 +50,8 @@ <string name="menu_select_all">Select All</string> <string name="menu_select_all">Select All</string> <!-- Menu item title that copies the selected documents [CHAR LIMIT=24] --> <!-- Menu item title that copies the selected documents [CHAR LIMIT=24] --> <string name="menu_copy">Copy to\u2026</string> <string name="menu_copy">Copy to\u2026</string> <!-- Menu item title that moves the selected documents [CHAR LIMIT=24] --> <string name="menu_move">Move to\u2026</string> <!-- Menu item that reveals internal storage built into the device [CHAR LIMIT=24] --> <!-- Menu item that reveals internal storage built into the device [CHAR LIMIT=24] --> <string name="menu_advanced_show" product="nosdcard">Show internal storage</string> <string name="menu_advanced_show" product="nosdcard">Show internal storage</string> Loading Loading @@ -124,6 +126,10 @@ <item quantity="one">Copying <xliff:g id="count" example="1">%1$d</xliff:g> file.</item> <item quantity="one">Copying <xliff:g id="count" example="1">%1$d</xliff:g> file.</item> <item quantity="other">Copying <xliff:g id="count" example="3">%1$d</xliff:g> files.</item> <item quantity="other">Copying <xliff:g id="count" example="3">%1$d</xliff:g> files.</item> </plurals> </plurals> <plurals name="move_begin"> <item quantity="one">Moving <xliff:g id="count" example="1">%1$d</xliff:g> file.</item> <item quantity="other">Moving <xliff:g id="count" example="3">%1$d</xliff:g> files.</item> </plurals> <!-- Text shown on the copy notification while DocumentsUI performs setup in preparation for copying files [CHAR LIMIT=32] --> <!-- Text shown on the copy notification while DocumentsUI performs setup in preparation for copying files [CHAR LIMIT=32] --> <string name="copy_preparing">Preparing for copy\u2026</string> <string name="copy_preparing">Preparing for copy\u2026</string> <!-- Title of the copy error notification [CHAR LIMIT=48] --> <!-- Title of the copy error notification [CHAR LIMIT=48] --> Loading
packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java +10 −8 Original line number Original line Diff line number Diff line Loading @@ -269,14 +269,16 @@ abstract class BaseActivity extends Activity { /** Derived after loader */ /** Derived after loader */ public int derivedSortOrder = SORT_ORDER_DISPLAY_NAME; public int derivedSortOrder = SORT_ORDER_DISPLAY_NAME; public boolean allowMultiple = false; public boolean allowMultiple; public boolean showSize = false; public boolean showSize; public boolean localOnly = false; public boolean localOnly ; public boolean forceAdvanced = false; public boolean forceAdvanced ; public boolean showAdvanced = false; public boolean showAdvanced ; public boolean stackTouched = false; public boolean stackTouched ; public boolean restored = false; public boolean restored ; public boolean directoryCopy = false; public boolean directoryCopy ; /** Transfer mode for file copy/move operations. */ public int transferMode; /** Current user navigation stack; empty implies recents. */ /** Current user navigation stack; empty implies recents. */ public DocumentStack stack = new DocumentStack(); public DocumentStack stack = new DocumentStack(); Loading
packages/DocumentsUI/src/com/android/documentsui/CopyService.java +45 −14 Original line number Original line Diff line number Diff line Loading @@ -61,6 +61,11 @@ public class CopyService extends IntentService { public static final String EXTRA_SRC_LIST = "com.android.documentsui.SRC_LIST"; public static final String EXTRA_SRC_LIST = "com.android.documentsui.SRC_LIST"; public static final String EXTRA_STACK = "com.android.documentsui.STACK"; public static final String EXTRA_STACK = "com.android.documentsui.STACK"; public static final String EXTRA_FAILURE = "com.android.documentsui.FAILURE"; public static final String EXTRA_FAILURE = "com.android.documentsui.FAILURE"; public static final String EXTRA_TRANSFER_MODE = "com.android.documentsui.TRANSFER_MODE"; public static final int TRANSFER_MODE_NONE = 0; public static final int TRANSFER_MODE_COPY = 1; public static final int TRANSFER_MODE_MOVE = 2; // TODO: Move it to a shared file when more operations are implemented. // TODO: Move it to a shared file when more operations are implemented. public static final int FAILURE_COPY = 1; public static final int FAILURE_COPY = 1; Loading Loading @@ -101,15 +106,19 @@ public class CopyService extends IntentService { * @param srcDocs A list of src files to copy. * @param srcDocs A list of src files to copy. * @param dstStack The copy destination stack. * @param dstStack The copy destination stack. */ */ public static void start(Context context, List<DocumentInfo> srcDocs, DocumentStack dstStack) { public static void start(Context context, List<DocumentInfo> srcDocs, DocumentStack dstStack, int mode) { final Resources res = context.getResources(); final Resources res = context.getResources(); final Intent copyIntent = new Intent(context, CopyService.class); final Intent copyIntent = new Intent(context, CopyService.class); copyIntent.putParcelableArrayListExtra( copyIntent.putParcelableArrayListExtra( EXTRA_SRC_LIST, new ArrayList<DocumentInfo>(srcDocs)); EXTRA_SRC_LIST, new ArrayList<DocumentInfo>(srcDocs)); copyIntent.putExtra(EXTRA_STACK, (Parcelable) dstStack); copyIntent.putExtra(EXTRA_STACK, (Parcelable) dstStack); copyIntent.putExtra(EXTRA_TRANSFER_MODE, mode); int toastMessage = (mode == TRANSFER_MODE_COPY) ? R.plurals.copy_begin : R.plurals.move_begin; Toast.makeText(context, Toast.makeText(context, res.getQuantityString(R.plurals.copy_begin, srcDocs.size(), srcDocs.size()), res.getQuantityString(toastMessage, srcDocs.size(), srcDocs.size()), Toast.LENGTH_SHORT).show(); Toast.LENGTH_SHORT).show(); context.startService(copyIntent); context.startService(copyIntent); } } Loading @@ -131,6 +140,8 @@ public class CopyService extends IntentService { final ArrayList<DocumentInfo> srcs = intent.getParcelableArrayListExtra(EXTRA_SRC_LIST); final ArrayList<DocumentInfo> srcs = intent.getParcelableArrayListExtra(EXTRA_SRC_LIST); final DocumentStack stack = intent.getParcelableExtra(EXTRA_STACK); final DocumentStack stack = intent.getParcelableExtra(EXTRA_STACK); // Copy by default. final int transferMode = intent.getIntExtra(EXTRA_TRANSFER_MODE, TRANSFER_MODE_COPY); try { try { // Acquire content providers. // Acquire content providers. Loading @@ -142,7 +153,7 @@ public class CopyService extends IntentService { setupCopyJob(srcs, stack); setupCopyJob(srcs, stack); for (int i = 0; i < srcs.size() && !mIsCancelled; ++i) { for (int i = 0; i < srcs.size() && !mIsCancelled; ++i) { copy(srcs.get(i), stack.peek()); copy(srcs.get(i), stack.peek(), transferMode); } } } catch (Exception e) { } catch (Exception e) { // Catch-all to prevent any copy errors from wedging the app. // Catch-all to prevent any copy errors from wedging the app. Loading Loading @@ -173,8 +184,6 @@ public class CopyService extends IntentService { .setAutoCancel(true); .setAutoCancel(true); mNotificationManager.notify(mJobId, 0, errorBuilder.build()); mNotificationManager.notify(mJobId, 0, errorBuilder.build()); } } // TODO: Display a toast if the copy was cancelled. } } } } Loading Loading @@ -377,7 +386,8 @@ public class CopyService extends IntentService { * @param dstDirInfo The destination directory. * @param dstDirInfo The destination directory. * @throws RemoteException * @throws RemoteException */ */ private void copy(DocumentInfo srcInfo, DocumentInfo dstDirInfo) throws RemoteException { private void copy(DocumentInfo srcInfo, DocumentInfo dstDirInfo, int mode) throws RemoteException { final Uri dstUri = DocumentsContract.createDocument(mDstClient, dstDirInfo.derivedUri, final Uri dstUri = DocumentsContract.createDocument(mDstClient, dstDirInfo.derivedUri, srcInfo.mimeType, srcInfo.displayName); srcInfo.mimeType, srcInfo.displayName); if (dstUri == null) { if (dstUri == null) { Loading @@ -388,9 +398,9 @@ public class CopyService extends IntentService { } } if (Document.MIME_TYPE_DIR.equals(srcInfo.mimeType)) { if (Document.MIME_TYPE_DIR.equals(srcInfo.mimeType)) { copyDirectoryHelper(srcInfo.derivedUri, dstUri); copyDirectoryHelper(srcInfo.derivedUri, dstUri, mode); } else { } else { copyFileHelper(srcInfo.derivedUri, dstUri); copyFileHelper(srcInfo.derivedUri, dstUri, mode); } } } } Loading @@ -403,7 +413,8 @@ public class CopyService extends IntentService { * @param dstDirUri URI of the directory to copy to. Must be created beforehand. * @param dstDirUri URI of the directory to copy to. Must be created beforehand. * @throws RemoteException * @throws RemoteException */ */ private void copyDirectoryHelper(Uri srcDirUri, Uri dstDirUri) throws RemoteException { private void copyDirectoryHelper(Uri srcDirUri, Uri dstDirUri, int mode) throws RemoteException { // Recurse into directories. Copy children into the new subdirectory. // Recurse into directories. Copy children into the new subdirectory. final String queryColumns[] = new String[] { final String queryColumns[] = new String[] { Document.COLUMN_DISPLAY_NAME, Document.COLUMN_DISPLAY_NAME, Loading @@ -424,9 +435,20 @@ public class CopyService extends IntentService { final Uri childUri = DocumentsContract.buildDocumentUri(srcDirUri.getAuthority(), final Uri childUri = DocumentsContract.buildDocumentUri(srcDirUri.getAuthority(), getCursorString(cursor, Document.COLUMN_DOCUMENT_ID)); getCursorString(cursor, Document.COLUMN_DOCUMENT_ID)); if (Document.MIME_TYPE_DIR.equals(childMimeType)) { if (Document.MIME_TYPE_DIR.equals(childMimeType)) { copyDirectoryHelper(childUri, dstUri); copyDirectoryHelper(childUri, dstUri, mode); } else { } else { copyFileHelper(childUri, dstUri); copyFileHelper(childUri, dstUri, mode); } } if (mode == TRANSFER_MODE_MOVE) { try { DocumentsContract.deleteDocument(mSrcClient, srcDirUri); } catch (RemoteException e) { // RemoteExceptions usually signal that the connection is dead, so there's no // point attempting to continue. Propagate the exception up so the copy job is // cancelled. Log.w(TAG, "Failed to clean up after move: " + srcDirUri, e); throw e; } } } } } finally { } finally { Loading @@ -441,7 +463,8 @@ public class CopyService extends IntentService { * @param dstUri URI of the *file* to copy to. Must be created beforehand. * @param dstUri URI of the *file* to copy to. Must be created beforehand. * @throws RemoteException * @throws RemoteException */ */ private void copyFileHelper(Uri srcUri, Uri dstUri) throws RemoteException { private void copyFileHelper(Uri srcUri, Uri dstUri, int mode) throws RemoteException { // Copy an individual file. // Copy an individual file. CancellationSignal canceller = new CancellationSignal(); CancellationSignal canceller = new CancellationSignal(); ParcelFileDescriptor srcFile = null; ParcelFileDescriptor srcFile = null; Loading Loading @@ -494,11 +517,19 @@ public class CopyService extends IntentService { try { try { DocumentsContract.deleteDocument(mDstClient, dstUri); DocumentsContract.deleteDocument(mDstClient, dstUri); } catch (RemoteException e) { } catch (RemoteException e) { Log.w(TAG, "Failed to clean up: " + srcUri, e); Log.w(TAG, "Failed to clean up after copy error: " + dstUri, e); // RemoteExceptions usually signal that the connection is dead, so there's no point // RemoteExceptions usually signal that the connection is dead, so there's no point // attempting to continue. Propagate the exception up so the copy job is cancelled. // attempting to continue. Propagate the exception up so the copy job is cancelled. throw e; throw e; } } } else if (mode == TRANSFER_MODE_MOVE) { // Clean up src files after a successful move. try { DocumentsContract.deleteDocument(mSrcClient, srcUri); } catch (RemoteException e) { Log.w(TAG, "Failed to clean up after move: " + srcUri, e); throw e; } } } } } } }
packages/DocumentsUI/src/com/android/documentsui/DirectoryFragment.java +13 −5 Original line number Original line Diff line number Diff line Loading @@ -369,7 +369,8 @@ public class DirectoryFragment extends Fragment { } } CopyService.start(getActivity(), getDisplayState(this).selectedDocumentsForCopy, CopyService.start(getActivity(), getDisplayState(this).selectedDocumentsForCopy, (DocumentStack) data.getParcelableExtra(CopyService.EXTRA_STACK)); (DocumentStack) data.getParcelableExtra(CopyService.EXTRA_STACK), data.getIntExtra(CopyService.EXTRA_TRANSFER_MODE, CopyService.TRANSFER_MODE_NONE)); } } @Override @Override Loading Loading @@ -502,6 +503,7 @@ public class DirectoryFragment extends Fragment { final MenuItem share = menu.findItem(R.id.menu_share); final MenuItem share = menu.findItem(R.id.menu_share); final MenuItem delete = menu.findItem(R.id.menu_delete); final MenuItem delete = menu.findItem(R.id.menu_delete); final MenuItem copy = menu.findItem(R.id.menu_copy); final MenuItem copy = menu.findItem(R.id.menu_copy); final MenuItem move = menu.findItem(R.id.menu_move); final boolean manageOrBrowse = (state.action == ACTION_MANAGE final boolean manageOrBrowse = (state.action == ACTION_MANAGE || state.action == ACTION_BROWSE || state.action == ACTION_BROWSE_ALL); || state.action == ACTION_BROWSE || state.action == ACTION_BROWSE_ALL); Loading @@ -511,7 +513,7 @@ public class DirectoryFragment extends Fragment { delete.setVisible(manageOrBrowse); delete.setVisible(manageOrBrowse); // Disable copying from the Recents view. // Disable copying from the Recents view. copy.setVisible(manageOrBrowse && mType != TYPE_RECENT_OPEN); copy.setVisible(manageOrBrowse && mType != TYPE_RECENT_OPEN); move.setVisible(SystemProperties.getBoolean("debug.documentsui.enable_move", false)); return true; return true; } } Loading @@ -536,7 +538,12 @@ public class DirectoryFragment extends Fragment { return true; return true; } else if (id == R.id.menu_copy) { } else if (id == R.id.menu_copy) { onCopyDocuments(docs); onTransferDocuments(docs, CopyService.TRANSFER_MODE_COPY); mode.finish(); return true; } else if (id == R.id.menu_move) { onTransferDocuments(docs, CopyService.TRANSFER_MODE_MOVE); mode.finish(); mode.finish(); return true; return true; Loading Loading @@ -665,7 +672,7 @@ public class DirectoryFragment extends Fragment { } } } } private void onCopyDocuments(List<DocumentInfo> docs) { private void onTransferDocuments(List<DocumentInfo> docs, int mode) { getDisplayState(this).selectedDocumentsForCopy = docs; getDisplayState(this).selectedDocumentsForCopy = docs; // Pop up a dialog to pick a destination. This is inadequate but works for now. // Pop up a dialog to pick a destination. This is inadequate but works for now. Loading @@ -683,6 +690,7 @@ public class DirectoryFragment extends Fragment { } } } } intent.putExtra(BaseActivity.DocumentsIntent.EXTRA_DIRECTORY_COPY, directoryCopy); intent.putExtra(BaseActivity.DocumentsIntent.EXTRA_DIRECTORY_COPY, directoryCopy); intent.putExtra(CopyService.EXTRA_TRANSFER_MODE, mode); startActivityForResult(intent, REQUEST_COPY_DESTINATION); startActivityForResult(intent, REQUEST_COPY_DESTINATION); } } Loading Loading @@ -1241,7 +1249,7 @@ public class DirectoryFragment extends Fragment { tmpStack = curStack; tmpStack = curStack; } } CopyService.start(getActivity(), srcDocs, tmpStack); CopyService.start(getActivity(), srcDocs, tmpStack, CopyService.TRANSFER_MODE_COPY); } } private List<DocumentInfo> getDocumentsFromClipData(ClipData clipData) { private List<DocumentInfo> getDocumentsFromClipData(ClipData clipData) { Loading