diff options
| author | 2016-01-27 17:36:51 +0900 | |
|---|---|---|
| committer | 2016-02-03 11:56:54 +0900 | |
| commit | a6120da1e37a4457bac58f8900bffa795dc8e7cb (patch) | |
| tree | 4f0ae9e38c275590345a5f699a031631f9ce92e8 | |
| parent | b8bcd19975e5b1de26297682d214f2f2c216e20b (diff) | |
Open zip files nicely from the Download app with Files app.
Bug: 26321218
Change-Id: I8a7a7e914d290ea1b6f424ee5fbd38a4b09c362d
5 files changed, 107 insertions, 22 deletions
diff --git a/packages/DocumentsUI/AndroidManifest.xml b/packages/DocumentsUI/AndroidManifest.xml index fa9ff0153c87..9ac929ba9b28 100644 --- a/packages/DocumentsUI/AndroidManifest.xml +++ b/packages/DocumentsUI/AndroidManifest.xml @@ -75,6 +75,19 @@ <category android:name="android.intent.category.DEFAULT" /> <data android:mimeType="vnd.android.document/root" /> </intent-filter> + <intent-filter> + <action android:name="android.intent.action.VIEW" /> + <category android:name="android.intent.category.DEFAULT" /> + <data android:mimeType="application/zip" + android:host="com.android.providers.downloads.documents" + android:scheme="content" /> + <data android:mimeType="application/x-zip" + android:host="com.android.providers.downloads.documents" + android:scheme="content" /> + <data android:mimeType="application/x-zip-compressed" + android:host="com.android.providers.downloads.documents" + android:scheme="content" /> + </intent-filter> </activity> <activity diff --git a/packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java b/packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java index 0fed6410b2cd..9dfe631d6e9b 100644 --- a/packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java +++ b/packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java @@ -541,7 +541,7 @@ public abstract class BaseActivity extends Activity implements SearchManagerList } } - private DocumentInfo getRootDocumentBlocking(RootInfo root) { + DocumentInfo getRootDocumentBlocking(RootInfo root) { try { final Uri uri = DocumentsContract.buildDocumentUri( root.authority, root.documentId); diff --git a/packages/DocumentsUI/src/com/android/documentsui/DownloadsActivity.java b/packages/DocumentsUI/src/com/android/documentsui/DownloadsActivity.java index b6ded6c3fbd7..5cc677c4f008 100644 --- a/packages/DocumentsUI/src/com/android/documentsui/DownloadsActivity.java +++ b/packages/DocumentsUI/src/com/android/documentsui/DownloadsActivity.java @@ -182,29 +182,25 @@ public class DownloadsActivity extends BaseActivity { @Override public void onDocumentPicked(DocumentInfo doc, SiblingProvider siblings) { - final FragmentManager fm = getFragmentManager(); - if (doc.isContainer()) { - openContainerDocument(doc); - } else { - // First try managing the document; we expect manager to filter - // based on authority, so we don't grant. - final Intent manage = new Intent(DocumentsContract.ACTION_MANAGE_DOCUMENT); - manage.setData(doc.derivedUri); + Preconditions.checkArgument(!doc.isDirectory()); + // First try managing the document; we expect manager to filter + // based on authority, so we don't grant. + final Intent manage = new Intent(DocumentsContract.ACTION_MANAGE_DOCUMENT); + manage.setData(doc.derivedUri); + + try { + startActivity(manage); + } catch (ActivityNotFoundException ex) { + // Fall back to viewing. + final Intent view = new Intent(Intent.ACTION_VIEW); + view.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); + view.setData(doc.derivedUri); try { - startActivity(manage); - } catch (ActivityNotFoundException ex) { - // Fall back to viewing - final Intent view = new Intent(Intent.ACTION_VIEW); - view.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); - view.setData(doc.derivedUri); - - try { - startActivity(view); - } catch (ActivityNotFoundException ex2) { - Snackbars.makeSnackbar(this, R.string.toast_no_application, Snackbar.LENGTH_SHORT) - .show(); - } + startActivity(view); + } catch (ActivityNotFoundException ex2) { + Snackbars.makeSnackbar(this, R.string.toast_no_application, Snackbar.LENGTH_SHORT) + .show(); } } } diff --git a/packages/DocumentsUI/src/com/android/documentsui/FilesActivity.java b/packages/DocumentsUI/src/com/android/documentsui/FilesActivity.java index f0df3a2ce823..59463bf2b087 100644 --- a/packages/DocumentsUI/src/com/android/documentsui/FilesActivity.java +++ b/packages/DocumentsUI/src/com/android/documentsui/FilesActivity.java @@ -30,6 +30,7 @@ import android.content.ContentResolver; import android.content.ContentValues; import android.content.Intent; import android.net.Uri; +import android.os.AsyncTask; import android.os.Bundle; import android.os.Parcelable; import android.provider.DocumentsContract; @@ -53,8 +54,10 @@ import com.android.documentsui.model.DurableUtils; import com.android.documentsui.model.RootInfo; import com.android.documentsui.services.FileOperationService; +import java.io.FileNotFoundException; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collection; import java.util.List; /** @@ -109,6 +112,10 @@ public class FilesActivity extends BaseActivity { if (DEBUG) Log.d(TAG, "Launching with non-empty stack."); checkState(uri == null || LauncherActivity.isLaunchUri(uri)); refreshCurrentRootAndDirectory(ANIM_NONE); + } else if (intent.getAction() == Intent.ACTION_VIEW) { + checkArgument(uri != null); + new OpenUriForViewTask().executeOnExecutor( + ProviderExecutor.forAuthority(uri.getAuthority()), uri); } else if (DocumentsContract.isRootUri(this, uri)) { if (DEBUG) Log.d(TAG, "Launching with root URI."); // If we've got a specific root to display, restore that root using a dedicated @@ -447,4 +454,44 @@ public class FilesActivity extends BaseActivity { setResult(Activity.RESULT_OK, intent); finish(); } + + /** + * Builds a stack for the specific Uris. Multi roots are not supported, as it's impossible + * to know which root to select. Also, the stack doesn't contain intermediate directories. + * It's primarly used for opening ZIP archives from Downloads app. + */ + final class OpenUriForViewTask extends AsyncTask<Uri, Void, Void> { + @Override + protected Void doInBackground(Uri... params) { + final Uri uri = params[0]; + + final RootsCache rootsCache = DocumentsApplication.getRootsCache(FilesActivity.this); + final String authority = uri.getAuthority(); + + final Collection<RootInfo> roots = + rootsCache.getRootsForAuthorityBlocking(authority); + if (roots.isEmpty()) { + Log.e(TAG, "Failed to find root for the requested Uri: " + uri); + return null; + } + + final RootInfo root = roots.iterator().next(); + mState.stack.root = root; + try { + mState.stack.add(DocumentInfo.fromUri(getContentResolver(), uri)); + } catch (FileNotFoundException e) { + Log.e(TAG, "Failed to resolve DocumentInfo from Uri: " + uri); + } + mState.stack.add(getRootDocumentBlocking(root)); + return null; + } + + @Override + protected void onPostExecute(Void result) { + if (isDestroyed()) { + return; + } + refreshCurrentRootAndDirectory(ANIM_NONE); + } + } } diff --git a/packages/DocumentsUI/src/com/android/documentsui/RootsCache.java b/packages/DocumentsUI/src/com/android/documentsui/RootsCache.java index 21e756623bdd..0a280abadc47 100644 --- a/packages/DocumentsUI/src/com/android/documentsui/RootsCache.java +++ b/packages/DocumentsUI/src/com/android/documentsui/RootsCache.java @@ -48,6 +48,7 @@ import libcore.io.IoUtils; import java.util.ArrayList; import java.util.Collection; +import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Objects; @@ -159,6 +160,21 @@ public class RootsCache { } } + /** + * Load roots from a stopped authority. Normal {@link UpdateTask} passes + * ignore stopped applications. + */ + private void loadStoppedAuthority(String authority) { + final ContentResolver resolver = mContext.getContentResolver(); + synchronized (mLock) { + if (DEBUG) { + Log.d(TAG, "Loading stopped authority " + authority); + } + mRoots.putAll(authority, loadRootsForAuthority(resolver, authority)); + mStoppedAuthorities.remove(authority); + } + } + private class UpdateTask extends AsyncTask<Void, Void, Void> { private final String mFilterPackage; @@ -360,6 +376,19 @@ public class RootsCache { } } + /** + * Returns a list of roots for the specified authority. If not found, then + * an empty list is returned. + */ + public Collection<RootInfo> getRootsForAuthorityBlocking(String authority) { + waitForFirstLoad(); + loadStoppedAuthority(authority); + synchronized (mLock) { + final Collection<RootInfo> roots = mRoots.get(authority); + return roots != null ? roots : Collections.<RootInfo>emptyList(); + } + } + public void setOnCacheUpdateListener(OnCacheUpdateListener cacheUpdateListener) { mCacheUpdateListener = cacheUpdateListener; } |