Loading src/com/android/documentsui/BaseActivity.java +29 −2 Original line number Diff line number Diff line Loading @@ -16,10 +16,13 @@ package com.android.documentsui; import static com.android.documentsui.DirectoryFragment.ANIM_DOWN; import static com.android.documentsui.DirectoryFragment.ANIM_NONE; import static com.android.documentsui.DirectoryFragment.ANIM_SIDE; import static com.android.documentsui.DirectoryFragment.ANIM_UP; import static com.android.internal.util.Preconditions.checkArgument; import android.annotation.Nullable; import android.app.Activity; import android.app.Fragment; import android.content.Intent; Loading Loading @@ -79,8 +82,9 @@ abstract class BaseActivity extends Activity { private final String mTag; public abstract State getDisplayState(); public abstract void onDocumentPicked(DocumentInfo doc); public abstract void onDocumentPicked(DocumentInfo doc, @Nullable DocumentContext siblings); public abstract void onDocumentsPicked(List<DocumentInfo> docs); abstract void onTaskFinished(Uri... uris); abstract void onDirectoryChanged(int anim); abstract void updateActionBar(); Loading Loading @@ -258,6 +262,17 @@ abstract class BaseActivity extends Activity { && !root.isDownloads(); } void onDirectoryCreated(DocumentInfo doc) { checkArgument(doc.isDirectory()); openDirectory(doc); } void openDirectory(DocumentInfo doc) { getDisplayState().stack.push(doc); getDisplayState().stackTouched = true; onCurrentDirectoryChanged(ANIM_DOWN); } /** * Call this when directory changes. Prior to root fragment update * the (abstract) directoryChanged method will be called. Loading Loading @@ -605,7 +620,6 @@ abstract class BaseActivity extends Activity { if (isDestroyed()) return; getDisplayState().restored = true; onCurrentDirectoryChanged(ANIM_NONE); onStackRestored(mRestoredStack, mExternal); } } Loading Loading @@ -843,4 +857,17 @@ abstract class BaseActivity extends Activity { updateActionBar(); } } /** * Interface providing access to current view of documents * even when all documents are not homed to the same parent. */ interface DocumentContext { /** * Returns the cursor for the selected document. The cursor can be used to retrieve * details about a document and its siblings. * @return */ Cursor getCursor(); } } src/com/android/documentsui/CreateDirectoryFragment.java +1 −1 Original line number Diff line number Diff line Loading @@ -146,7 +146,7 @@ public class CreateDirectoryFragment extends DialogFragment { protected void onPostExecute(DocumentInfo result) { if (result != null) { // Navigate into newly created child mActivity.onDocumentPicked(result); mActivity.onDirectoryCreated(result); } else { Toast.makeText(mActivity, R.string.create_error, Toast.LENGTH_SHORT).show(); } Loading src/com/android/documentsui/DirectoryFragment.java +12 −2 Original line number Diff line number Diff line Loading @@ -89,6 +89,7 @@ import android.widget.ListView; import android.widget.TextView; import android.widget.Toast; import com.android.documentsui.BaseActivity.DocumentContext; import com.android.documentsui.BaseActivity.State; import com.android.documentsui.MultiSelectManager.Selection; import com.android.documentsui.ProviderExecutor.Preemptable; Loading Loading @@ -457,7 +458,7 @@ public class DirectoryFragment extends Fragment { final int docFlags = getCursorInt(cursor, Document.COLUMN_FLAGS); if (isDocumentEnabled(docMimeType, docFlags)) { final DocumentInfo doc = DocumentInfo.fromDirectoryCursor(cursor); ((BaseActivity) getActivity()).onDocumentPicked(doc); ((BaseActivity) getActivity()).onDocumentPicked(doc, mAdapter); mSelectionManager.clearSelection(); return true; } Loading Loading @@ -949,7 +950,8 @@ public class DirectoryFragment extends Fragment { } } private final class DocumentsAdapter extends RecyclerView.Adapter<DocumentHolder> { private final class DocumentsAdapter extends RecyclerView.Adapter<DocumentHolder> implements DocumentContext { private final Context mContext; private final LayoutInflater mInflater; Loading Loading @@ -1213,6 +1215,14 @@ public class DirectoryFragment extends Fragment { } } @Override public Cursor getCursor() { if (Looper.myLooper() != Looper.getMainLooper()) { throw new IllegalStateException("Can't call getCursor from non-main thread."); } return mCursor; } private Cursor getItem(int position) { if (position < mCursorCount) { mCursor.moveToPosition(position); Loading src/com/android/documentsui/DocumentsActivity.java +3 −9 Original line number Diff line number Diff line Loading @@ -26,12 +26,8 @@ import static com.android.documentsui.BaseActivity.State.ACTION_OPEN_TREE; import static com.android.documentsui.DirectoryFragment.ANIM_DOWN; import static com.android.documentsui.DirectoryFragment.ANIM_NONE; import static com.android.documentsui.DirectoryFragment.ANIM_UP; import static com.android.internal.util.Preconditions.checkArgument; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import android.app.ActionBar; import android.app.Activity; import android.app.Fragment; import android.app.FragmentManager; Loading Loading @@ -608,12 +604,10 @@ public class DocumentsActivity extends BaseActivity { } @Override public void onDocumentPicked(DocumentInfo doc) { public void onDocumentPicked(DocumentInfo doc, DocumentContext context) { final FragmentManager fm = getFragmentManager(); if (doc.isDirectory()) { mState.stack.push(doc); mState.stackTouched = true; onCurrentDirectoryChanged(ANIM_DOWN); openDirectory(doc); } else if (mState.action == ACTION_OPEN || mState.action == ACTION_GET_CONTENT) { // Explicit file picked, return new ExistingFinishTask(doc.derivedUri).executeOnExecutor(getCurrentExecutor()); Loading src/com/android/documentsui/QuickViewIntentBuilder.java 0 → 100644 +112 −0 Original line number Diff line number Diff line /* * Copyright (C) 2015 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.documentsui; import static com.android.documentsui.model.DocumentInfo.getCursorString; import android.annotation.Nullable; import android.content.ClipData; import android.content.ClipDescription; import android.content.ComponentName; import android.content.Intent; import android.content.pm.PackageManager; import android.database.Cursor; import android.net.Uri; import android.provider.DocumentsContract; import android.provider.DocumentsContract.Document; import android.util.Log; import com.android.documentsui.BaseActivity.DocumentContext; import com.android.documentsui.model.DocumentInfo; /** * Provides support for gather a list of quick-viewable files into a quick view intent. */ final class QuickViewIntentBuilder { private static final String TAG = "QvIntentBuilder"; private static final boolean DEBUG = false; private final DocumentInfo mDocument; private final DocumentContext mContext; public ClipData mClipData; public int mDocumentLocation; private PackageManager mPkgManager; public QuickViewIntentBuilder( PackageManager pkgManager, DocumentInfo doc, DocumentContext context) { mPkgManager = pkgManager; mDocument = doc; mContext = context; } /** * Builds the intent for quick viewing. Short circuits building if a handler cannot * be resolved; in this case {@code null} is returned. */ @Nullable Intent build() { if (DEBUG) Log.d(TAG, "Preparing intent for doc:" + mDocument.documentId); Intent intent = new Intent(Intent.ACTION_QUICK_VIEW); intent.setDataAndType(mDocument.derivedUri, mDocument.mimeType); // Try to resolve the intent. If a matching app isn't installed, it won't resolve. ComponentName handler = intent.resolveActivity(mPkgManager); if (handler == null) { return null; } Cursor cursor = mContext.getCursor(); for (int i = 0; i < cursor.getCount(); i++) { onNextItem(i, cursor); } intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); intent.putExtra(Intent.EXTRA_INDEX, mDocumentLocation); intent.setClipData(mClipData); return intent; } private void onNextItem(int index, Cursor cursor) { cursor.moveToPosition(index); String mimeType = getCursorString(cursor, Document.COLUMN_MIME_TYPE); if (Document.MIME_TYPE_DIR.equals(mimeType)) { return; } String id = getCursorString(cursor, Document.COLUMN_DOCUMENT_ID); String authority = getCursorString(cursor, RootCursorWrapper.COLUMN_AUTHORITY); Uri uri = DocumentsContract.buildDocumentUri(authority, id); if (DEBUG) Log.d(TAG, "Including file[" + id + "] @ " + uri); if (id.equals(mDocument.documentId)) { if (DEBUG) Log.d(TAG, "Found starting point for QV. " + index); mDocumentLocation = index; } ClipData.Item item = new ClipData.Item(uri); if (mClipData == null) { mClipData = new ClipData( "URIs", new String[]{ClipDescription.MIMETYPE_TEXT_URILIST}, item); } else { mClipData.addItem(item); } } } Loading
src/com/android/documentsui/BaseActivity.java +29 −2 Original line number Diff line number Diff line Loading @@ -16,10 +16,13 @@ package com.android.documentsui; import static com.android.documentsui.DirectoryFragment.ANIM_DOWN; import static com.android.documentsui.DirectoryFragment.ANIM_NONE; import static com.android.documentsui.DirectoryFragment.ANIM_SIDE; import static com.android.documentsui.DirectoryFragment.ANIM_UP; import static com.android.internal.util.Preconditions.checkArgument; import android.annotation.Nullable; import android.app.Activity; import android.app.Fragment; import android.content.Intent; Loading Loading @@ -79,8 +82,9 @@ abstract class BaseActivity extends Activity { private final String mTag; public abstract State getDisplayState(); public abstract void onDocumentPicked(DocumentInfo doc); public abstract void onDocumentPicked(DocumentInfo doc, @Nullable DocumentContext siblings); public abstract void onDocumentsPicked(List<DocumentInfo> docs); abstract void onTaskFinished(Uri... uris); abstract void onDirectoryChanged(int anim); abstract void updateActionBar(); Loading Loading @@ -258,6 +262,17 @@ abstract class BaseActivity extends Activity { && !root.isDownloads(); } void onDirectoryCreated(DocumentInfo doc) { checkArgument(doc.isDirectory()); openDirectory(doc); } void openDirectory(DocumentInfo doc) { getDisplayState().stack.push(doc); getDisplayState().stackTouched = true; onCurrentDirectoryChanged(ANIM_DOWN); } /** * Call this when directory changes. Prior to root fragment update * the (abstract) directoryChanged method will be called. Loading Loading @@ -605,7 +620,6 @@ abstract class BaseActivity extends Activity { if (isDestroyed()) return; getDisplayState().restored = true; onCurrentDirectoryChanged(ANIM_NONE); onStackRestored(mRestoredStack, mExternal); } } Loading Loading @@ -843,4 +857,17 @@ abstract class BaseActivity extends Activity { updateActionBar(); } } /** * Interface providing access to current view of documents * even when all documents are not homed to the same parent. */ interface DocumentContext { /** * Returns the cursor for the selected document. The cursor can be used to retrieve * details about a document and its siblings. * @return */ Cursor getCursor(); } }
src/com/android/documentsui/CreateDirectoryFragment.java +1 −1 Original line number Diff line number Diff line Loading @@ -146,7 +146,7 @@ public class CreateDirectoryFragment extends DialogFragment { protected void onPostExecute(DocumentInfo result) { if (result != null) { // Navigate into newly created child mActivity.onDocumentPicked(result); mActivity.onDirectoryCreated(result); } else { Toast.makeText(mActivity, R.string.create_error, Toast.LENGTH_SHORT).show(); } Loading
src/com/android/documentsui/DirectoryFragment.java +12 −2 Original line number Diff line number Diff line Loading @@ -89,6 +89,7 @@ import android.widget.ListView; import android.widget.TextView; import android.widget.Toast; import com.android.documentsui.BaseActivity.DocumentContext; import com.android.documentsui.BaseActivity.State; import com.android.documentsui.MultiSelectManager.Selection; import com.android.documentsui.ProviderExecutor.Preemptable; Loading Loading @@ -457,7 +458,7 @@ public class DirectoryFragment extends Fragment { final int docFlags = getCursorInt(cursor, Document.COLUMN_FLAGS); if (isDocumentEnabled(docMimeType, docFlags)) { final DocumentInfo doc = DocumentInfo.fromDirectoryCursor(cursor); ((BaseActivity) getActivity()).onDocumentPicked(doc); ((BaseActivity) getActivity()).onDocumentPicked(doc, mAdapter); mSelectionManager.clearSelection(); return true; } Loading Loading @@ -949,7 +950,8 @@ public class DirectoryFragment extends Fragment { } } private final class DocumentsAdapter extends RecyclerView.Adapter<DocumentHolder> { private final class DocumentsAdapter extends RecyclerView.Adapter<DocumentHolder> implements DocumentContext { private final Context mContext; private final LayoutInflater mInflater; Loading Loading @@ -1213,6 +1215,14 @@ public class DirectoryFragment extends Fragment { } } @Override public Cursor getCursor() { if (Looper.myLooper() != Looper.getMainLooper()) { throw new IllegalStateException("Can't call getCursor from non-main thread."); } return mCursor; } private Cursor getItem(int position) { if (position < mCursorCount) { mCursor.moveToPosition(position); Loading
src/com/android/documentsui/DocumentsActivity.java +3 −9 Original line number Diff line number Diff line Loading @@ -26,12 +26,8 @@ import static com.android.documentsui.BaseActivity.State.ACTION_OPEN_TREE; import static com.android.documentsui.DirectoryFragment.ANIM_DOWN; import static com.android.documentsui.DirectoryFragment.ANIM_NONE; import static com.android.documentsui.DirectoryFragment.ANIM_UP; import static com.android.internal.util.Preconditions.checkArgument; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import android.app.ActionBar; import android.app.Activity; import android.app.Fragment; import android.app.FragmentManager; Loading Loading @@ -608,12 +604,10 @@ public class DocumentsActivity extends BaseActivity { } @Override public void onDocumentPicked(DocumentInfo doc) { public void onDocumentPicked(DocumentInfo doc, DocumentContext context) { final FragmentManager fm = getFragmentManager(); if (doc.isDirectory()) { mState.stack.push(doc); mState.stackTouched = true; onCurrentDirectoryChanged(ANIM_DOWN); openDirectory(doc); } else if (mState.action == ACTION_OPEN || mState.action == ACTION_GET_CONTENT) { // Explicit file picked, return new ExistingFinishTask(doc.derivedUri).executeOnExecutor(getCurrentExecutor()); Loading
src/com/android/documentsui/QuickViewIntentBuilder.java 0 → 100644 +112 −0 Original line number Diff line number Diff line /* * Copyright (C) 2015 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.documentsui; import static com.android.documentsui.model.DocumentInfo.getCursorString; import android.annotation.Nullable; import android.content.ClipData; import android.content.ClipDescription; import android.content.ComponentName; import android.content.Intent; import android.content.pm.PackageManager; import android.database.Cursor; import android.net.Uri; import android.provider.DocumentsContract; import android.provider.DocumentsContract.Document; import android.util.Log; import com.android.documentsui.BaseActivity.DocumentContext; import com.android.documentsui.model.DocumentInfo; /** * Provides support for gather a list of quick-viewable files into a quick view intent. */ final class QuickViewIntentBuilder { private static final String TAG = "QvIntentBuilder"; private static final boolean DEBUG = false; private final DocumentInfo mDocument; private final DocumentContext mContext; public ClipData mClipData; public int mDocumentLocation; private PackageManager mPkgManager; public QuickViewIntentBuilder( PackageManager pkgManager, DocumentInfo doc, DocumentContext context) { mPkgManager = pkgManager; mDocument = doc; mContext = context; } /** * Builds the intent for quick viewing. Short circuits building if a handler cannot * be resolved; in this case {@code null} is returned. */ @Nullable Intent build() { if (DEBUG) Log.d(TAG, "Preparing intent for doc:" + mDocument.documentId); Intent intent = new Intent(Intent.ACTION_QUICK_VIEW); intent.setDataAndType(mDocument.derivedUri, mDocument.mimeType); // Try to resolve the intent. If a matching app isn't installed, it won't resolve. ComponentName handler = intent.resolveActivity(mPkgManager); if (handler == null) { return null; } Cursor cursor = mContext.getCursor(); for (int i = 0; i < cursor.getCount(); i++) { onNextItem(i, cursor); } intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); intent.putExtra(Intent.EXTRA_INDEX, mDocumentLocation); intent.setClipData(mClipData); return intent; } private void onNextItem(int index, Cursor cursor) { cursor.moveToPosition(index); String mimeType = getCursorString(cursor, Document.COLUMN_MIME_TYPE); if (Document.MIME_TYPE_DIR.equals(mimeType)) { return; } String id = getCursorString(cursor, Document.COLUMN_DOCUMENT_ID); String authority = getCursorString(cursor, RootCursorWrapper.COLUMN_AUTHORITY); Uri uri = DocumentsContract.buildDocumentUri(authority, id); if (DEBUG) Log.d(TAG, "Including file[" + id + "] @ " + uri); if (id.equals(mDocument.documentId)) { if (DEBUG) Log.d(TAG, "Found starting point for QV. " + index); mDocumentLocation = index; } ClipData.Item item = new ClipData.Item(uri); if (mClipData == null) { mClipData = new ClipData( "URIs", new String[]{ClipDescription.MIMETYPE_TEXT_URILIST}, item); } else { mClipData.addItem(item); } } }