Merge "Show loading, error, and info messages as footers." into klp-dev
This commit is contained in:
34
packages/DocumentsUI/res/layout/item_loading.xml
Normal file
34
packages/DocumentsUI/res/layout/item_loading.xml
Normal file
@@ -0,0 +1,34 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Copyright (C) 2013 The Android Open Source Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:minHeight="?android:attr/listPreferredItemHeight"
|
||||
android:paddingStart="?android:attr/listPreferredItemPaddingStart"
|
||||
android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
|
||||
android:paddingTop="8dip"
|
||||
android:paddingBottom="8dip"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<ProgressBar
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:indeterminate="true"
|
||||
style="?android:attr/progressBarStyle" />
|
||||
|
||||
</FrameLayout>
|
||||
59
packages/DocumentsUI/res/layout/item_message_grid.xml
Normal file
59
packages/DocumentsUI/res/layout/item_message_grid.xml
Normal file
@@ -0,0 +1,59 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Copyright (C) 2013 The Android Open Source Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="180dip"
|
||||
android:paddingBottom="?android:attr/listPreferredItemPaddingEnd"
|
||||
android:paddingEnd="?android:attr/listPreferredItemPaddingEnd">
|
||||
|
||||
<FrameLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@color/chip"
|
||||
android:foreground="@drawable/item_background"
|
||||
android:duplicateParentState="true">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:paddingBottom="6dp"
|
||||
android:orientation="vertical"
|
||||
android:gravity="center">
|
||||
|
||||
<ImageView
|
||||
android:id="@android:id/icon"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:contentDescription="@null" />
|
||||
|
||||
<TextView
|
||||
android:id="@android:id/title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:singleLine="true"
|
||||
android:ellipsize="marquee"
|
||||
android:paddingTop="6dp"
|
||||
android:paddingStart="?android:attr/listPreferredItemPaddingStart"
|
||||
android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
|
||||
android:textAppearance="?android:attr/textAppearanceSmall"
|
||||
android:textAlignment="viewStart" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</FrameLayout>
|
||||
|
||||
</FrameLayout>
|
||||
47
packages/DocumentsUI/res/layout/item_message_list.xml
Normal file
47
packages/DocumentsUI/res/layout/item_message_list.xml
Normal file
@@ -0,0 +1,47 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Copyright (C) 2013 The Android Open Source Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@drawable/item_background"
|
||||
android:minHeight="?android:attr/listPreferredItemHeight"
|
||||
android:paddingStart="?android:attr/listPreferredItemPaddingStart"
|
||||
android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
|
||||
android:paddingTop="8dip"
|
||||
android:paddingBottom="8dip"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<ImageView
|
||||
android:id="@android:id/icon"
|
||||
android:layout_width="@android:dimen/app_icon_size"
|
||||
android:layout_height="@android:dimen/app_icon_size"
|
||||
android:layout_marginEnd="8dip"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:scaleType="centerInside"
|
||||
android:contentDescription="@null" />
|
||||
|
||||
<TextView
|
||||
android:id="@android:id/title"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:singleLine="true"
|
||||
android:ellipsize="marquee"
|
||||
android:textAppearance="?android:attr/textAppearanceMedium"
|
||||
android:textAlignment="viewStart" />
|
||||
|
||||
</LinearLayout>
|
||||
@@ -412,11 +412,83 @@ public class DirectoryFragment extends Fragment {
|
||||
return ((DocumentsActivity) fragment.getActivity()).getDisplayState();
|
||||
}
|
||||
|
||||
private interface Footer {
|
||||
public View getView(View convertView, ViewGroup parent);
|
||||
}
|
||||
|
||||
private static class LoadingFooter implements Footer {
|
||||
@Override
|
||||
public View getView(View convertView, ViewGroup parent) {
|
||||
final Context context = parent.getContext();
|
||||
if (convertView == null) {
|
||||
final LayoutInflater inflater = LayoutInflater.from(context);
|
||||
convertView = inflater.inflate(R.layout.item_loading, parent, false);
|
||||
}
|
||||
return convertView;
|
||||
}
|
||||
}
|
||||
|
||||
private class MessageFooter implements Footer {
|
||||
private final int mIcon;
|
||||
private final String mMessage;
|
||||
|
||||
public MessageFooter(int icon, String message) {
|
||||
mIcon = icon;
|
||||
mMessage = message;
|
||||
}
|
||||
|
||||
@Override
|
||||
public View getView(View convertView, ViewGroup parent) {
|
||||
final Context context = parent.getContext();
|
||||
final State state = getDisplayState(DirectoryFragment.this);
|
||||
|
||||
if (convertView == null) {
|
||||
final LayoutInflater inflater = LayoutInflater.from(context);
|
||||
if (state.mode == MODE_LIST) {
|
||||
convertView = inflater.inflate(R.layout.item_message_list, parent, false);
|
||||
} else if (state.mode == MODE_GRID) {
|
||||
convertView = inflater.inflate(R.layout.item_message_grid, parent, false);
|
||||
} else {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
}
|
||||
|
||||
final ImageView icon = (ImageView) convertView.findViewById(android.R.id.icon);
|
||||
final TextView title = (TextView) convertView.findViewById(android.R.id.title);
|
||||
icon.setImageResource(mIcon);
|
||||
title.setText(mMessage);
|
||||
return convertView;
|
||||
}
|
||||
}
|
||||
|
||||
private class DocumentsAdapter extends BaseAdapter {
|
||||
private Cursor mCursor;
|
||||
private int mCursorCount;
|
||||
|
||||
private List<Footer> mFooters = Lists.newArrayList();
|
||||
|
||||
public void swapCursor(Cursor cursor) {
|
||||
mCursor = cursor;
|
||||
mCursorCount = cursor != null ? cursor.getCount() : 0;
|
||||
|
||||
mFooters.clear();
|
||||
|
||||
final Bundle extras = cursor != null ? cursor.getExtras() : null;
|
||||
if (extras != null) {
|
||||
final String info = extras.getString(DocumentsContract.EXTRA_INFO);
|
||||
if (info != null) {
|
||||
mFooters.add(new MessageFooter(
|
||||
com.android.internal.R.drawable.ic_menu_info_details, info));
|
||||
}
|
||||
final String error = extras.getString(DocumentsContract.EXTRA_ERROR);
|
||||
if (error != null) {
|
||||
mFooters.add(new MessageFooter(
|
||||
com.android.internal.R.drawable.ic_dialog_alert, error));
|
||||
}
|
||||
if (extras.getBoolean(DocumentsContract.EXTRA_LOADING, false)) {
|
||||
mFooters.add(new LoadingFooter());
|
||||
}
|
||||
}
|
||||
|
||||
if (isEmpty()) {
|
||||
mEmptyView.setVisibility(View.VISIBLE);
|
||||
@@ -429,6 +501,15 @@ public class DirectoryFragment extends Fragment {
|
||||
|
||||
@Override
|
||||
public View getView(int position, View convertView, ViewGroup parent) {
|
||||
if (position < mCursorCount) {
|
||||
return getDocumentView(position, convertView, parent);
|
||||
} else {
|
||||
position -= mCursorCount;
|
||||
return mFooters.get(position).getView(convertView, parent);
|
||||
}
|
||||
}
|
||||
|
||||
private View getDocumentView(int position, View convertView, ViewGroup parent) {
|
||||
final Context context = parent.getContext();
|
||||
final State state = getDisplayState(DirectoryFragment.this);
|
||||
|
||||
@@ -535,21 +616,42 @@ public class DirectoryFragment extends Fragment {
|
||||
|
||||
@Override
|
||||
public int getCount() {
|
||||
return mCursor != null ? mCursor.getCount() : 0;
|
||||
return mCursorCount + mFooters.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Cursor getItem(int position) {
|
||||
if (mCursor != null) {
|
||||
if (position < mCursorCount) {
|
||||
mCursor.moveToPosition(position);
|
||||
return mCursor;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
return mCursor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getItemId(int position) {
|
||||
return position;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemViewType(int position) {
|
||||
if (position < mCursorCount) {
|
||||
return 0;
|
||||
} else {
|
||||
return IGNORE_ITEM_VIEW_TYPE;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean areAllItemsEnabled() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabled(int position) {
|
||||
return position < mCursorCount;
|
||||
}
|
||||
}
|
||||
|
||||
private static class ThumbnailAsyncTask extends AsyncTask<Uri, Void, Bitmap> {
|
||||
|
||||
@@ -77,11 +77,12 @@ public class DirectoryLoader extends AsyncTaskLoader<DirectoryResult> {
|
||||
.getContentResolver().acquireUnstableContentProviderClient(authority);
|
||||
final Cursor cursor = result.client.query(
|
||||
mUri, null, null, null, getQuerySortOrder(mSortOrder), mSignal);
|
||||
cursor.registerContentObserver(mObserver);
|
||||
|
||||
final Cursor withRoot = new RootCursorWrapper(mUri.getAuthority(), mRootId, cursor, -1);
|
||||
final Cursor sorted = new SortingCursorWrapper(withRoot, mSortOrder);
|
||||
|
||||
result.cursor = sorted;
|
||||
result.cursor.registerContentObserver(mObserver);
|
||||
} catch (Exception e) {
|
||||
result.exception = e;
|
||||
ContentProviderClient.closeQuietly(result.client);
|
||||
|
||||
@@ -18,6 +18,7 @@ package com.android.documentsui;
|
||||
|
||||
import android.database.AbstractCursor;
|
||||
import android.database.Cursor;
|
||||
import android.os.Bundle;
|
||||
|
||||
/**
|
||||
* Cursor wrapper that adds columns to identify which root a document came from.
|
||||
@@ -62,6 +63,11 @@ public class RootCursorWrapper extends AbstractCursor {
|
||||
mColumnNames[mRootIdIndex] = COLUMN_ROOT_ID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Bundle getExtras() {
|
||||
return mCursor.getExtras();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
super.close();
|
||||
@@ -128,5 +134,4 @@ public class RootCursorWrapper extends AbstractCursor {
|
||||
public boolean isNull(int column) {
|
||||
return mCursor.isNull(column);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@ import static com.android.documentsui.DocumentsActivity.State.SORT_ORDER_SIZE;
|
||||
|
||||
import android.database.AbstractCursor;
|
||||
import android.database.Cursor;
|
||||
import android.os.Bundle;
|
||||
import android.provider.DocumentsContract.Document;
|
||||
|
||||
/**
|
||||
@@ -95,6 +96,11 @@ public class SortingCursorWrapper extends AbstractCursor {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Bundle getExtras() {
|
||||
return mCursor.getExtras();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
super.close();
|
||||
|
||||
@@ -13,7 +13,20 @@
|
||||
android:permission="android.permission.MANAGE_DOCUMENTS">
|
||||
<meta-data
|
||||
android:name="android.content.DOCUMENT_PROVIDER"
|
||||
android:resource="@xml/document_provider" />
|
||||
android:value="true" />
|
||||
</provider>
|
||||
|
||||
<!-- TODO: find a better place for tests to live -->
|
||||
<provider
|
||||
android:name=".TestDocumentsProvider"
|
||||
android:authorities="com.example.documents"
|
||||
android:grantUriPermissions="true"
|
||||
android:exported="true"
|
||||
android:permission="android.permission.MANAGE_DOCUMENTS"
|
||||
android:enabled="false">
|
||||
<meta-data
|
||||
android:name="android.content.DOCUMENT_PROVIDER"
|
||||
android:value="true" />
|
||||
</provider>
|
||||
</application>
|
||||
</manifest>
|
||||
|
||||
@@ -0,0 +1,244 @@
|
||||
/*
|
||||
* Copyright (C) 2013 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.externalstorage;
|
||||
|
||||
import android.content.ContentResolver;
|
||||
import android.database.Cursor;
|
||||
import android.database.MatrixCursor;
|
||||
import android.database.MatrixCursor.RowBuilder;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.os.CancellationSignal;
|
||||
import android.os.ParcelFileDescriptor;
|
||||
import android.os.SystemClock;
|
||||
import android.provider.DocumentsContract;
|
||||
import android.provider.DocumentsContract.Document;
|
||||
import android.provider.DocumentsContract.Root;
|
||||
import android.provider.DocumentsProvider;
|
||||
import android.util.Log;
|
||||
|
||||
import java.io.FileNotFoundException;
|
||||
import java.lang.ref.WeakReference;
|
||||
|
||||
public class TestDocumentsProvider extends DocumentsProvider {
|
||||
private static final String TAG = "TestDocuments";
|
||||
|
||||
private static final boolean CRASH_ROOTS = false;
|
||||
private static final boolean CRASH_DOCUMENT = false;
|
||||
|
||||
private static final String MY_ROOT_ID = "myRoot";
|
||||
private static final String MY_DOC_ID = "myDoc";
|
||||
private static final String MY_DOC_NULL = "myNull";
|
||||
|
||||
private static final String[] DEFAULT_ROOT_PROJECTION = new String[] {
|
||||
Root.COLUMN_ROOT_ID, Root.COLUMN_ROOT_TYPE, Root.COLUMN_FLAGS, Root.COLUMN_ICON,
|
||||
Root.COLUMN_TITLE, Root.COLUMN_SUMMARY, Root.COLUMN_DOCUMENT_ID,
|
||||
Root.COLUMN_AVAILABLE_BYTES,
|
||||
};
|
||||
|
||||
private static final String[] DEFAULT_DOCUMENT_PROJECTION = new String[] {
|
||||
Document.COLUMN_DOCUMENT_ID, Document.COLUMN_MIME_TYPE, Document.COLUMN_DISPLAY_NAME,
|
||||
Document.COLUMN_LAST_MODIFIED, Document.COLUMN_FLAGS, Document.COLUMN_SIZE,
|
||||
};
|
||||
|
||||
private static String[] resolveRootProjection(String[] projection) {
|
||||
return projection != null ? projection : DEFAULT_ROOT_PROJECTION;
|
||||
}
|
||||
|
||||
private static String[] resolveDocumentProjection(String[] projection) {
|
||||
return projection != null ? projection : DEFAULT_DOCUMENT_PROJECTION;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Cursor queryRoots(String[] projection) throws FileNotFoundException {
|
||||
if (CRASH_ROOTS) System.exit(12);
|
||||
|
||||
final MatrixCursor result = new MatrixCursor(resolveRootProjection(projection));
|
||||
final RowBuilder row = result.newRow();
|
||||
row.offer(Root.COLUMN_ROOT_ID, MY_ROOT_ID);
|
||||
row.offer(Root.COLUMN_ROOT_TYPE, Root.ROOT_TYPE_SERVICE);
|
||||
row.offer(Root.COLUMN_FLAGS, Root.FLAG_SUPPORTS_RECENTS);
|
||||
row.offer(Root.COLUMN_TITLE, "_Test title which is really long");
|
||||
row.offer(Root.COLUMN_SUMMARY, "_Summary which is also super long text");
|
||||
row.offer(Root.COLUMN_DOCUMENT_ID, MY_DOC_ID);
|
||||
row.offer(Root.COLUMN_AVAILABLE_BYTES, 1024);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Cursor queryDocument(String documentId, String[] projection)
|
||||
throws FileNotFoundException {
|
||||
if (CRASH_DOCUMENT) System.exit(12);
|
||||
|
||||
final MatrixCursor result = new MatrixCursor(resolveDocumentProjection(projection));
|
||||
includeFile(result, documentId);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds any outstanding or finished "network" fetching.
|
||||
*/
|
||||
private WeakReference<CloudTask> mTask;
|
||||
|
||||
private static class CloudTask implements Runnable {
|
||||
|
||||
private final ContentResolver mResolver;
|
||||
private final Uri mNotifyUri;
|
||||
|
||||
private volatile boolean mFinished;
|
||||
|
||||
public CloudTask(ContentResolver resolver, Uri notifyUri) {
|
||||
mResolver = resolver;
|
||||
mNotifyUri = notifyUri;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
// Pretend to do some network
|
||||
Log.d(TAG, hashCode() + ": pretending to do some network!");
|
||||
SystemClock.sleep(2000);
|
||||
Log.d(TAG, hashCode() + ": network done!");
|
||||
|
||||
mFinished = true;
|
||||
|
||||
// Tell anyone remotely they should requery
|
||||
mResolver.notifyChange(mNotifyUri, null, false);
|
||||
}
|
||||
|
||||
public boolean includeIfFinished(MatrixCursor result) {
|
||||
Log.d(TAG, hashCode() + ": includeIfFinished() found " + mFinished);
|
||||
if (mFinished) {
|
||||
includeFile(result, "_networkfile1");
|
||||
includeFile(result, "_networkfile2");
|
||||
includeFile(result, "_networkfile3");
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static class CloudCursor extends MatrixCursor {
|
||||
public Object keepAlive;
|
||||
public final Bundle extras = new Bundle();
|
||||
|
||||
public CloudCursor(String[] columnNames) {
|
||||
super(columnNames);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Bundle getExtras() {
|
||||
return extras;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Cursor queryChildDocuments(
|
||||
String parentDocumentId, String[] projection, String sortOrder)
|
||||
throws FileNotFoundException {
|
||||
|
||||
final ContentResolver resolver = getContext().getContentResolver();
|
||||
final Uri notifyUri = DocumentsContract.buildDocumentUri(
|
||||
"com.example.documents", parentDocumentId);
|
||||
|
||||
CloudCursor result = new CloudCursor(resolveDocumentProjection(projection));
|
||||
result.setNotificationUri(resolver, notifyUri);
|
||||
|
||||
// Always include local results
|
||||
includeFile(result, MY_DOC_NULL);
|
||||
includeFile(result, "localfile1");
|
||||
includeFile(result, "localfile2");
|
||||
|
||||
synchronized (this) {
|
||||
// Try picking up an existing network fetch
|
||||
CloudTask task = mTask != null ? mTask.get() : null;
|
||||
if (task == null) {
|
||||
Log.d(TAG, "No network task found; starting!");
|
||||
task = new CloudTask(resolver, notifyUri);
|
||||
mTask = new WeakReference<CloudTask>(task);
|
||||
new Thread(task).start();
|
||||
|
||||
// Aggressively try freeing weak reference above
|
||||
new Thread() {
|
||||
@Override
|
||||
public void run() {
|
||||
while (mTask.get() != null) {
|
||||
SystemClock.sleep(200);
|
||||
System.gc();
|
||||
System.runFinalization();
|
||||
}
|
||||
Log.d(TAG, "AHA! THE CLOUD TASK WAS GC'ED!");
|
||||
}
|
||||
}.start();
|
||||
}
|
||||
|
||||
// Blend in cloud results if ready
|
||||
if (task.includeIfFinished(result)) {
|
||||
result.extras.putString(DocumentsContract.EXTRA_INFO,
|
||||
"Everything Went Better Than Expected and this message is quite "
|
||||
+ "long and verbose and maybe even too long");
|
||||
result.extras.putString(DocumentsContract.EXTRA_ERROR,
|
||||
"But then again, maybe our server ran into an error, which means "
|
||||
+ "we're going to have a bad time");
|
||||
} else {
|
||||
result.extras.putBoolean(DocumentsContract.EXTRA_LOADING, true);
|
||||
}
|
||||
|
||||
// Tie the network fetch to the cursor GC lifetime
|
||||
result.keepAlive = task;
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Cursor queryRecentDocuments(String rootId, String[] projection)
|
||||
throws FileNotFoundException {
|
||||
// Pretend to take a super long time to respond
|
||||
SystemClock.sleep(3000);
|
||||
|
||||
final MatrixCursor result = new MatrixCursor(resolveDocumentProjection(projection));
|
||||
includeFile(result, "It was /worth/ the_wait for?the file:with the&incredibly long name");
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ParcelFileDescriptor openDocument(String docId, String mode, CancellationSignal signal)
|
||||
throws FileNotFoundException {
|
||||
throw new FileNotFoundException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreate() {
|
||||
return true;
|
||||
}
|
||||
|
||||
private static void includeFile(MatrixCursor result, String docId) {
|
||||
final RowBuilder row = result.newRow();
|
||||
row.offer(Document.COLUMN_DOCUMENT_ID, docId);
|
||||
row.offer(Document.COLUMN_DISPLAY_NAME, docId);
|
||||
row.offer(Document.COLUMN_LAST_MODIFIED, System.currentTimeMillis());
|
||||
|
||||
if (MY_DOC_ID.equals(docId)) {
|
||||
row.offer(Document.COLUMN_MIME_TYPE, Document.MIME_TYPE_DIR);
|
||||
} else if (MY_DOC_NULL.equals(docId)) {
|
||||
// No MIME type
|
||||
} else {
|
||||
row.offer(Document.COLUMN_MIME_TYPE, "application/octet-stream");
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user