diff options
-rw-r--r-- | AndroidManifest.xml | 15 | ||||
-rw-r--r-- | res/values/strings.xml | 3 | ||||
-rw-r--r-- | src/com/android/providers/downloads/Constants.java | 2 | ||||
-rw-r--r-- | src/com/android/providers/downloads/DownloadStorageProvider.java | 30 | ||||
-rw-r--r-- | src/com/android/providers/downloads/TrampolineActivity.java | 37 | ||||
-rw-r--r-- | ui/AndroidManifest.xml | 14 | ||||
-rw-r--r-- | ui/src/com/android/providers/downloads/ui/DownloadList.java | 6 | ||||
-rw-r--r-- | ui/src/com/android/providers/downloads/ui/TrampolineActivity.java | 225 |
8 files changed, 263 insertions, 69 deletions
diff --git a/AndroidManifest.xml b/AndroidManifest.xml index 398f8f4c..49f039ef 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -106,20 +106,5 @@ <activity android:name=".SizeLimitActivity" android:launchMode="singleTask" android:theme="@style/Theme.Translucent"/> - - <!-- PackageInstaller really wants raw files --> - <activity - android:name=".TrampolineActivity" - android:theme="@android:style/Theme.NoDisplay" - android:permission="android.permission.MANAGE_DOCUMENTS"> - <intent-filter> - <action android:name="android.intent.action.VIEW" /> - <category android:name="android.intent.category.DEFAULT" /> - <data - android:scheme="content" - android:host="com.android.providers.downloads.documents" - android:mimeType="application/vnd.android.package-archive" /> - </intent-filter> - </activity> </application> </manifest> diff --git a/res/values/strings.xml b/res/values/strings.xml index 620e3fad..c5712194 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -226,4 +226,7 @@ an individual item in the download list. [CHAR LIMIT=24] --> <string name="download_error">Unsuccessful</string> + <!-- Representation of download progress percentage when running. [CHAR LIMIT=24] --> + <string name="download_running_percent">In progress, <xliff:g id="number">%d</xliff:g><xliff:g id="percent">%%</xliff:g></string> + </resources> diff --git a/src/com/android/providers/downloads/Constants.java b/src/com/android/providers/downloads/Constants.java index e33a6362..89210a25 100644 --- a/src/com/android/providers/downloads/Constants.java +++ b/src/com/android/providers/downloads/Constants.java @@ -176,5 +176,5 @@ public class Constants { public static final boolean LOGVV = LOCAL_LOGVV && LOGV; public static final String STORAGE_AUTHORITY = "com.android.providers.downloads.documents"; - public static final String STORAGE_DOC_ID_ROOT = "downloads"; + public static final String STORAGE_ROOT_ID = "downloads"; } diff --git a/src/com/android/providers/downloads/DownloadStorageProvider.java b/src/com/android/providers/downloads/DownloadStorageProvider.java index 04cbf090..f1cd8fa9 100644 --- a/src/com/android/providers/downloads/DownloadStorageProvider.java +++ b/src/com/android/providers/downloads/DownloadStorageProvider.java @@ -41,7 +41,7 @@ import java.io.FileNotFoundException; * contents. */ public class DownloadStorageProvider extends DocumentsProvider { - private static final String DOC_ID_ROOT = Constants.STORAGE_DOC_ID_ROOT; + private static final String DOC_ID_ROOT = Constants.STORAGE_ROOT_ID; private static final String[] DEFAULT_ROOT_PROJECTION = new String[] { Root.COLUMN_ROOT_ID, Root.COLUMN_ROOT_TYPE, Root.COLUMN_FLAGS, Root.COLUMN_ICON, @@ -51,7 +51,8 @@ public class DownloadStorageProvider extends DocumentsProvider { 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, + Document.COLUMN_SUMMARY, Document.COLUMN_LAST_MODIFIED, Document.COLUMN_FLAGS, + Document.COLUMN_SIZE, }; private DownloadManager mDm; @@ -214,33 +215,35 @@ public class DownloadStorageProvider extends DocumentsProvider { if (mimeType == null) { mimeType = "application/octet-stream"; } - Long size = null; + Long size = cursor.getLong( + cursor.getColumnIndexOrThrow(DownloadManager.COLUMN_TOTAL_SIZE_BYTES)); + if (size == -1) { + size = null; + } final int status = cursor.getInt( cursor.getColumnIndexOrThrow(DownloadManager.COLUMN_STATUS)); switch (status) { case DownloadManager.STATUS_SUCCESSFUL: - size = cursor.getLong( - cursor.getColumnIndexOrThrow(DownloadManager.COLUMN_TOTAL_SIZE_BYTES)); - if (size == -1) { - size = null; - } break; case DownloadManager.STATUS_PAUSED: - mimeType = null; summary = getContext().getString(R.string.download_queued); break; case DownloadManager.STATUS_PENDING: - mimeType = null; summary = getContext().getString(R.string.download_queued); break; case DownloadManager.STATUS_RUNNING: - mimeType = null; - summary = getContext().getString(R.string.download_running); + final long progress = cursor.getLong(cursor.getColumnIndexOrThrow( + DownloadManager.COLUMN_BYTES_DOWNLOADED_SO_FAR)); + if (size != null) { + final long percent = progress * 100 / size; + summary = getContext().getString(R.string.download_running_percent, percent); + } else { + summary = getContext().getString(R.string.download_running); + } break; case DownloadManager.STATUS_FAILED: default: - mimeType = null; summary = getContext().getString(R.string.download_error); break; } @@ -256,6 +259,7 @@ public class DownloadStorageProvider extends DocumentsProvider { final RowBuilder row = result.newRow(); row.offer(Document.COLUMN_DOCUMENT_ID, docId); row.offer(Document.COLUMN_DISPLAY_NAME, displayName); + row.offer(Document.COLUMN_SUMMARY, summary); row.offer(Document.COLUMN_SIZE, size); row.offer(Document.COLUMN_MIME_TYPE, mimeType); row.offer(Document.COLUMN_LAST_MODIFIED, lastModified); diff --git a/src/com/android/providers/downloads/TrampolineActivity.java b/src/com/android/providers/downloads/TrampolineActivity.java deleted file mode 100644 index 0f494cff..00000000 --- a/src/com/android/providers/downloads/TrampolineActivity.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * 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.providers.downloads; - -import android.app.Activity; -import android.content.ContentUris; -import android.content.Intent; -import android.os.Bundle; - -/** - * PackageInstaller really wants raw files. - */ -public class TrampolineActivity extends Activity { - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - final long id = ContentUris.parseId(getIntent().getData()); - final Intent intent = OpenHelper.buildViewIntent(this, id); - startActivity(intent); - finish(); - } -} diff --git a/ui/AndroidManifest.xml b/ui/AndroidManifest.xml index 61669154..93fb5223 100644 --- a/ui/AndroidManifest.xml +++ b/ui/AndroidManifest.xml @@ -25,5 +25,19 @@ <category android:name="android.intent.category.DEFAULT" /> </intent-filter> </activity> + + <activity + android:name=".TrampolineActivity" + android:theme="@android:style/Theme.NoDisplay" + android:permission="android.permission.MANAGE_DOCUMENTS"> + <intent-filter> + <action android:name="android.provider.action.MANAGE_DOCUMENT" /> + <category android:name="android.intent.category.DEFAULT" /> + <data + android:scheme="content" + android:host="com.android.providers.downloads.documents" + android:mimeType="*/*" /> + </intent-filter> + </activity> </application> </manifest> diff --git a/ui/src/com/android/providers/downloads/ui/DownloadList.java b/ui/src/com/android/providers/downloads/ui/DownloadList.java index 443491a9..991d70b6 100644 --- a/ui/src/com/android/providers/downloads/ui/DownloadList.java +++ b/ui/src/com/android/providers/downloads/ui/DownloadList.java @@ -151,9 +151,9 @@ public class DownloadList extends Activity { super.onCreate(icicle); // Trampoline over to new management UI - final Intent intent = new Intent(DocumentsContract.ACTION_MANAGE_DOCUMENTS); - intent.setData(DocumentsContract.buildDocumentUri( - Constants.STORAGE_AUTHORITY, Constants.STORAGE_DOC_ID_ROOT)); + final Intent intent = new Intent(DocumentsContract.ACTION_MANAGE_ROOT); + intent.setData(DocumentsContract.buildRootUri( + Constants.STORAGE_AUTHORITY, Constants.STORAGE_ROOT_ID)); startActivity(intent); finish(); } diff --git a/ui/src/com/android/providers/downloads/ui/TrampolineActivity.java b/ui/src/com/android/providers/downloads/ui/TrampolineActivity.java new file mode 100644 index 00000000..e9cc17ef --- /dev/null +++ b/ui/src/com/android/providers/downloads/ui/TrampolineActivity.java @@ -0,0 +1,225 @@ +/* + * 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.providers.downloads.ui; + +import android.app.Activity; +import android.app.AlertDialog; +import android.app.Dialog; +import android.app.DialogFragment; +import android.app.DownloadManager; +import android.app.DownloadManager.Query; +import android.app.FragmentManager; +import android.content.ContentUris; +import android.content.Context; +import android.content.DialogInterface; +import android.content.Intent; +import android.database.Cursor; +import android.os.Bundle; +import android.util.Log; +import android.widget.Toast; + +import com.android.providers.downloads.Constants; +import com.android.providers.downloads.OpenHelper; + +import libcore.io.IoUtils; + +/** + * Intercept all download clicks to provide special behavior. For example, + * PackageInstaller really wants raw file paths. + */ +public class TrampolineActivity extends Activity { + private static final String TAG_PAUSED = "paused"; + private static final String TAG_FAILED = "failed"; + + private static final String KEY_ID = "id"; + private static final String KEY_REASON = "reason"; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + final long id = ContentUris.parseId(getIntent().getData()); + + final DownloadManager dm = (DownloadManager) getSystemService(Context.DOWNLOAD_SERVICE); + dm.setAccessAllDownloads(true); + + final int status; + final int reason; + + final Cursor cursor = dm.query(new Query().setFilterById(id)); + try { + if (cursor.moveToFirst()) { + status = cursor.getInt(cursor.getColumnIndexOrThrow(DownloadManager.COLUMN_STATUS)); + reason = cursor.getInt(cursor.getColumnIndexOrThrow(DownloadManager.COLUMN_REASON)); + } else { + Toast.makeText(this, R.string.dialog_file_missing_body, Toast.LENGTH_SHORT).show(); + finish(); + return; + } + } finally { + IoUtils.closeQuietly(cursor); + } + + Log.d(Constants.TAG, "Found " + id + " with status " + status + ", reason " + reason); + switch (status) { + case DownloadManager.STATUS_PENDING: + case DownloadManager.STATUS_RUNNING: + sendRunningDownloadClickedBroadcast(id); + finish(); + break; + + case DownloadManager.STATUS_PAUSED: + if (reason == DownloadManager.PAUSED_QUEUED_FOR_WIFI) { + PausedDialogFragment.show(getFragmentManager(), id); + } else { + sendRunningDownloadClickedBroadcast(id); + finish(); + } + break; + + case DownloadManager.STATUS_SUCCESSFUL: + final Intent intent = OpenHelper.buildViewIntent(this, id); + startActivity(intent); + finish(); + break; + + case DownloadManager.STATUS_FAILED: + FailedDialogFragment.show(getFragmentManager(), id, reason); + break; + } + } + + private void sendRunningDownloadClickedBroadcast(long id) { + final Intent intent = new Intent(Constants.ACTION_LIST); + intent.setPackage(Constants.PROVIDER_PACKAGE_NAME); + intent.putExtra(DownloadManager.EXTRA_NOTIFICATION_CLICK_DOWNLOAD_IDS, new long[] { id }); + sendBroadcast(intent); + } + + public static class PausedDialogFragment extends DialogFragment { + public static void show(FragmentManager fm, long id) { + final PausedDialogFragment dialog = new PausedDialogFragment(); + final Bundle args = new Bundle(); + args.putLong(KEY_ID, id); + dialog.setArguments(args); + dialog.show(fm, TAG_PAUSED); + } + + @Override + public Dialog onCreateDialog(Bundle savedInstanceState) { + final Context context = getActivity(); + + final DownloadManager dm = (DownloadManager) context.getSystemService( + Context.DOWNLOAD_SERVICE); + dm.setAccessAllDownloads(true); + + final long id = getArguments().getLong(KEY_ID); + + final AlertDialog.Builder builder = new AlertDialog.Builder( + context, AlertDialog.THEME_HOLO_LIGHT); + builder.setTitle(R.string.dialog_title_queued_body); + builder.setMessage(R.string.dialog_queued_body); + + builder.setPositiveButton(R.string.keep_queued_download, null); + + builder.setNegativeButton( + R.string.remove_download, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + dm.remove(id); + } + }); + + return builder.create(); + } + + @Override + public void onDismiss(DialogInterface dialog) { + super.onDismiss(dialog); + getActivity().finish(); + } + } + + public static class FailedDialogFragment extends DialogFragment { + public static void show(FragmentManager fm, long id, int reason) { + final FailedDialogFragment dialog = new FailedDialogFragment(); + final Bundle args = new Bundle(); + args.putLong(KEY_ID, id); + args.putInt(KEY_REASON, reason); + dialog.setArguments(args); + dialog.show(fm, TAG_FAILED); + } + + @Override + public Dialog onCreateDialog(Bundle savedInstanceState) { + final Context context = getActivity(); + + final DownloadManager dm = (DownloadManager) context.getSystemService( + Context.DOWNLOAD_SERVICE); + dm.setAccessAllDownloads(true); + + final long id = getArguments().getLong(KEY_ID); + final int reason = getArguments().getInt(KEY_REASON); + + final AlertDialog.Builder builder = new AlertDialog.Builder( + context, AlertDialog.THEME_HOLO_LIGHT); + builder.setTitle(R.string.dialog_title_not_available); + + final String message; + switch (reason) { + case DownloadManager.ERROR_FILE_ALREADY_EXISTS: + builder.setMessage(R.string.dialog_file_already_exists); + break; + case DownloadManager.ERROR_INSUFFICIENT_SPACE: + builder.setMessage(R.string.dialog_insufficient_space_on_external); + break; + case DownloadManager.ERROR_DEVICE_NOT_FOUND: + builder.setMessage(R.string.dialog_media_not_found); + break; + case DownloadManager.ERROR_CANNOT_RESUME: + builder.setMessage(R.string.dialog_cannot_resume); + break; + default: + builder.setMessage(R.string.dialog_failed_body); + } + + builder.setNegativeButton( + R.string.delete_download, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + dm.remove(id); + } + }); + + builder.setPositiveButton( + R.string.retry_download, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + dm.restartDownload(id); + } + }); + + return builder.create(); + } + + @Override + public void onDismiss(DialogInterface dialog) { + super.onDismiss(dialog); + getActivity().finish(); + } + } +} |