Loading api/current.txt +5 −0 Original line number Original line Diff line number Diff line Loading @@ -20270,12 +20270,17 @@ package android.provider { public final class DocumentsContract { public final class DocumentsContract { ctor public DocumentsContract(); ctor public DocumentsContract(); method public static android.net.Uri buildContentsUri(java.lang.String, java.lang.String, java.lang.String); method public static android.net.Uri buildContentsUri(android.net.Uri); method public static android.net.Uri buildContentsUri(android.net.Uri); method public static android.net.Uri buildDocumentUri(java.lang.String, java.lang.String, java.lang.String); method public static android.net.Uri buildDocumentUri(java.lang.String, java.lang.String, java.lang.String); method public static android.net.Uri buildDocumentUri(android.net.Uri, java.lang.String); method public static android.net.Uri buildDocumentUri(android.net.Uri, java.lang.String); method public static android.net.Uri buildRootUri(java.lang.String, java.lang.String); method public static android.net.Uri buildRootUri(java.lang.String, java.lang.String); method public static android.net.Uri buildRootsUri(java.lang.String); method public static android.net.Uri buildRootsUri(java.lang.String); method public static android.net.Uri buildSearchUri(java.lang.String, java.lang.String, java.lang.String, java.lang.String); method public static android.net.Uri buildSearchUri(android.net.Uri, java.lang.String); method public static android.net.Uri buildSearchUri(android.net.Uri, java.lang.String); method public static java.lang.String getDocId(android.net.Uri); method public static java.lang.String getRootId(android.net.Uri); method public static java.lang.String getSearchQuery(android.net.Uri); method public static android.graphics.Bitmap getThumbnail(android.content.ContentResolver, android.net.Uri, android.graphics.Point); method public static android.graphics.Bitmap getThumbnail(android.content.ContentResolver, android.net.Uri, android.graphics.Point); method public static boolean renameDocument(android.content.ContentResolver, android.net.Uri, java.lang.String); method public static boolean renameDocument(android.content.ContentResolver, android.net.Uri, java.lang.String); field public static final java.lang.String EXTRA_HAS_MORE = "has_more"; field public static final java.lang.String EXTRA_HAS_MORE = "has_more"; core/java/android/provider/DocumentsContract.java +52 −16 Original line number Original line Diff line number Diff line Loading @@ -34,6 +34,7 @@ import libcore.io.IoUtils; import java.io.IOException; import java.io.IOException; import java.io.InputStream; import java.io.InputStream; import java.util.List; /** /** * The contract between a storage backend and the platform. Contains definitions * The contract between a storage backend and the platform. Contains definitions Loading Loading @@ -152,36 +153,71 @@ public final class DocumentsContract { .authority(authority).appendPath(PATH_ROOTS).appendPath(rootId).build(); .authority(authority).appendPath(PATH_ROOTS).appendPath(rootId).build(); } } /** * Build URI representing the given {@link DocumentColumns#DOC_ID} in a * storage root. */ public static Uri buildDocumentUri(String authority, String rootId, String docId) { public static Uri buildDocumentUri(String authority, String rootId, String docId) { return buildDocumentUri(buildRootUri(authority, rootId), docId); return new Uri.Builder().scheme(ContentResolver.SCHEME_CONTENT).authority(authority) .appendPath(PATH_ROOTS).appendPath(rootId).appendPath(PATH_DOCS).appendPath(docId) .build(); } } /** /** * Build URI representing the given {@link DocumentColumns#DOC_ID} in a * Build URI representing the contents of the given directory in a storage * storage root. * backend. The given document must be {@link #MIME_TYPE_DIRECTORY}. */ */ public static Uri buildDocumentUri(Uri rootUri, String docId) { public static Uri buildContentsUri(String authority, String rootId, String docId) { return rootUri.buildUpon().appendPath(PATH_DOCS).appendPath(docId).build(); return new Uri.Builder().scheme(ContentResolver.SCHEME_CONTENT).authority(authority) .appendPath(PATH_ROOTS).appendPath(rootId).appendPath(PATH_DOCS).appendPath(docId) .appendPath(PATH_CONTENTS).build(); } } /** /** * Build URI representing a search for matching documents under a directory * Build URI representing a search for matching documents under a directory * in a storage backend. * in a storage backend. * * @param documentUri directory to search under, which must have * {@link #FLAG_SUPPORTS_SEARCH}. */ */ public static Uri buildSearchUri(Uri documentUri, String query) { public static Uri buildSearchUri(String authority, String rootId, String docId, String query) { return documentUri.buildUpon() return new Uri.Builder().scheme(ContentResolver.SCHEME_CONTENT).authority(authority) .appendPath(PATH_ROOTS).appendPath(rootId).appendPath(PATH_DOCS).appendPath(docId) .appendPath(PATH_SEARCH).appendQueryParameter(PARAM_QUERY, query).build(); .appendPath(PATH_SEARCH).appendQueryParameter(PARAM_QUERY, query).build(); } } /** public static Uri buildDocumentUri(Uri relatedUri, String docId) { * Build URI representing the contents of the given directory in a storage return buildDocumentUri(relatedUri.getAuthority(), getRootId(relatedUri), docId); * backend. The given document must be {@link #MIME_TYPE_DIRECTORY}. } */ public static Uri buildContentsUri(Uri documentUri) { public static Uri buildContentsUri(Uri relatedUri) { return documentUri.buildUpon().appendPath(PATH_CONTENTS).build(); return buildContentsUri( relatedUri.getAuthority(), getRootId(relatedUri), getDocId(relatedUri)); } public static Uri buildSearchUri(Uri relatedUri, String query) { return buildSearchUri( relatedUri.getAuthority(), getRootId(relatedUri), getDocId(relatedUri), query); } public static String getRootId(Uri documentUri) { final List<String> paths = documentUri.getPathSegments(); if (!PATH_ROOTS.equals(paths.get(0))) { throw new IllegalArgumentException(); } return paths.get(1); } public static String getDocId(Uri documentUri) { final List<String> paths = documentUri.getPathSegments(); if (!PATH_ROOTS.equals(paths.get(0))) { throw new IllegalArgumentException(); } if (!PATH_DOCS.equals(paths.get(2))) { throw new IllegalArgumentException(); } return paths.get(3); } public static String getSearchQuery(Uri documentUri) { return documentUri.getQueryParameter(PARAM_QUERY); } } /** /** Loading packages/DocumentsUI/src/com/android/documentsui/DirectoryFragment.java +32 −46 Original line number Original line Diff line number Diff line Loading @@ -67,31 +67,29 @@ public class DirectoryFragment extends Fragment { private AbsListView mCurrentView; private AbsListView mCurrentView; private static final int TYPE_NORMAL = 1; private static final int TYPE_SEARCH = 2; private static final int TYPE_RECENT_OPEN = 3; private static final int TYPE_RECENT_CREATE = 4; private int mType = TYPE_NORMAL; private DocumentsAdapter mAdapter; private DocumentsAdapter mAdapter; private LoaderCallbacks<Cursor> mCallbacks; private LoaderCallbacks<Cursor> mCallbacks; private int mFlags; private static final String EXTRA_URI = "uri"; private static final String EXTRA_ROOT_URI = "rootUri"; private static final String EXTRA_DOCS_URI = "docsUri"; private static final int LOADER_DOCUMENTS = 2; private static final int LOADER_DOCUMENTS = 2; public static void show(FragmentManager fm, Uri rootUri, Uri docsUri, String displayName, public static void show(FragmentManager fm, Uri uri) { boolean addToBackStack) { final Bundle args = new Bundle(); final Bundle args = new Bundle(); args.putParcelable(EXTRA_ROOT_URI, rootUri); args.putParcelable(EXTRA_URI, uri); args.putParcelable(EXTRA_DOCS_URI, docsUri); final DirectoryFragment fragment = new DirectoryFragment(); final DirectoryFragment fragment = new DirectoryFragment(); fragment.setArguments(args); fragment.setArguments(args); final FragmentTransaction ft = fm.beginTransaction(); final FragmentTransaction ft = fm.beginTransaction(); ft.replace(R.id.directory, fragment); ft.replace(R.id.directory, fragment); if (addToBackStack) { ft.addToBackStack(displayName); } ft.setBreadCrumbTitle(displayName); ft.commitAllowingStateLoss(); ft.commitAllowingStateLoss(); } } Loading Loading @@ -119,9 +117,17 @@ public class DirectoryFragment extends Fragment { mAdapter = new DocumentsAdapter(context); mAdapter = new DocumentsAdapter(context); updateMode(); updateMode(); // TODO: migrate flags query to loader final Uri uri = getArguments().getParcelable(EXTRA_URI); final Uri docsUri = getArguments().getParcelable(EXTRA_DOCS_URI); mFlags = getDocumentFlags(context, docsUri); if (uri.getQueryParameter(DocumentsContract.PARAM_QUERY) != null) { mType = TYPE_SEARCH; } else if (RecentsProvider.buildRecentOpen().equals(uri)) { mType = TYPE_RECENT_OPEN; } else if (RecentsProvider.buildRecentCreate().equals(uri)) { mType = TYPE_RECENT_CREATE; } else { mType = TYPE_NORMAL; } mCallbacks = new LoaderCallbacks<Cursor>() { mCallbacks = new LoaderCallbacks<Cursor>() { @Override @Override Loading @@ -137,10 +143,10 @@ public class DirectoryFragment extends Fragment { } } final Uri contentsUri; final Uri contentsUri; if (docsUri.getQueryParameter(DocumentsContract.PARAM_QUERY) != null) { if (mType == TYPE_NORMAL) { contentsUri = docsUri; contentsUri = DocumentsContract.buildContentsUri(uri); } else { } else { contentsUri = DocumentsContract.buildContentsUri(docsUri); contentsUri = uri; } } return new CursorLoader(context, contentsUri, null, null, null, sortOrder); return new CursorLoader(context, contentsUri, null, null, null, sortOrder); Loading @@ -164,10 +170,6 @@ public class DirectoryFragment extends Fragment { public void onStart() { public void onStart() { super.onStart(); super.onStart(); getLoaderManager().restartLoader(LOADER_DOCUMENTS, getArguments(), mCallbacks); getLoaderManager().restartLoader(LOADER_DOCUMENTS, getArguments(), mCallbacks); // TODO: clean up tracking of current directory final Uri docsUri = getArguments().getParcelable(EXTRA_DOCS_URI); ((DocumentsActivity) getActivity()).onDirectoryChanged(docsUri, mFlags); } } @Override @Override Loading Loading @@ -249,8 +251,8 @@ public class DirectoryFragment extends Fragment { @Override @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { public void onItemClick(AdapterView<?> parent, View view, int position, long id) { final Cursor cursor = (Cursor) mAdapter.getItem(position); final Cursor cursor = (Cursor) mAdapter.getItem(position); final Uri rootUri = getArguments().getParcelable(EXTRA_ROOT_URI); final Uri uri = getArguments().getParcelable(EXTRA_URI); final Document doc = Document.fromCursor(rootUri, cursor); final Document doc = Document.fromCursor(uri, cursor); ((DocumentsActivity) getActivity()).onDocumentPicked(doc); ((DocumentsActivity) getActivity()).onDocumentPicked(doc); } } }; }; Loading @@ -270,7 +272,7 @@ public class DirectoryFragment extends Fragment { @Override @Override public boolean onActionItemClicked(ActionMode mode, MenuItem item) { public boolean onActionItemClicked(ActionMode mode, MenuItem item) { if (item.getItemId() == R.id.menu_open) { if (item.getItemId() == R.id.menu_open) { final Uri rootUri = getArguments().getParcelable(EXTRA_ROOT_URI); final Uri uri = getArguments().getParcelable(EXTRA_URI); final SparseBooleanArray checked = mCurrentView.getCheckedItemPositions(); final SparseBooleanArray checked = mCurrentView.getCheckedItemPositions(); final ArrayList<Document> docs = Lists.newArrayList(); final ArrayList<Document> docs = Lists.newArrayList(); Loading @@ -278,7 +280,7 @@ public class DirectoryFragment extends Fragment { for (int i = 0; i < size; i++) { for (int i = 0; i < size; i++) { if (checked.valueAt(i)) { if (checked.valueAt(i)) { final Cursor cursor = (Cursor) mAdapter.getItem(checked.keyAt(i)); final Cursor cursor = (Cursor) mAdapter.getItem(checked.keyAt(i)); docs.add(Document.fromCursor(rootUri, cursor)); docs.add(Document.fromCursor(uri, cursor)); } } } } Loading Loading @@ -346,15 +348,13 @@ public class DirectoryFragment extends Fragment { final long lastModified = getCursorLong(cursor, DocumentColumns.LAST_MODIFIED); final long lastModified = getCursorLong(cursor, DocumentColumns.LAST_MODIFIED); final int flags = getCursorInt(cursor, DocumentColumns.FLAGS); final int flags = getCursorInt(cursor, DocumentColumns.FLAGS); final Uri rootUri = getArguments().getParcelable(EXTRA_ROOT_URI); final Uri uri = getArguments().getParcelable(EXTRA_URI); final String authority = rootUri.getAuthority(); if ((flags & DocumentsContract.FLAG_SUPPORTS_THUMBNAIL) != 0) { if ((flags & DocumentsContract.FLAG_SUPPORTS_THUMBNAIL) != 0) { final Uri childUri = DocumentsContract.buildDocumentUri(rootUri, docId); final Uri childUri = DocumentsContract.buildDocumentUri(uri, docId); icon.setImageURI(childUri); icon.setImageURI(childUri); } else { } else { icon.setImageDrawable( icon.setImageDrawable(DocumentsActivity.resolveDocumentIcon( DocumentsActivity.resolveDocumentIcon(context, authority, mimeType)); context, uri.getAuthority(), mimeType)); } } title.setText(displayName); title.setText(displayName); Loading @@ -364,20 +364,6 @@ public class DirectoryFragment extends Fragment { } } } } private static int getDocumentFlags(Context context, Uri uri) { final Cursor cursor = context.getContentResolver().query(uri, new String[] { DocumentColumns.FLAGS }, null, null, null); try { if (cursor.moveToFirst()) { return getCursorInt(cursor, DocumentColumns.FLAGS); } else { return 0; } } finally { cursor.close(); } } public static String getCursorString(Cursor cursor, String columnName) { public static String getCursorString(Cursor cursor, String columnName) { return cursor.getString(cursor.getColumnIndex(columnName)); return cursor.getString(cursor.getColumnIndex(columnName)); } } Loading packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java +205 −80 File changed.Preview size limit exceeded, changes collapsed. Show changes packages/DocumentsUI/src/com/android/documentsui/RecentsProvider.java +29 −6 Original line number Original line Diff line number Diff line Loading @@ -17,6 +17,7 @@ package com.android.documentsui; package com.android.documentsui; import android.content.ContentProvider; import android.content.ContentProvider; import android.content.ContentResolver; import android.content.ContentValues; import android.content.ContentValues; import android.content.Context; import android.content.Context; import android.content.UriMatcher; import android.content.UriMatcher; Loading @@ -30,6 +31,9 @@ import android.util.Log; public class RecentsProvider extends ContentProvider { public class RecentsProvider extends ContentProvider { private static final String TAG = "RecentsProvider"; private static final String TAG = "RecentsProvider"; // TODO: offer view of recents that handles backend root resolution before // returning cursor, include extra columns public static final String AUTHORITY = "com.android.documentsui.recents"; public static final String AUTHORITY = "com.android.documentsui.recents"; private static final UriMatcher sMatcher = new UriMatcher(UriMatcher.NO_MATCH); private static final UriMatcher sMatcher = new UriMatcher(UriMatcher.NO_MATCH); Loading @@ -53,13 +57,29 @@ public class RecentsProvider extends ContentProvider { * starting with root. * starting with root. */ */ public static final String COL_PATH = "path"; public static final String COL_PATH = "path"; public static final String COL_URI = "uri"; public static final String COL_PACKAGE_NAME = "package_name"; public static final String COL_PACKAGE_NAME = "package_name"; public static final String COL_TIMESTAMP = "timestamp"; public static final String COL_TIMESTAMP = "timestamp"; public static Uri buildRecentOpen() { return new Uri.Builder().scheme(ContentResolver.SCHEME_CONTENT) .authority(AUTHORITY).appendPath("recent_open").build(); } public static Uri buildRecentCreate() { return new Uri.Builder().scheme(ContentResolver.SCHEME_CONTENT) .authority(AUTHORITY).appendPath("recent_create").build(); } public static Uri buildResume(String packageName) { return new Uri.Builder().scheme(ContentResolver.SCHEME_CONTENT) .authority(AUTHORITY).appendPath("resume").appendPath(packageName).build(); } private DatabaseHelper mHelper; private DatabaseHelper mHelper; private static class DatabaseHelper extends SQLiteOpenHelper { private static class DatabaseHelper extends SQLiteOpenHelper { private static final String DB_NAME = "recents"; private static final String DB_NAME = "recents.db"; private static final int VERSION_INIT = 1; private static final int VERSION_INIT = 1; Loading @@ -70,19 +90,19 @@ public class RecentsProvider extends ContentProvider { @Override @Override public void onCreate(SQLiteDatabase db) { public void onCreate(SQLiteDatabase db) { db.execSQL("CREATE TABLE " + TABLE_RECENT_OPEN + " (" + db.execSQL("CREATE TABLE " + TABLE_RECENT_OPEN + " (" + COL_PATH + " TEXT," + COL_URI + " TEXT PRIMARY KEY ON CONFLICT REPLACE," + COL_TIMESTAMP + " INTEGER," + COL_TIMESTAMP + " INTEGER" + ")"); ")"); db.execSQL("CREATE TABLE " + TABLE_RECENT_CREATE + " (" + db.execSQL("CREATE TABLE " + TABLE_RECENT_CREATE + " (" + COL_PATH + " TEXT," + COL_PATH + " TEXT PRIMARY KEY ON CONFLICT REPLACE," + COL_TIMESTAMP + " INTEGER," + COL_TIMESTAMP + " INTEGER" + ")"); ")"); db.execSQL("CREATE TABLE " + TABLE_RESUME + " (" + db.execSQL("CREATE TABLE " + TABLE_RESUME + " (" + COL_PACKAGE_NAME + " TEXT PRIMARY KEY ON CONFLICT REPLACE," + COL_PACKAGE_NAME + " TEXT PRIMARY KEY ON CONFLICT REPLACE," + COL_PATH + " TEXT," + COL_PATH + " TEXT," + COL_TIMESTAMP + " INTEGER," + COL_TIMESTAMP + " INTEGER" + ")"); ")"); } } Loading Loading @@ -136,11 +156,13 @@ public class RecentsProvider extends ContentProvider { final SQLiteDatabase db = mHelper.getWritableDatabase(); final SQLiteDatabase db = mHelper.getWritableDatabase(); switch (sMatcher.match(uri)) { switch (sMatcher.match(uri)) { case URI_RECENT_OPEN: { case URI_RECENT_OPEN: { values.put(COL_TIMESTAMP, System.currentTimeMillis()); db.insert(TABLE_RECENT_OPEN, null, values); db.insert(TABLE_RECENT_OPEN, null, values); db.delete(TABLE_RECENT_OPEN, buildWhereOlder(DateUtils.WEEK_IN_MILLIS), null); db.delete(TABLE_RECENT_OPEN, buildWhereOlder(DateUtils.WEEK_IN_MILLIS), null); return uri; return uri; } } case URI_RECENT_CREATE: { case URI_RECENT_CREATE: { values.put(COL_TIMESTAMP, System.currentTimeMillis()); db.insert(TABLE_RECENT_CREATE, null, values); db.insert(TABLE_RECENT_CREATE, null, values); db.delete(TABLE_RECENT_CREATE, buildWhereOlder(DateUtils.WEEK_IN_MILLIS), null); db.delete(TABLE_RECENT_CREATE, buildWhereOlder(DateUtils.WEEK_IN_MILLIS), null); return uri; return uri; Loading @@ -148,6 +170,7 @@ public class RecentsProvider extends ContentProvider { case URI_RESUME: { case URI_RESUME: { final String packageName = uri.getPathSegments().get(1); final String packageName = uri.getPathSegments().get(1); values.put(COL_PACKAGE_NAME, packageName); values.put(COL_PACKAGE_NAME, packageName); values.put(COL_TIMESTAMP, System.currentTimeMillis()); db.insert(TABLE_RESUME, null, values); db.insert(TABLE_RESUME, null, values); return uri; return uri; } } Loading Loading
api/current.txt +5 −0 Original line number Original line Diff line number Diff line Loading @@ -20270,12 +20270,17 @@ package android.provider { public final class DocumentsContract { public final class DocumentsContract { ctor public DocumentsContract(); ctor public DocumentsContract(); method public static android.net.Uri buildContentsUri(java.lang.String, java.lang.String, java.lang.String); method public static android.net.Uri buildContentsUri(android.net.Uri); method public static android.net.Uri buildContentsUri(android.net.Uri); method public static android.net.Uri buildDocumentUri(java.lang.String, java.lang.String, java.lang.String); method public static android.net.Uri buildDocumentUri(java.lang.String, java.lang.String, java.lang.String); method public static android.net.Uri buildDocumentUri(android.net.Uri, java.lang.String); method public static android.net.Uri buildDocumentUri(android.net.Uri, java.lang.String); method public static android.net.Uri buildRootUri(java.lang.String, java.lang.String); method public static android.net.Uri buildRootUri(java.lang.String, java.lang.String); method public static android.net.Uri buildRootsUri(java.lang.String); method public static android.net.Uri buildRootsUri(java.lang.String); method public static android.net.Uri buildSearchUri(java.lang.String, java.lang.String, java.lang.String, java.lang.String); method public static android.net.Uri buildSearchUri(android.net.Uri, java.lang.String); method public static android.net.Uri buildSearchUri(android.net.Uri, java.lang.String); method public static java.lang.String getDocId(android.net.Uri); method public static java.lang.String getRootId(android.net.Uri); method public static java.lang.String getSearchQuery(android.net.Uri); method public static android.graphics.Bitmap getThumbnail(android.content.ContentResolver, android.net.Uri, android.graphics.Point); method public static android.graphics.Bitmap getThumbnail(android.content.ContentResolver, android.net.Uri, android.graphics.Point); method public static boolean renameDocument(android.content.ContentResolver, android.net.Uri, java.lang.String); method public static boolean renameDocument(android.content.ContentResolver, android.net.Uri, java.lang.String); field public static final java.lang.String EXTRA_HAS_MORE = "has_more"; field public static final java.lang.String EXTRA_HAS_MORE = "has_more";
core/java/android/provider/DocumentsContract.java +52 −16 Original line number Original line Diff line number Diff line Loading @@ -34,6 +34,7 @@ import libcore.io.IoUtils; import java.io.IOException; import java.io.IOException; import java.io.InputStream; import java.io.InputStream; import java.util.List; /** /** * The contract between a storage backend and the platform. Contains definitions * The contract between a storage backend and the platform. Contains definitions Loading Loading @@ -152,36 +153,71 @@ public final class DocumentsContract { .authority(authority).appendPath(PATH_ROOTS).appendPath(rootId).build(); .authority(authority).appendPath(PATH_ROOTS).appendPath(rootId).build(); } } /** * Build URI representing the given {@link DocumentColumns#DOC_ID} in a * storage root. */ public static Uri buildDocumentUri(String authority, String rootId, String docId) { public static Uri buildDocumentUri(String authority, String rootId, String docId) { return buildDocumentUri(buildRootUri(authority, rootId), docId); return new Uri.Builder().scheme(ContentResolver.SCHEME_CONTENT).authority(authority) .appendPath(PATH_ROOTS).appendPath(rootId).appendPath(PATH_DOCS).appendPath(docId) .build(); } } /** /** * Build URI representing the given {@link DocumentColumns#DOC_ID} in a * Build URI representing the contents of the given directory in a storage * storage root. * backend. The given document must be {@link #MIME_TYPE_DIRECTORY}. */ */ public static Uri buildDocumentUri(Uri rootUri, String docId) { public static Uri buildContentsUri(String authority, String rootId, String docId) { return rootUri.buildUpon().appendPath(PATH_DOCS).appendPath(docId).build(); return new Uri.Builder().scheme(ContentResolver.SCHEME_CONTENT).authority(authority) .appendPath(PATH_ROOTS).appendPath(rootId).appendPath(PATH_DOCS).appendPath(docId) .appendPath(PATH_CONTENTS).build(); } } /** /** * Build URI representing a search for matching documents under a directory * Build URI representing a search for matching documents under a directory * in a storage backend. * in a storage backend. * * @param documentUri directory to search under, which must have * {@link #FLAG_SUPPORTS_SEARCH}. */ */ public static Uri buildSearchUri(Uri documentUri, String query) { public static Uri buildSearchUri(String authority, String rootId, String docId, String query) { return documentUri.buildUpon() return new Uri.Builder().scheme(ContentResolver.SCHEME_CONTENT).authority(authority) .appendPath(PATH_ROOTS).appendPath(rootId).appendPath(PATH_DOCS).appendPath(docId) .appendPath(PATH_SEARCH).appendQueryParameter(PARAM_QUERY, query).build(); .appendPath(PATH_SEARCH).appendQueryParameter(PARAM_QUERY, query).build(); } } /** public static Uri buildDocumentUri(Uri relatedUri, String docId) { * Build URI representing the contents of the given directory in a storage return buildDocumentUri(relatedUri.getAuthority(), getRootId(relatedUri), docId); * backend. The given document must be {@link #MIME_TYPE_DIRECTORY}. } */ public static Uri buildContentsUri(Uri documentUri) { public static Uri buildContentsUri(Uri relatedUri) { return documentUri.buildUpon().appendPath(PATH_CONTENTS).build(); return buildContentsUri( relatedUri.getAuthority(), getRootId(relatedUri), getDocId(relatedUri)); } public static Uri buildSearchUri(Uri relatedUri, String query) { return buildSearchUri( relatedUri.getAuthority(), getRootId(relatedUri), getDocId(relatedUri), query); } public static String getRootId(Uri documentUri) { final List<String> paths = documentUri.getPathSegments(); if (!PATH_ROOTS.equals(paths.get(0))) { throw new IllegalArgumentException(); } return paths.get(1); } public static String getDocId(Uri documentUri) { final List<String> paths = documentUri.getPathSegments(); if (!PATH_ROOTS.equals(paths.get(0))) { throw new IllegalArgumentException(); } if (!PATH_DOCS.equals(paths.get(2))) { throw new IllegalArgumentException(); } return paths.get(3); } public static String getSearchQuery(Uri documentUri) { return documentUri.getQueryParameter(PARAM_QUERY); } } /** /** Loading
packages/DocumentsUI/src/com/android/documentsui/DirectoryFragment.java +32 −46 Original line number Original line Diff line number Diff line Loading @@ -67,31 +67,29 @@ public class DirectoryFragment extends Fragment { private AbsListView mCurrentView; private AbsListView mCurrentView; private static final int TYPE_NORMAL = 1; private static final int TYPE_SEARCH = 2; private static final int TYPE_RECENT_OPEN = 3; private static final int TYPE_RECENT_CREATE = 4; private int mType = TYPE_NORMAL; private DocumentsAdapter mAdapter; private DocumentsAdapter mAdapter; private LoaderCallbacks<Cursor> mCallbacks; private LoaderCallbacks<Cursor> mCallbacks; private int mFlags; private static final String EXTRA_URI = "uri"; private static final String EXTRA_ROOT_URI = "rootUri"; private static final String EXTRA_DOCS_URI = "docsUri"; private static final int LOADER_DOCUMENTS = 2; private static final int LOADER_DOCUMENTS = 2; public static void show(FragmentManager fm, Uri rootUri, Uri docsUri, String displayName, public static void show(FragmentManager fm, Uri uri) { boolean addToBackStack) { final Bundle args = new Bundle(); final Bundle args = new Bundle(); args.putParcelable(EXTRA_ROOT_URI, rootUri); args.putParcelable(EXTRA_URI, uri); args.putParcelable(EXTRA_DOCS_URI, docsUri); final DirectoryFragment fragment = new DirectoryFragment(); final DirectoryFragment fragment = new DirectoryFragment(); fragment.setArguments(args); fragment.setArguments(args); final FragmentTransaction ft = fm.beginTransaction(); final FragmentTransaction ft = fm.beginTransaction(); ft.replace(R.id.directory, fragment); ft.replace(R.id.directory, fragment); if (addToBackStack) { ft.addToBackStack(displayName); } ft.setBreadCrumbTitle(displayName); ft.commitAllowingStateLoss(); ft.commitAllowingStateLoss(); } } Loading Loading @@ -119,9 +117,17 @@ public class DirectoryFragment extends Fragment { mAdapter = new DocumentsAdapter(context); mAdapter = new DocumentsAdapter(context); updateMode(); updateMode(); // TODO: migrate flags query to loader final Uri uri = getArguments().getParcelable(EXTRA_URI); final Uri docsUri = getArguments().getParcelable(EXTRA_DOCS_URI); mFlags = getDocumentFlags(context, docsUri); if (uri.getQueryParameter(DocumentsContract.PARAM_QUERY) != null) { mType = TYPE_SEARCH; } else if (RecentsProvider.buildRecentOpen().equals(uri)) { mType = TYPE_RECENT_OPEN; } else if (RecentsProvider.buildRecentCreate().equals(uri)) { mType = TYPE_RECENT_CREATE; } else { mType = TYPE_NORMAL; } mCallbacks = new LoaderCallbacks<Cursor>() { mCallbacks = new LoaderCallbacks<Cursor>() { @Override @Override Loading @@ -137,10 +143,10 @@ public class DirectoryFragment extends Fragment { } } final Uri contentsUri; final Uri contentsUri; if (docsUri.getQueryParameter(DocumentsContract.PARAM_QUERY) != null) { if (mType == TYPE_NORMAL) { contentsUri = docsUri; contentsUri = DocumentsContract.buildContentsUri(uri); } else { } else { contentsUri = DocumentsContract.buildContentsUri(docsUri); contentsUri = uri; } } return new CursorLoader(context, contentsUri, null, null, null, sortOrder); return new CursorLoader(context, contentsUri, null, null, null, sortOrder); Loading @@ -164,10 +170,6 @@ public class DirectoryFragment extends Fragment { public void onStart() { public void onStart() { super.onStart(); super.onStart(); getLoaderManager().restartLoader(LOADER_DOCUMENTS, getArguments(), mCallbacks); getLoaderManager().restartLoader(LOADER_DOCUMENTS, getArguments(), mCallbacks); // TODO: clean up tracking of current directory final Uri docsUri = getArguments().getParcelable(EXTRA_DOCS_URI); ((DocumentsActivity) getActivity()).onDirectoryChanged(docsUri, mFlags); } } @Override @Override Loading Loading @@ -249,8 +251,8 @@ public class DirectoryFragment extends Fragment { @Override @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { public void onItemClick(AdapterView<?> parent, View view, int position, long id) { final Cursor cursor = (Cursor) mAdapter.getItem(position); final Cursor cursor = (Cursor) mAdapter.getItem(position); final Uri rootUri = getArguments().getParcelable(EXTRA_ROOT_URI); final Uri uri = getArguments().getParcelable(EXTRA_URI); final Document doc = Document.fromCursor(rootUri, cursor); final Document doc = Document.fromCursor(uri, cursor); ((DocumentsActivity) getActivity()).onDocumentPicked(doc); ((DocumentsActivity) getActivity()).onDocumentPicked(doc); } } }; }; Loading @@ -270,7 +272,7 @@ public class DirectoryFragment extends Fragment { @Override @Override public boolean onActionItemClicked(ActionMode mode, MenuItem item) { public boolean onActionItemClicked(ActionMode mode, MenuItem item) { if (item.getItemId() == R.id.menu_open) { if (item.getItemId() == R.id.menu_open) { final Uri rootUri = getArguments().getParcelable(EXTRA_ROOT_URI); final Uri uri = getArguments().getParcelable(EXTRA_URI); final SparseBooleanArray checked = mCurrentView.getCheckedItemPositions(); final SparseBooleanArray checked = mCurrentView.getCheckedItemPositions(); final ArrayList<Document> docs = Lists.newArrayList(); final ArrayList<Document> docs = Lists.newArrayList(); Loading @@ -278,7 +280,7 @@ public class DirectoryFragment extends Fragment { for (int i = 0; i < size; i++) { for (int i = 0; i < size; i++) { if (checked.valueAt(i)) { if (checked.valueAt(i)) { final Cursor cursor = (Cursor) mAdapter.getItem(checked.keyAt(i)); final Cursor cursor = (Cursor) mAdapter.getItem(checked.keyAt(i)); docs.add(Document.fromCursor(rootUri, cursor)); docs.add(Document.fromCursor(uri, cursor)); } } } } Loading Loading @@ -346,15 +348,13 @@ public class DirectoryFragment extends Fragment { final long lastModified = getCursorLong(cursor, DocumentColumns.LAST_MODIFIED); final long lastModified = getCursorLong(cursor, DocumentColumns.LAST_MODIFIED); final int flags = getCursorInt(cursor, DocumentColumns.FLAGS); final int flags = getCursorInt(cursor, DocumentColumns.FLAGS); final Uri rootUri = getArguments().getParcelable(EXTRA_ROOT_URI); final Uri uri = getArguments().getParcelable(EXTRA_URI); final String authority = rootUri.getAuthority(); if ((flags & DocumentsContract.FLAG_SUPPORTS_THUMBNAIL) != 0) { if ((flags & DocumentsContract.FLAG_SUPPORTS_THUMBNAIL) != 0) { final Uri childUri = DocumentsContract.buildDocumentUri(rootUri, docId); final Uri childUri = DocumentsContract.buildDocumentUri(uri, docId); icon.setImageURI(childUri); icon.setImageURI(childUri); } else { } else { icon.setImageDrawable( icon.setImageDrawable(DocumentsActivity.resolveDocumentIcon( DocumentsActivity.resolveDocumentIcon(context, authority, mimeType)); context, uri.getAuthority(), mimeType)); } } title.setText(displayName); title.setText(displayName); Loading @@ -364,20 +364,6 @@ public class DirectoryFragment extends Fragment { } } } } private static int getDocumentFlags(Context context, Uri uri) { final Cursor cursor = context.getContentResolver().query(uri, new String[] { DocumentColumns.FLAGS }, null, null, null); try { if (cursor.moveToFirst()) { return getCursorInt(cursor, DocumentColumns.FLAGS); } else { return 0; } } finally { cursor.close(); } } public static String getCursorString(Cursor cursor, String columnName) { public static String getCursorString(Cursor cursor, String columnName) { return cursor.getString(cursor.getColumnIndex(columnName)); return cursor.getString(cursor.getColumnIndex(columnName)); } } Loading
packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java +205 −80 File changed.Preview size limit exceeded, changes collapsed. Show changes
packages/DocumentsUI/src/com/android/documentsui/RecentsProvider.java +29 −6 Original line number Original line Diff line number Diff line Loading @@ -17,6 +17,7 @@ package com.android.documentsui; package com.android.documentsui; import android.content.ContentProvider; import android.content.ContentProvider; import android.content.ContentResolver; import android.content.ContentValues; import android.content.ContentValues; import android.content.Context; import android.content.Context; import android.content.UriMatcher; import android.content.UriMatcher; Loading @@ -30,6 +31,9 @@ import android.util.Log; public class RecentsProvider extends ContentProvider { public class RecentsProvider extends ContentProvider { private static final String TAG = "RecentsProvider"; private static final String TAG = "RecentsProvider"; // TODO: offer view of recents that handles backend root resolution before // returning cursor, include extra columns public static final String AUTHORITY = "com.android.documentsui.recents"; public static final String AUTHORITY = "com.android.documentsui.recents"; private static final UriMatcher sMatcher = new UriMatcher(UriMatcher.NO_MATCH); private static final UriMatcher sMatcher = new UriMatcher(UriMatcher.NO_MATCH); Loading @@ -53,13 +57,29 @@ public class RecentsProvider extends ContentProvider { * starting with root. * starting with root. */ */ public static final String COL_PATH = "path"; public static final String COL_PATH = "path"; public static final String COL_URI = "uri"; public static final String COL_PACKAGE_NAME = "package_name"; public static final String COL_PACKAGE_NAME = "package_name"; public static final String COL_TIMESTAMP = "timestamp"; public static final String COL_TIMESTAMP = "timestamp"; public static Uri buildRecentOpen() { return new Uri.Builder().scheme(ContentResolver.SCHEME_CONTENT) .authority(AUTHORITY).appendPath("recent_open").build(); } public static Uri buildRecentCreate() { return new Uri.Builder().scheme(ContentResolver.SCHEME_CONTENT) .authority(AUTHORITY).appendPath("recent_create").build(); } public static Uri buildResume(String packageName) { return new Uri.Builder().scheme(ContentResolver.SCHEME_CONTENT) .authority(AUTHORITY).appendPath("resume").appendPath(packageName).build(); } private DatabaseHelper mHelper; private DatabaseHelper mHelper; private static class DatabaseHelper extends SQLiteOpenHelper { private static class DatabaseHelper extends SQLiteOpenHelper { private static final String DB_NAME = "recents"; private static final String DB_NAME = "recents.db"; private static final int VERSION_INIT = 1; private static final int VERSION_INIT = 1; Loading @@ -70,19 +90,19 @@ public class RecentsProvider extends ContentProvider { @Override @Override public void onCreate(SQLiteDatabase db) { public void onCreate(SQLiteDatabase db) { db.execSQL("CREATE TABLE " + TABLE_RECENT_OPEN + " (" + db.execSQL("CREATE TABLE " + TABLE_RECENT_OPEN + " (" + COL_PATH + " TEXT," + COL_URI + " TEXT PRIMARY KEY ON CONFLICT REPLACE," + COL_TIMESTAMP + " INTEGER," + COL_TIMESTAMP + " INTEGER" + ")"); ")"); db.execSQL("CREATE TABLE " + TABLE_RECENT_CREATE + " (" + db.execSQL("CREATE TABLE " + TABLE_RECENT_CREATE + " (" + COL_PATH + " TEXT," + COL_PATH + " TEXT PRIMARY KEY ON CONFLICT REPLACE," + COL_TIMESTAMP + " INTEGER," + COL_TIMESTAMP + " INTEGER" + ")"); ")"); db.execSQL("CREATE TABLE " + TABLE_RESUME + " (" + db.execSQL("CREATE TABLE " + TABLE_RESUME + " (" + COL_PACKAGE_NAME + " TEXT PRIMARY KEY ON CONFLICT REPLACE," + COL_PACKAGE_NAME + " TEXT PRIMARY KEY ON CONFLICT REPLACE," + COL_PATH + " TEXT," + COL_PATH + " TEXT," + COL_TIMESTAMP + " INTEGER," + COL_TIMESTAMP + " INTEGER" + ")"); ")"); } } Loading Loading @@ -136,11 +156,13 @@ public class RecentsProvider extends ContentProvider { final SQLiteDatabase db = mHelper.getWritableDatabase(); final SQLiteDatabase db = mHelper.getWritableDatabase(); switch (sMatcher.match(uri)) { switch (sMatcher.match(uri)) { case URI_RECENT_OPEN: { case URI_RECENT_OPEN: { values.put(COL_TIMESTAMP, System.currentTimeMillis()); db.insert(TABLE_RECENT_OPEN, null, values); db.insert(TABLE_RECENT_OPEN, null, values); db.delete(TABLE_RECENT_OPEN, buildWhereOlder(DateUtils.WEEK_IN_MILLIS), null); db.delete(TABLE_RECENT_OPEN, buildWhereOlder(DateUtils.WEEK_IN_MILLIS), null); return uri; return uri; } } case URI_RECENT_CREATE: { case URI_RECENT_CREATE: { values.put(COL_TIMESTAMP, System.currentTimeMillis()); db.insert(TABLE_RECENT_CREATE, null, values); db.insert(TABLE_RECENT_CREATE, null, values); db.delete(TABLE_RECENT_CREATE, buildWhereOlder(DateUtils.WEEK_IN_MILLIS), null); db.delete(TABLE_RECENT_CREATE, buildWhereOlder(DateUtils.WEEK_IN_MILLIS), null); return uri; return uri; Loading @@ -148,6 +170,7 @@ public class RecentsProvider extends ContentProvider { case URI_RESUME: { case URI_RESUME: { final String packageName = uri.getPathSegments().get(1); final String packageName = uri.getPathSegments().get(1); values.put(COL_PACKAGE_NAME, packageName); values.put(COL_PACKAGE_NAME, packageName); values.put(COL_TIMESTAMP, System.currentTimeMillis()); db.insert(TABLE_RESUME, null, values); db.insert(TABLE_RESUME, null, values); return uri; return uri; } } Loading