am af4d039f: Merge "More UX work for thumbnails, search, management." into klp-dev

* commit 'af4d039fb3a45d4a74683a69ee48071b8338a13d':
  More UX work for thumbnails, search, management.
This commit is contained in:
Jeff Sharkey
2013-09-10 17:02:11 -07:00
committed by Android Git Automerger
16 changed files with 270 additions and 67 deletions

View File

@@ -459,6 +459,7 @@ public final class DocumentsContract {
private static final String PATH_SEARCH = "search";
private static final String PARAM_QUERY = "query";
private static final String PARAM_MANAGE = "manage";
/**
* Build Uri representing the roots of a document provider. When queried, a
@@ -583,6 +584,16 @@ public final class DocumentsContract {
return searchDocumentsUri.getQueryParameter(PARAM_QUERY);
}
/** {@hide} */
public static Uri setManageMode(Uri uri) {
return uri.buildUpon().appendQueryParameter(PARAM_MANAGE, "true").build();
}
/** {@hide} */
public static boolean isManageMode(Uri uri) {
return uri.getBooleanQueryParameter(PARAM_MANAGE, false);
}
/**
* Return list of all documents that the calling package has "open." These
* are Uris matching {@link DocumentsContract} to which persistent

View File

@@ -167,6 +167,14 @@ public abstract class DocumentsProvider extends ContentProvider {
String parentDocumentId, String[] projection, String sortOrder)
throws FileNotFoundException;
/** {@hide} */
@SuppressWarnings("unused")
public Cursor queryChildDocumentsForManage(
String parentDocumentId, String[] projection, String sortOrder)
throws FileNotFoundException {
throw new UnsupportedOperationException("Manage not supported");
}
/**
* Return documents that that match the given query, starting the search at
* the given directory.
@@ -262,7 +270,12 @@ public abstract class DocumentsProvider extends ContentProvider {
case MATCH_DOCUMENT:
return queryDocument(getDocumentId(uri), projection);
case MATCH_CHILDREN:
return queryChildDocuments(getDocumentId(uri), projection, sortOrder);
if (DocumentsContract.isManageMode(uri)) {
return queryChildDocumentsForManage(
getDocumentId(uri), projection, sortOrder);
} else {
return queryChildDocuments(getDocumentId(uri), projection, sortOrder);
}
case MATCH_SEARCH:
return querySearchDocuments(
getDocumentId(uri), getSearchDocumentsQuery(uri), projection);

View File

@@ -32,12 +32,26 @@
android:layout_weight="1"
android:background="#fff">
<ImageView
<FrameLayout
android:id="@android:id/icon"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="centerInside"
android:contentDescription="@null" />
android:layout_height="match_parent">
<ImageView
android:id="@+id/icon_mime"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="centerInside"
android:contentDescription="@null" />
<ImageView
android:id="@+id/icon_thumb"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="centerCrop"
android:contentDescription="@null" />
</FrameLayout>
<ImageView
android:layout_width="match_parent"

View File

@@ -25,15 +25,29 @@
android:paddingBottom="8dip"
android:orientation="horizontal">
<ImageView
<FrameLayout
android:id="@android:id/icon"
android:layout_width="@dimen/icon_size"
android:layout_height="@dimen/icon_size"
android:layout_marginStart="12dp"
android:layout_marginEnd="20dp"
android:layout_gravity="center_vertical"
android:scaleType="centerInside"
android:contentDescription="@null" />
android:layout_gravity="center_vertical">
<ImageView
android:id="@+id/icon_mime"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="centerInside"
android:contentDescription="@null" />
<ImageView
android:id="@+id/icon_thumb"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="centerCrop"
android:contentDescription="@null" />
</FrameLayout>
<LinearLayout
android:layout_width="0dip"

View File

@@ -14,6 +14,13 @@
limitations under the License.
-->
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@android:id/title"
style="?android:attr/listSeparatorTextViewStyle" />
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="12dp">
<TextView
android:id="@android:id/title"
style="?android:attr/listSeparatorTextViewStyle" />
</FrameLayout>

View File

@@ -38,9 +38,11 @@ import android.content.Loader;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.Point;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.CancellationSignal;
import android.provider.DocumentsContract;
import android.provider.DocumentsContract.Document;
import android.text.format.DateUtils;
@@ -56,6 +58,7 @@ import android.view.View;
import android.view.ViewGroup;
import android.widget.AbsListView;
import android.widget.AbsListView.MultiChoiceModeListener;
import android.widget.AbsListView.RecyclerListener;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.BaseAdapter;
@@ -162,10 +165,12 @@ public class DirectoryFragment extends Fragment {
mListView = (ListView) view.findViewById(R.id.list);
mListView.setOnItemClickListener(mItemListener);
mListView.setMultiChoiceModeListener(mMultiListener);
mListView.setRecyclerListener(mRecycleListener);
mGridView = (GridView) view.findViewById(R.id.grid);
mGridView.setOnItemClickListener(mItemListener);
mGridView.setMultiChoiceModeListener(mMultiListener);
mGridView.setRecyclerListener(mRecycleListener);
return view;
}
@@ -192,13 +197,19 @@ public class DirectoryFragment extends Fragment {
case TYPE_NORMAL:
contentsUri = DocumentsContract.buildChildDocumentsUri(
doc.authority, doc.documentId);
if (state.action == ACTION_MANAGE) {
contentsUri = DocumentsContract.setManageMode(contentsUri);
}
return new DirectoryLoader(
context, root, doc, contentsUri, state.userSortOrder);
context, mType, root, doc, contentsUri, state.userSortOrder);
case TYPE_SEARCH:
contentsUri = DocumentsContract.buildSearchDocumentsUri(
doc.authority, doc.documentId, query);
if (state.action == ACTION_MANAGE) {
contentsUri = DocumentsContract.setManageMode(contentsUri);
}
return new DirectoryLoader(
context, root, doc, contentsUri, state.userSortOrder);
context, mType, root, doc, contentsUri, state.userSortOrder);
case TYPE_RECENT_OPEN:
final RootsCache roots = DocumentsApplication.getRootsCache(context);
final List<RootInfo> matchingRoots = roots.getMatchingRoots(state);
@@ -425,6 +436,20 @@ public class DirectoryFragment extends Fragment {
}
};
private RecyclerListener mRecycleListener = new RecyclerListener() {
@Override
public void onMovedToScrapHeap(View view) {
final ImageView iconThumb = (ImageView) view.findViewById(R.id.icon_thumb);
if (iconThumb != null) {
final ThumbnailAsyncTask oldTask = (ThumbnailAsyncTask) iconThumb.getTag();
if (oldTask != null) {
oldTask.reallyCancel();
iconThumb.setTag(null);
}
}
}
};
private void onShareDocuments(List<DocumentInfo> docs) {
Intent intent;
if (docs.size() == 1) {
@@ -632,7 +657,9 @@ public class DirectoryFragment extends Fragment {
final String docSummary = getCursorString(cursor, Document.COLUMN_SUMMARY);
final long docSize = getCursorLong(cursor, Document.COLUMN_SIZE);
final ImageView icon = (ImageView) convertView.findViewById(android.R.id.icon);
final View icon = convertView.findViewById(android.R.id.icon);
final ImageView iconMime = (ImageView) convertView.findViewById(R.id.icon_mime);
final ImageView iconThumb = (ImageView) convertView.findViewById(R.id.icon_thumb);
final TextView title = (TextView) convertView.findViewById(android.R.id.title);
final View line2 = convertView.findViewById(R.id.line2);
final ImageView icon1 = (ImageView) convertView.findViewById(android.R.id.icon1);
@@ -640,30 +667,49 @@ public class DirectoryFragment extends Fragment {
final TextView date = (TextView) convertView.findViewById(R.id.date);
final TextView size = (TextView) convertView.findViewById(R.id.size);
final ThumbnailAsyncTask oldTask = (ThumbnailAsyncTask) icon.getTag();
final ThumbnailAsyncTask oldTask = (ThumbnailAsyncTask) iconThumb.getTag();
if (oldTask != null) {
oldTask.cancel(false);
oldTask.reallyCancel();
iconThumb.setTag(null);
}
iconMime.animate().cancel();
iconThumb.animate().cancel();
final boolean supportsThumbnail = (docFlags & Document.FLAG_SUPPORTS_THUMBNAIL) != 0;
final boolean allowThumbnail = (state.derivedMode == MODE_GRID)
|| MimePredicate.mimeMatches(LIST_THUMBNAIL_MIMES, docMimeType);
boolean cacheHit = false;
if (supportsThumbnail && allowThumbnail) {
final Uri uri = DocumentsContract.buildDocumentUri(docAuthority, docId);
final Bitmap cachedResult = thumbs.get(uri);
if (cachedResult != null) {
icon.setImageBitmap(cachedResult);
iconThumb.setImageBitmap(cachedResult);
cacheHit = true;
} else {
final ThumbnailAsyncTask task = new ThumbnailAsyncTask(icon, mThumbSize);
icon.setImageBitmap(null);
icon.setTag(task);
task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, uri);
iconThumb.setImageDrawable(null);
final ThumbnailAsyncTask task = new ThumbnailAsyncTask(
uri, iconMime, iconThumb, mThumbSize);
iconThumb.setTag(task);
task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}
} else if (docIcon != 0) {
icon.setImageDrawable(IconUtils.loadPackageIcon(context, docAuthority, docIcon));
}
// Always throw MIME icon into place, even when a thumbnail is being
// loaded in background.
if (cacheHit) {
iconMime.setAlpha(0f);
iconThumb.setAlpha(1f);
} else {
icon.setImageDrawable(IconUtils.loadMimeIcon(context, docMimeType));
iconMime.setAlpha(1f);
iconThumb.setAlpha(0f);
if (docIcon != 0) {
iconMime.setImageDrawable(
IconUtils.loadPackageIcon(context, docAuthority, docIcon));
} else {
iconMime.setImageDrawable(IconUtils.loadMimeIcon(context, docMimeType));
}
}
title.setText(docDisplayName);
@@ -672,12 +718,19 @@ public class DirectoryFragment extends Fragment {
if (mType == TYPE_RECENT_OPEN) {
final RootInfo root = roots.getRoot(docAuthority, docRootId);
final Drawable iconDrawable = root.loadIcon(context);
icon1.setVisibility(View.VISIBLE);
icon1.setImageDrawable(root.loadIcon(context));
summary.setText(root.getDirectoryString());
summary.setVisibility(View.VISIBLE);
summary.setTextAlignment(TextView.TEXT_ALIGNMENT_TEXT_END);
hasLine2 = true;
icon1.setImageDrawable(iconDrawable);
if (iconDrawable != null && roots.isIconUnique(root)) {
// No summary needed if icon speaks for itself
summary.setVisibility(View.INVISIBLE);
} else {
summary.setText(root.getDirectoryString());
summary.setVisibility(View.VISIBLE);
summary.setTextAlignment(TextView.TEXT_ALIGNMENT_TEXT_END);
hasLine2 = true;
}
} else {
icon1.setVisibility(View.GONE);
if (docSummary != null) {
@@ -762,32 +815,39 @@ public class DirectoryFragment extends Fragment {
}
private static class ThumbnailAsyncTask extends AsyncTask<Uri, Void, Bitmap> {
private final ImageView mTarget;
private final Uri mUri;
private final ImageView mIconMime;
private final ImageView mIconThumb;
private final Point mThumbSize;
private final CancellationSignal mSignal;
public ThumbnailAsyncTask(ImageView target, Point thumbSize) {
mTarget = target;
public ThumbnailAsyncTask(
Uri uri, ImageView iconMime, ImageView iconThumb, Point thumbSize) {
mUri = uri;
mIconMime = iconMime;
mIconThumb = iconThumb;
mThumbSize = thumbSize;
mSignal = new CancellationSignal();
}
@Override
protected void onPreExecute() {
mTarget.setTag(this);
public void reallyCancel() {
cancel(false);
mSignal.cancel();
}
@Override
protected Bitmap doInBackground(Uri... params) {
final Context context = mTarget.getContext();
final Uri uri = params[0];
final Context context = mIconThumb.getContext();
Bitmap result = null;
try {
// TODO: switch to using unstable provider
result = DocumentsContract.getDocumentThumbnail(
context.getContentResolver(), uri, mThumbSize, null);
context.getContentResolver(), mUri, mThumbSize, mSignal);
if (result != null) {
final ThumbnailCache thumbs = DocumentsApplication.getThumbnailsCache(
context, mThumbSize);
thumbs.put(uri, result);
thumbs.put(mUri, result);
}
} catch (Exception e) {
Log.w(TAG, "Failed to load thumbnail: " + e);
@@ -797,9 +857,14 @@ public class DirectoryFragment extends Fragment {
@Override
protected void onPostExecute(Bitmap result) {
if (mTarget.getTag() == this) {
mTarget.setImageBitmap(result);
mTarget.setTag(null);
if (mIconThumb.getTag() == this && result != null) {
mIconThumb.setTag(null);
mIconThumb.setImageBitmap(result);
mIconMime.setAlpha(1f);
mIconMime.animate().alpha(0f).start();
mIconThumb.setAlpha(0f);
mIconThumb.animate().alpha(1f).start();
}
}
}

View File

@@ -62,6 +62,7 @@ class DirectoryResult implements AutoCloseable {
public class DirectoryLoader extends AsyncTaskLoader<DirectoryResult> {
private final ForceLoadContentObserver mObserver = new ForceLoadContentObserver();
private final int mType;
private final RootInfo mRoot;
private final DocumentInfo mDoc;
private final Uri mUri;
@@ -70,9 +71,10 @@ public class DirectoryLoader extends AsyncTaskLoader<DirectoryResult> {
private CancellationSignal mSignal;
private DirectoryResult mResult;
public DirectoryLoader(
Context context, RootInfo root, DocumentInfo doc, Uri uri, int userSortOrder) {
public DirectoryLoader(Context context, int type, RootInfo root, DocumentInfo doc, Uri uri,
int userSortOrder) {
super(context);
mType = type;
mRoot = root;
mDoc = doc;
mUri = uri;
@@ -128,6 +130,11 @@ public class DirectoryLoader extends AsyncTaskLoader<DirectoryResult> {
}
}
// Search always uses ranking from provider
if (mType == DirectoryFragment.TYPE_SEARCH) {
result.sortOrder = State.SORT_ORDER_UNKNOWN;
}
Log.d(TAG, "userMode=" + userMode + ", userSortOrder=" + mUserSortOrder + " --> mode="
+ result.mode + ", sortOrder=" + result.sortOrder);
@@ -137,11 +144,18 @@ public class DirectoryLoader extends AsyncTaskLoader<DirectoryResult> {
mUri, null, null, null, getQuerySortOrder(result.sortOrder), mSignal);
cursor.registerContentObserver(mObserver);
final Cursor withRoot = new RootCursorWrapper(
mUri.getAuthority(), mRoot.rootId, cursor, -1);
final Cursor sorted = new SortingCursorWrapper(withRoot, result.sortOrder);
cursor = new RootCursorWrapper(mUri.getAuthority(), mRoot.rootId, cursor, -1);
result.cursor = sorted;
if (mType == DirectoryFragment.TYPE_SEARCH) {
// Filter directories out of search results, for now
cursor = new FilteringCursorWrapper(cursor, null, new String[] {
Document.MIME_TYPE_DIR });
} else {
// Normal directories should have sorting applied
cursor = new SortingCursorWrapper(cursor, result.sortOrder);
}
result.cursor = cursor;
} catch (Exception e) {
Log.d(TAG, "Failed to query", e);
result.exception = e;

View File

@@ -50,6 +50,7 @@ import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.MenuItem.OnActionExpandListener;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
@@ -87,6 +88,7 @@ public class DocumentsActivity extends Activity {
private static final String EXTRA_STATE = "state";
private boolean mIgnoreNextNavigation;
private boolean mIgnoreNextCollapse;
private RootsCache mRoots;
private State mState;
@@ -234,12 +236,14 @@ public class DocumentsActivity extends Activity {
public void onDrawerOpened(View drawerView) {
mDrawerToggle.onDrawerOpened(drawerView);
updateActionBar();
invalidateOptionsMenu();
}
@Override
public void onDrawerClosed(View drawerView) {
mDrawerToggle.onDrawerClosed(drawerView);
updateActionBar();
invalidateOptionsMenu();
}
@Override
@@ -305,7 +309,6 @@ public class DocumentsActivity extends Activity {
public boolean onQueryTextSubmit(String query) {
mState.currentSearch = query;
onCurrentDirectoryChanged();
mSearchView.setIconified(true);
return true;
}
@@ -315,12 +318,22 @@ public class DocumentsActivity extends Activity {
}
});
mSearchView.setOnCloseListener(new OnCloseListener() {
searchMenu.setOnActionExpandListener(new OnActionExpandListener() {
@Override
public boolean onClose() {
public boolean onMenuItemActionExpand(MenuItem item) {
return true;
}
@Override
public boolean onMenuItemActionCollapse(MenuItem item) {
if (mIgnoreNextCollapse) {
mIgnoreNextCollapse = false;
return true;
}
mState.currentSearch = null;
onCurrentDirectoryChanged();
return false;
return true;
}
});
@@ -342,6 +355,18 @@ public class DocumentsActivity extends Activity {
final MenuItem list = menu.findItem(R.id.menu_list);
final MenuItem settings = menu.findItem(R.id.menu_settings);
// Open drawer means we hide most actions
if (mDrawerLayout.isDrawerOpen(mRootsContainer)) {
createDir.setVisible(false);
search.setVisible(false);
sort.setVisible(false);
grid.setVisible(false);
list.setVisible(false);
mIgnoreNextCollapse = true;
search.collapseActionView();
return true;
}
if (cwd != null) {
sort.setVisible(true);
grid.setVisible(mState.derivedMode != MODE_GRID);
@@ -352,6 +377,17 @@ public class DocumentsActivity extends Activity {
list.setVisible(false);
}
if (mState.currentSearch != null) {
// Search uses backend ranking; no sorting
sort.setVisible(false);
search.expandActionView();
mSearchView.setQuery(mState.currentSearch, false);
} else {
mIgnoreNextCollapse = true;
search.collapseActionView();
}
// Only sort by size when visible
sortSize.setVisible(mState.showSize);

View File

@@ -56,7 +56,11 @@ public class DocumentsApplication extends Application {
packageFilter.addAction(Intent.ACTION_PACKAGE_CHANGED);
packageFilter.addAction(Intent.ACTION_PACKAGE_REMOVED);
packageFilter.addDataScheme("package");
registerReceiver(mPackageReceiver, packageFilter);
registerReceiver(mCacheReceiver, packageFilter);
final IntentFilter localeFilter = new IntentFilter();
localeFilter.addAction(Intent.ACTION_LOCALE_CHANGED);
registerReceiver(mCacheReceiver, localeFilter);
}
@Override
@@ -70,7 +74,7 @@ public class DocumentsApplication extends Application {
}
}
private BroadcastReceiver mPackageReceiver = new BroadcastReceiver() {
private BroadcastReceiver mCacheReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
// TODO: narrow changed/removed to only packages that have backends

View File

@@ -34,6 +34,10 @@ public class FilteringCursorWrapper extends AbstractCursor {
private int mCount;
public FilteringCursorWrapper(Cursor cursor, String[] acceptMimes) {
this(cursor, acceptMimes, null);
}
public FilteringCursorWrapper(Cursor cursor, String[] acceptMimes, String[] rejectMimes) {
mCursor = cursor;
final int count = cursor.getCount();
@@ -43,6 +47,9 @@ public class FilteringCursorWrapper extends AbstractCursor {
while (cursor.moveToNext()) {
final String mimeType = cursor.getString(
cursor.getColumnIndex(Document.COLUMN_MIME_TYPE));
if (rejectMimes != null && MimePredicate.mimeMatches(rejectMimes, mimeType)) {
continue;
}
if (MimePredicate.mimeMatches(acceptMimes, mimeType)) {
mPosition[mCount++] = cursor.getPosition();
}

View File

@@ -183,12 +183,12 @@ public class RecentsCreateFragment extends Fragment {
convertView = inflater.inflate(R.layout.item_doc_list, parent, false);
}
final ImageView icon = (ImageView) convertView.findViewById(android.R.id.icon);
final ImageView iconMime = (ImageView) convertView.findViewById(R.id.icon_mime);
final TextView title = (TextView) convertView.findViewById(android.R.id.title);
final View line2 = convertView.findViewById(R.id.line2);
final DocumentStack stack = getItem(position);
icon.setImageDrawable(stack.root.loadIcon(context));
iconMime.setImageDrawable(stack.root.loadIcon(context));
final Drawable crumb = context.getResources()
.getDrawable(R.drawable.ic_breadcrumb_arrow);

View File

@@ -151,18 +151,18 @@ public class RecentsProvider extends ContentProvider {
case URI_RECENT:
final long cutoff = System.currentTimeMillis() - MAX_HISTORY_IN_MILLIS;
return db.query(TABLE_RECENT, projection, RecentColumns.TIMESTAMP + ">" + cutoff,
null, null, null, null);
null, null, null, sortOrder);
case URI_STATE:
final String authority = uri.getPathSegments().get(1);
final String rootId = uri.getPathSegments().get(2);
final String documentId = uri.getPathSegments().get(3);
return db.query(TABLE_STATE, projection, StateColumns.AUTHORITY + "=? AND "
+ StateColumns.ROOT_ID + "=? AND " + StateColumns.DOCUMENT_ID + "=?",
new String[] { authority, rootId, documentId }, null, null, null);
new String[] { authority, rootId, documentId }, null, null, sortOrder);
case URI_RESUME:
final String packageName = uri.getPathSegments().get(1);
return db.query(TABLE_RESUME, projection, ResumeColumns.PACKAGE_NAME + "=?",
new String[] { packageName }, null, null, null);
new String[] { packageName }, null, null, sortOrder);
default:
throw new UnsupportedOperationException("Unsupported Uri " + uri);
}

View File

@@ -109,6 +109,8 @@ public class RootsCache {
}
}
}
Log.d(TAG, "Update found " + mRoots.size() + " roots");
}
@Deprecated
@@ -133,6 +135,21 @@ public class RootsCache {
return null;
}
@GuardedBy("ActivityThread")
public boolean isIconUnique(RootInfo root) {
for (RootInfo test : mRoots) {
if (Objects.equal(test.authority, root.authority)) {
if (Objects.equal(test.rootId, root.rootId)) {
continue;
}
if (test.icon == root.icon) {
return false;
}
}
}
return true;
}
@GuardedBy("ActivityThread")
public RootInfo getRecentsRoot() {
return mRecentsRoot;

View File

@@ -25,6 +25,7 @@ import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.os.Bundle;
import android.provider.DocumentsContract.Root;
import android.text.TextUtils;
import android.text.format.Formatter;
import android.view.LayoutInflater;
import android.view.View;
@@ -168,7 +169,7 @@ public class RootsFragment extends Fragment {
}
summary.setText(summaryText);
summary.setVisibility(summaryText != null ? View.VISIBLE : View.GONE);
summary.setVisibility(TextUtils.isEmpty(summaryText) ? View.GONE : View.VISIBLE);
return convertView;
}

View File

@@ -26,6 +26,7 @@ import android.graphics.drawable.Drawable;
import android.os.Parcel;
import android.os.Parcelable;
import android.provider.DocumentsContract.Root;
import android.text.TextUtils;
import com.android.documentsui.IconUtils;
import com.android.documentsui.R;
@@ -203,6 +204,6 @@ public class RootInfo implements Durable, Parcelable {
}
public String getDirectoryString() {
return (summary != null) ? summary : title;
return !TextUtils.isEmpty(summary) ? summary : title;
}
}

View File

@@ -267,16 +267,15 @@ public class ExternalStorageProvider extends DocumentsProvider {
final LinkedList<File> pending = new LinkedList<File>();
pending.add(parent);
while (!pending.isEmpty() && result.getCount() < 20) {
while (!pending.isEmpty() && result.getCount() < 24) {
final File file = pending.removeFirst();
if (file.isDirectory()) {
for (File child : file.listFiles()) {
pending.add(child);
}
} else {
if (file.getName().toLowerCase().contains(query)) {
includeFile(result, null, file);
}
}
if (file.getName().toLowerCase().contains(query)) {
includeFile(result, null, file);
}
}
return result;