diff options
author | Jeff Sharkey <jsharkey@android.com> | 2013-08-15 16:17:41 -0700 |
---|---|---|
committer | Jeff Sharkey <jsharkey@android.com> | 2013-08-15 16:25:30 -0700 |
commit | a5599ef636e37cb0b6474349936999be1afe6987 (patch) | |
tree | ab99c3f837201713f7cd2c0b80a842334934e2d4 /packages/DocumentsUI/src/com/android/documentsui | |
parent | 54ca29a5b94c2edf461c5433825d4ae17469fd7c (diff) | |
download | frameworks_base-a5599ef636e37cb0b6474349936999be1afe6987.zip frameworks_base-a5599ef636e37cb0b6474349936999be1afe6987.tar.gz frameworks_base-a5599ef636e37cb0b6474349936999be1afe6987.tar.bz2 |
Documents management mode; API adjustment.
Create documents manage mode to support Downloads and transient
storage devices. Locks user into requested backend root, and forces
file sizes on and sorting by last modified.
Separate API constants for Documents versus Roots, and give concrete
MIME types for roots.
Treat null sizes as unknown. Documents are always enabled in list
so that divider is drawn. Mark external storage file as writable.
Bug: 10329983, 10332993, 10332952
Change-Id: I05f4fdf5b04041a38e1ba7fb30202a3b0c615bf6
Diffstat (limited to 'packages/DocumentsUI/src/com/android/documentsui')
8 files changed, 106 insertions, 56 deletions
diff --git a/packages/DocumentsUI/src/com/android/documentsui/CreateDirectoryFragment.java b/packages/DocumentsUI/src/com/android/documentsui/CreateDirectoryFragment.java index 313774b..575947f 100644 --- a/packages/DocumentsUI/src/com/android/documentsui/CreateDirectoryFragment.java +++ b/packages/DocumentsUI/src/com/android/documentsui/CreateDirectoryFragment.java @@ -27,8 +27,8 @@ import android.content.DialogInterface; import android.content.DialogInterface.OnClickListener; import android.net.Uri; import android.os.Bundle; -import android.provider.DocumentsContract; import android.provider.DocumentsContract.DocumentColumns; +import android.provider.DocumentsContract.Documents; import android.view.LayoutInflater; import android.view.View; import android.widget.EditText; @@ -69,7 +69,7 @@ public class CreateDirectoryFragment extends DialogFragment { final String displayName = text1.getText().toString(); final ContentValues values = new ContentValues(); - values.put(DocumentColumns.MIME_TYPE, DocumentsContract.MIME_TYPE_DIRECTORY); + values.put(DocumentColumns.MIME_TYPE, Documents.MIME_TYPE_DIR); values.put(DocumentColumns.DISPLAY_NAME, displayName); final DocumentsActivity activity = (DocumentsActivity) getActivity(); diff --git a/packages/DocumentsUI/src/com/android/documentsui/DirectoryFragment.java b/packages/DocumentsUI/src/com/android/documentsui/DirectoryFragment.java index e1b6a91..ac5629e 100644 --- a/packages/DocumentsUI/src/com/android/documentsui/DirectoryFragment.java +++ b/packages/DocumentsUI/src/com/android/documentsui/DirectoryFragment.java @@ -190,10 +190,6 @@ public class DirectoryFragment extends Fragment { @Override public void onStart() { super.onStart(); - - final Context context = getActivity(); - getDisplayState(this).showSize = SettingsActivity.getDisplayFileSize(context); - getLoaderManager().restartLoader(mLoaderId, getArguments(), mCallbacks); } @@ -244,7 +240,9 @@ public class DirectoryFragment extends Fragment { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { final Document doc = mAdapter.getItem(position); - ((DocumentsActivity) getActivity()).onDocumentPicked(doc); + if (mFilter.apply(doc)) { + ((DocumentsActivity) getActivity()).onDocumentPicked(doc); + } } }; @@ -389,7 +387,7 @@ public class DirectoryFragment extends Fragment { if (state.showSize) { size.setVisibility(View.VISIBLE); - if (doc.isDirectory()) { + if (doc.isDirectory() || doc.size == -1) { size.setText(null); } else { size.setText(Formatter.formatFileSize(context, doc.size)); @@ -415,16 +413,5 @@ public class DirectoryFragment extends Fragment { public long getItemId(int position) { return getItem(position).uri.hashCode(); } - - @Override - public boolean areAllItemsEnabled() { - return false; - } - - @Override - public boolean isEnabled(int position) { - final Document doc = getItem(position); - return mFilter.apply(doc); - } } } diff --git a/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java b/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java index 89ba66e..11ccc89 100644 --- a/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java +++ b/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java @@ -31,6 +31,7 @@ import android.database.Cursor; import android.graphics.drawable.ColorDrawable; import android.net.Uri; import android.os.Bundle; +import android.provider.DocumentsContract; import android.provider.DocumentsContract.DocumentColumns; import android.support.v4.app.ActionBarDrawerToggle; import android.support.v4.view.GravityCompat; @@ -63,6 +64,7 @@ public class DocumentsActivity extends Activity { public static final int ACTION_OPEN = 1; public static final int ACTION_CREATE = 2; public static final int ACTION_GET_CONTENT = 3; + public static final int ACTION_MANAGE = 4; private int mAction; @@ -91,6 +93,8 @@ public class DocumentsActivity extends Activity { mAction = ACTION_CREATE; } else if (Intent.ACTION_GET_CONTENT.equals(action)) { mAction = ACTION_GET_CONTENT; + } else if (Intent.ACTION_MANAGE_DOCUMENT.equals(action)) { + mAction = ACTION_MANAGE; } if (mAction == ACTION_OPEN || mAction == ACTION_GET_CONTENT) { @@ -98,7 +102,9 @@ public class DocumentsActivity extends Activity { Intent.EXTRA_ALLOW_MULTIPLE, false); } - if (intent.hasExtra(Intent.EXTRA_MIME_TYPES)) { + if (mAction == ACTION_MANAGE) { + mDisplayState.acceptMimes = new String[] { "*/*" }; + } else if (intent.hasExtra(Intent.EXTRA_MIME_TYPES)) { mDisplayState.acceptMimes = intent.getStringArrayExtra(Intent.EXTRA_MIME_TYPES); } else { mDisplayState.acceptMimes = new String[] { intent.getType() }; @@ -120,10 +126,14 @@ public class DocumentsActivity extends Activity { moreApps.setComponent(null); moreApps.setPackage(null); RootsFragment.show(getFragmentManager(), moreApps); - } else { + } else if (mAction == ACTION_OPEN || mAction == ACTION_CREATE) { RootsFragment.show(getFragmentManager(), null); } + if (mAction == ACTION_MANAGE) { + mDisplayState.sortOrder = DisplayState.SORT_ORDER_DATE; + } + mRootsContainer = findViewById(R.id.container_roots); mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout); @@ -134,26 +144,54 @@ public class DocumentsActivity extends Activity { mDrawerLayout.setDrawerListener(mDrawerListener); mDrawerLayout.setDrawerShadow(R.drawable.drawer_shadow, GravityCompat.START); - mDrawerLayout.openDrawer(mRootsContainer); + if (mAction == ACTION_MANAGE) { + mDrawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED); - // Restore last stack for calling package - // TODO: move into async loader - final String packageName = getCallingPackage(); - final Cursor cursor = getContentResolver() - .query(RecentsProvider.buildResume(packageName), null, null, null, null); - try { - if (cursor.moveToFirst()) { - final String raw = cursor.getString( - cursor.getColumnIndex(RecentsProvider.COL_PATH)); - mStack = DocumentStack.deserialize(getContentResolver(), raw); + final Uri rootUri = intent.getData(); + final String authority = rootUri.getAuthority(); + final String rootId = DocumentsContract.getRootId(rootUri); + + final Root root = RootsCache.findRoot(this, authority, rootId); + if (root != null) { + onRootPicked(root, true); + } else { + Log.w(TAG, "Failed to find root: " + rootUri); + finish(); + } + + } else { + mDrawerLayout.openDrawer(mRootsContainer); + + // Restore last stack for calling package + // TODO: move into async loader + final String packageName = getCallingPackage(); + final Cursor cursor = getContentResolver() + .query(RecentsProvider.buildResume(packageName), null, null, null, null); + try { + if (cursor.moveToFirst()) { + final String raw = cursor.getString( + cursor.getColumnIndex(RecentsProvider.COL_PATH)); + mStack = DocumentStack.deserialize(getContentResolver(), raw); + } + } catch (FileNotFoundException e) { + Log.w(TAG, "Failed to resume", e); + } finally { + cursor.close(); } - } catch (FileNotFoundException e) { - Log.w(TAG, "Failed to resume", e); - } finally { - cursor.close(); + + onCurrentDirectoryChanged(); } + } - onCurrentDirectoryChanged(); + @Override + public void onStart() { + super.onStart(); + + if (mAction == ACTION_MANAGE) { + mDisplayState.showSize = true; + } else { + mDisplayState.showSize = SettingsActivity.getDisplayFileSize(this); + } } private DrawerListener mDrawerListener = new DrawerListener() { @@ -190,7 +228,6 @@ public class DocumentsActivity extends Activity { final ActionBar actionBar = getActionBar(); actionBar.setDisplayShowHomeEnabled(true); - actionBar.setDisplayHomeAsUpEnabled(true); if (mDrawerLayout.isDrawerOpen(mRootsContainer)) { actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_STANDARD); @@ -202,6 +239,9 @@ public class DocumentsActivity extends Activity { actionBar.setTitle(R.string.title_save); } + actionBar.setDisplayHomeAsUpEnabled(true); + mDrawerToggle.setDrawerIndicatorEnabled(true); + } else { final Root root = getCurrentRoot(); actionBar.setIcon(root != null ? root.icon : null); @@ -217,8 +257,13 @@ public class DocumentsActivity extends Activity { } if (mStack.size() > 1) { + actionBar.setDisplayHomeAsUpEnabled(true); + mDrawerToggle.setDrawerIndicatorEnabled(false); + } else if (mAction == ACTION_MANAGE) { + actionBar.setDisplayHomeAsUpEnabled(false); mDrawerToggle.setDrawerIndicatorEnabled(false); } else { + actionBar.setDisplayHomeAsUpEnabled(true); mDrawerToggle.setDrawerIndicatorEnabled(true); } } @@ -269,6 +314,7 @@ public class DocumentsActivity extends Activity { final MenuItem search = menu.findItem(R.id.menu_search); final MenuItem grid = menu.findItem(R.id.menu_grid); final MenuItem list = menu.findItem(R.id.menu_list); + final MenuItem settings = menu.findItem(R.id.menu_settings); grid.setVisible(mDisplayState.mode != DisplayState.MODE_GRID); list.setVisible(mDisplayState.mode != DisplayState.MODE_LIST); @@ -293,6 +339,8 @@ public class DocumentsActivity extends Activity { // TODO: close any search in-progress when hiding search.setVisible(searchVisible); + settings.setVisible(mAction != ACTION_MANAGE); + return true; } diff --git a/packages/DocumentsUI/src/com/android/documentsui/MimePredicate.java b/packages/DocumentsUI/src/com/android/documentsui/MimePredicate.java index f945c6a0..a9929de 100644 --- a/packages/DocumentsUI/src/com/android/documentsui/MimePredicate.java +++ b/packages/DocumentsUI/src/com/android/documentsui/MimePredicate.java @@ -49,7 +49,9 @@ public class MimePredicate implements Predicate<Document> { } public static boolean mimeMatches(String filter, String test) { - if (filter.equals(test)) { + if (test == null) { + return false; + } else if (filter.equals(test)) { return true; } else if ("*/*".equals(filter)) { return true; diff --git a/packages/DocumentsUI/src/com/android/documentsui/RootsCache.java b/packages/DocumentsUI/src/com/android/documentsui/RootsCache.java index ceab8fc..acd9396 100644 --- a/packages/DocumentsUI/src/com/android/documentsui/RootsCache.java +++ b/packages/DocumentsUI/src/com/android/documentsui/RootsCache.java @@ -27,6 +27,7 @@ import android.database.Cursor; import android.graphics.drawable.Drawable; import android.net.Uri; import android.provider.DocumentsContract; +import android.provider.DocumentsContract.Documents; import android.util.Log; import android.util.Pair; @@ -162,7 +163,7 @@ public class RootsCache { } } - if (DocumentsContract.MIME_TYPE_DIRECTORY.equals(mimeType)) { + if (Documents.MIME_TYPE_DIR.equals(mimeType)) { return context.getResources().getDrawable(R.drawable.ic_dir); } else { final PackageManager pm = context.getPackageManager(); diff --git a/packages/DocumentsUI/src/com/android/documentsui/RootsFragment.java b/packages/DocumentsUI/src/com/android/documentsui/RootsFragment.java index e32414b..4973e1d 100644 --- a/packages/DocumentsUI/src/com/android/documentsui/RootsFragment.java +++ b/packages/DocumentsUI/src/com/android/documentsui/RootsFragment.java @@ -26,7 +26,7 @@ import android.content.Intent; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import android.os.Bundle; -import android.provider.DocumentsContract; +import android.provider.DocumentsContract.Roots; import android.text.format.Formatter; import android.util.Log; import android.view.LayoutInflater; @@ -44,7 +44,6 @@ import com.android.documentsui.model.Root; import com.android.documentsui.model.Root.RootComparator; import java.util.Collection; -import java.util.Iterator; import java.util.List; /** @@ -138,8 +137,8 @@ public class RootsFragment extends Fragment { // Device summary is always available space final String summaryText; - if ((root.rootType == DocumentsContract.ROOT_TYPE_DEVICE - || root.rootType == DocumentsContract.ROOT_TYPE_DEVICE_ADVANCED) + if ((root.rootType == Roots.ROOT_TYPE_DEVICE + || root.rootType == Roots.ROOT_TYPE_DEVICE_ADVANCED) && root.availableBytes >= 0) { summaryText = context.getString(R.string.root_available_bytes, Formatter.formatFileSize(context, root.availableBytes)); @@ -226,17 +225,17 @@ public class RootsFragment extends Fragment { for (Root root : roots) { Log.d(TAG, "Found rootType=" + root.rootType); switch (root.rootType) { - case DocumentsContract.ROOT_TYPE_SERVICE: + case Roots.ROOT_TYPE_SERVICE: mServices.add(root); break; - case DocumentsContract.ROOT_TYPE_SHORTCUT: + case Roots.ROOT_TYPE_SHORTCUT: mShortcuts.add(root); break; - case DocumentsContract.ROOT_TYPE_DEVICE: + case Roots.ROOT_TYPE_DEVICE: mDevices.add(root); mDevicesAdvanced.add(root); break; - case DocumentsContract.ROOT_TYPE_DEVICE_ADVANCED: + case Roots.ROOT_TYPE_DEVICE_ADVANCED: mDevicesAdvanced.add(root); break; } diff --git a/packages/DocumentsUI/src/com/android/documentsui/model/Document.java b/packages/DocumentsUI/src/com/android/documentsui/model/Document.java index 95922b4..cf45394 100644 --- a/packages/DocumentsUI/src/com/android/documentsui/model/Document.java +++ b/packages/DocumentsUI/src/com/android/documentsui/model/Document.java @@ -21,6 +21,7 @@ import android.database.Cursor; import android.net.Uri; import android.provider.DocumentsContract; import android.provider.DocumentsContract.DocumentColumns; +import android.provider.DocumentsContract.Documents; import com.android.documentsui.RecentsProvider; @@ -87,7 +88,7 @@ public class Document { final String mimeType = getCursorString(cursor, DocumentColumns.MIME_TYPE); final String displayName = getCursorString(cursor, DocumentColumns.DISPLAY_NAME); final int flags = getCursorInt(cursor, DocumentColumns.FLAGS) - & DocumentsContract.FLAG_SUPPORTS_THUMBNAIL; + & Documents.FLAG_SUPPORTS_THUMBNAIL; final String summary = getCursorString(cursor, DocumentColumns.SUMMARY); final long size = getCursorLong(cursor, DocumentColumns.SIZE); @@ -127,19 +128,19 @@ public class Document { } public boolean isCreateSupported() { - return (flags & DocumentsContract.FLAG_SUPPORTS_CREATE) != 0; + return (flags & Documents.FLAG_SUPPORTS_CREATE) != 0; } public boolean isSearchSupported() { - return (flags & DocumentsContract.FLAG_SUPPORTS_SEARCH) != 0; + return (flags & Documents.FLAG_SUPPORTS_SEARCH) != 0; } public boolean isThumbnailSupported() { - return (flags & DocumentsContract.FLAG_SUPPORTS_THUMBNAIL) != 0; + return (flags & Documents.FLAG_SUPPORTS_THUMBNAIL) != 0; } public boolean isDirectory() { - return DocumentsContract.MIME_TYPE_DIRECTORY.equals(mimeType); + return Documents.MIME_TYPE_DIR.equals(mimeType); } private static String getCursorString(Cursor cursor, String columnName) { @@ -147,9 +148,19 @@ public class Document { return (index != -1) ? cursor.getString(index) : null; } + /** + * Missing or null values are returned as -1. + */ private static long getCursorLong(Cursor cursor, String columnName) { final int index = cursor.getColumnIndex(columnName); - return (index != -1) ? cursor.getLong(index) : 0; + if (index == -1) return -1; + final String value = cursor.getString(index); + if (value == null) return -1; + try { + return Long.parseLong(value); + } catch (NumberFormatException e) { + return -1; + } } private static int getCursorInt(Cursor cursor, String columnName) { diff --git a/packages/DocumentsUI/src/com/android/documentsui/model/Root.java b/packages/DocumentsUI/src/com/android/documentsui/model/Root.java index 0880731..23d16df 100644 --- a/packages/DocumentsUI/src/com/android/documentsui/model/Root.java +++ b/packages/DocumentsUI/src/com/android/documentsui/model/Root.java @@ -24,7 +24,9 @@ import android.database.Cursor; import android.graphics.drawable.Drawable; import android.net.Uri; import android.provider.DocumentsContract; +import android.provider.DocumentsContract.Documents; import android.provider.DocumentsContract.RootColumns; +import android.provider.DocumentsContract.Roots; import com.android.documentsui.R; @@ -47,7 +49,7 @@ public class Root { final PackageManager pm = context.getPackageManager(); final Root root = new Root(); root.rootId = null; - root.rootType = DocumentsContract.ROOT_TYPE_SHORTCUT; + root.rootType = Roots.ROOT_TYPE_SHORTCUT; root.uri = null; root.icon = context.getResources().getDrawable(R.drawable.ic_dir); root.title = context.getString(R.string.root_recent); @@ -65,7 +67,7 @@ public class Root { root.rootId = cursor.getString(cursor.getColumnIndex(RootColumns.ROOT_ID)); root.rootType = cursor.getInt(cursor.getColumnIndex(RootColumns.ROOT_TYPE)); root.uri = DocumentsContract.buildDocumentUri( - info.providerInfo.authority, root.rootId, DocumentsContract.ROOT_DOC_ID); + info.providerInfo.authority, root.rootId, Documents.DOC_ID_ROOT); root.icon = info.providerInfo.loadIcon(pm); root.title = info.providerInfo.loadLabel(pm).toString(); root.availableBytes = cursor.getLong(cursor.getColumnIndex(RootColumns.AVAILABLE_BYTES)); |