diff options
author | Leon Scroggins <scroggo@google.com> | 2010-01-26 14:15:01 -0500 |
---|---|---|
committer | Leon Scroggins <scroggo@google.com> | 2010-02-04 16:37:55 -0500 |
commit | fedc493cd810fbd4385efbd647ee70852870988f (patch) | |
tree | 7a32e6e925b30efe6c440f3f4b82c1bccd914888 | |
parent | c38909b6156331f8d739e0d6d7a9f7a0fae3d17c (diff) | |
download | packages_apps_Browser-fedc493cd810fbd4385efbd647ee70852870988f.zip packages_apps_Browser-fedc493cd810fbd4385efbd647ee70852870988f.tar.gz packages_apps_Browser-fedc493cd810fbd4385efbd647ee70852870988f.tar.bz2 |
Launch intents to open/delete downloads, and handle them in the browser.
Initial work for http://b/issue?id=2384554 : showing all downloads in the
browser. On the BrowserDownloadPage, no longer rely on the filename,
since once the Browser shows downloads from other applications, the
filenames for those downloads will not be available, and this way
all downloads are handled the same.
Other applications which download files will need to handle the same
Intents as OpenDownloadReceiver in order to open/delete them from
the BrowserDownloadPage.
OpenDownloadReceiver is also a necessary step towards moving the
BrowserDownloadPage into its own application, if we ultimately
decide to do that.
-rw-r--r-- | AndroidManifest.xml | 8 | ||||
-rw-r--r-- | src/com/android/browser/BrowserDownloadAdapter.java | 11 | ||||
-rw-r--r-- | src/com/android/browser/BrowserDownloadPage.java | 99 | ||||
-rw-r--r-- | src/com/android/browser/OpenDownloadReceiver.java | 99 |
4 files changed, 136 insertions, 81 deletions
diff --git a/AndroidManifest.xml b/AndroidManifest.xml index 6ef43fa..22c721d 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -33,6 +33,7 @@ <uses-permission android:name="com.android.browser.permission.READ_HISTORY_BOOKMARKS"/> <uses-permission android:name="com.android.browser.permission.WRITE_HISTORY_BOOKMARKS"/> <uses-permission android:name="android.permission.BACKUP_DATA" /> + <uses-permission android:name="android.permission.SEND_DOWNLOAD_COMPLETED_INTENTS" /> <application android:name="Browser" android:label="@string/application_name" @@ -194,6 +195,13 @@ <!-- Makes .BrowserActivity the search target for any activity in Browser --> <meta-data android:name="android.app.default_searchable" android:value=".BrowserActivity" /> + <receiver android:name=".OpenDownloadReceiver"> + <intent-filter> + <action android:name="android.intent.action.DOWNLOAD_NOTIFICATION_CLICKED"/> + <action android:name="android.intent.action.DELETE"/> + <data android:scheme="content" android:mimeType="vnd.android.cursor.item/download"/> + </intent-filter> + </receiver> </application> </manifest> diff --git a/src/com/android/browser/BrowserDownloadAdapter.java b/src/com/android/browser/BrowserDownloadAdapter.java index 2a3b69c..0f8f721 100644 --- a/src/com/android/browser/BrowserDownloadAdapter.java +++ b/src/com/android/browser/BrowserDownloadAdapter.java @@ -47,7 +47,6 @@ import java.util.List; */ public class BrowserDownloadAdapter extends DateSortedExpandableListAdapter { - private int mFilenameColumnId; private int mTitleColumnId; private int mDescColumnId; private int mStatusColumnId; @@ -58,7 +57,6 @@ public class BrowserDownloadAdapter extends DateSortedExpandableListAdapter { public BrowserDownloadAdapter(Context context, Cursor c, int index) { super(context, c, index); - mFilenameColumnId = c.getColumnIndexOrThrow(Downloads.Impl._DATA); mTitleColumnId = c.getColumnIndexOrThrow(Downloads.Impl.COLUMN_TITLE); mDescColumnId = c.getColumnIndexOrThrow(Downloads.Impl.COLUMN_DESCRIPTION); mStatusColumnId = c.getColumnIndexOrThrow(Downloads.Impl.COLUMN_STATUS); @@ -112,14 +110,7 @@ public class BrowserDownloadAdapter extends DateSortedExpandableListAdapter { TextView tv = (TextView) convertView.findViewById(R.id.download_title); String title = getString(mTitleColumnId); if (title == null) { - String fullFilename = getString(mFilenameColumnId); - if (fullFilename == null) { - title = r.getString(R.string.download_unknown_filename); - } else { - // We have a filename, so we can build a title from that - title = Downloads.Impl.createTitleFromFilename(context, fullFilename, - getLong(0)); - } + title = r.getString(R.string.download_unknown_filename); } tv.setText(title); diff --git a/src/com/android/browser/BrowserDownloadPage.java b/src/com/android/browser/BrowserDownloadPage.java index bbc804d..5cace19 100644 --- a/src/com/android/browser/BrowserDownloadPage.java +++ b/src/com/android/browser/BrowserDownloadPage.java @@ -26,11 +26,9 @@ import android.content.ContentUris; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import android.database.Cursor; -import android.database.DatabaseUtils; import android.net.Uri; import android.os.Bundle; import android.provider.Downloads; -import android.provider.MediaStore; import android.view.ContextMenu; import android.view.ContextMenu.ContextMenuInfo; import android.view.LayoutInflater; @@ -68,11 +66,14 @@ public class BrowserDownloadPage extends ExpandableListActivity { mListView = (ExpandableListView) findViewById(android.R.id.list); mListView.setEmptyView(findViewById(R.id.empty)); mDownloadCursor = managedQuery(Downloads.Impl.CONTENT_URI, - new String [] {"_id", Downloads.Impl.COLUMN_TITLE, Downloads.Impl.COLUMN_STATUS, - Downloads.Impl.COLUMN_TOTAL_BYTES, Downloads.Impl.COLUMN_CURRENT_BYTES, - Downloads.Impl._DATA, Downloads.Impl.COLUMN_DESCRIPTION, - Downloads.Impl.COLUMN_MIME_TYPE, Downloads.Impl.COLUMN_LAST_MODIFICATION, - Downloads.Impl.COLUMN_VISIBILITY}, + new String [] {Downloads.Impl._ID, Downloads.Impl.COLUMN_TITLE, + Downloads.Impl.COLUMN_STATUS, Downloads.Impl.COLUMN_TOTAL_BYTES, + Downloads.Impl.COLUMN_CURRENT_BYTES, + Downloads.Impl.COLUMN_DESCRIPTION, + Downloads.Impl.COLUMN_NOTIFICATION_PACKAGE, + Downloads.Impl.COLUMN_LAST_MODIFICATION, + Downloads.Impl.COLUMN_VISIBILITY, + Downloads.Impl.COLUMN_MIME_TYPE}, null, Downloads.Impl.COLUMN_LAST_MODIFICATION + " DESC"); // only attach everything to the listbox if we can access @@ -108,7 +109,7 @@ public class BrowserDownloadPage extends ExpandableListActivity { } } } - + @Override public boolean onCreateOptionsMenu(Menu menu) { if (mDownloadCursor != null) { @@ -144,28 +145,6 @@ public class BrowserDownloadPage extends ExpandableListActivity { Downloads.Impl.CONTENT_URI, id), null, null); } - /** - * Remove the file from the SD card - * @param filename Name of the file to delete. - * @param mimetype Mimetype of the file to delete. - * @return boolean True on success, false on failure. - */ - private boolean deleteFile(String filename, String mimetype) { - Uri uri; - if (mimetype.startsWith("image")) { - uri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI; - } else if (mimetype.startsWith("audio")) { - uri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI; - } else if (mimetype.startsWith("video")) { - uri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI; - } else { - File file = new File(filename); - return file.delete(); - } - return getContentResolver().delete(uri, MediaStore.MediaColumns.DATA - + " = " + DatabaseUtils.sqlEscapeString(filename), null) > 0; - } - @Override public boolean onContextItemSelected(MenuItem item) { if (!mDownloadAdapter.moveCursorToPackedChildPosition( @@ -175,31 +154,20 @@ public class BrowserDownloadPage extends ExpandableListActivity { switch (item.getItemId()) { case R.id.download_menu_open: hideCompletedDownload(); - openCurrentDownload(); + openOrDeleteCurrentDownload(false); return true; case R.id.download_menu_delete: - int filenameColumnId = - mDownloadCursor.getColumnIndexOrThrow(Downloads.Impl._DATA); - final String filename = mDownloadCursor.getString( - filenameColumnId); - int mimetypeColumnId = mDownloadCursor.getColumnIndexOrThrow( - Downloads.Impl.COLUMN_MIME_TYPE); - final String mimetype = mDownloadCursor.getString( - mimetypeColumnId); - final long id = mDownloadCursor.getLong(mIdColumnId); new AlertDialog.Builder(this) .setTitle(R.string.download_delete_file) .setIcon(android.R.drawable.ic_dialog_alert) - .setMessage(filename) + .setMessage(mDownloadCursor.getString(mTitleColumnId)) .setNegativeButton(R.string.cancel, null) .setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int whichButton) { - if (deleteFile(filename, mimetype)) { - clearFromDownloads(id); - } + openOrDeleteCurrentDownload(true); } }) .show(); @@ -392,33 +360,22 @@ public class BrowserDownloadPage extends ExpandableListActivity { } /** - * Open the content where the download db cursor currently is + * Open or delete content where the download db cursor currently is. Sends + * an Intent to perform the action. + * @param delete If true, delete the content. Otherwise open it. */ - private void openCurrentDownload() { - int filenameColumnId = - mDownloadCursor.getColumnIndexOrThrow(Downloads.Impl._DATA); - String filename = mDownloadCursor.getString(filenameColumnId); - int mimetypeColumnId = - mDownloadCursor.getColumnIndexOrThrow(Downloads.Impl.COLUMN_MIME_TYPE); - String mimetype = mDownloadCursor.getString(mimetypeColumnId); - Uri path = Uri.parse(filename); - // If there is no scheme, then it must be a file - if (path.getScheme() == null) { - path = Uri.fromFile(new File(filename)); - } - Intent intent = new Intent(Intent.ACTION_VIEW); - intent.setDataAndType(path, mimetype); - intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); - try { - startActivity(intent); - } catch (ActivityNotFoundException ex) { - new AlertDialog.Builder(this) - .setTitle(R.string.download_no_application_title) - .setIcon(R.drawable.ssl_icon) - .setMessage(R.string.download_no_application) - .setPositiveButton(R.string.ok, null) - .show(); - } + private void openOrDeleteCurrentDownload(boolean delete) { + int packageColumnId = mDownloadCursor.getColumnIndexOrThrow( + Downloads.Impl.COLUMN_NOTIFICATION_PACKAGE); + String packageName = mDownloadCursor.getString(packageColumnId); + Intent intent = new Intent(delete ? Intent.ACTION_DELETE + : Downloads.Impl.ACTION_NOTIFICATION_CLICKED); + Uri contentUri = ContentUris.withAppendedId( + Downloads.Impl.CONTENT_URI, + mDownloadCursor.getLong(mIdColumnId)); + intent.setData(contentUri); + intent.setPackage(packageName); + sendBroadcast(intent); } @Override @@ -433,7 +390,7 @@ public class BrowserDownloadPage extends ExpandableListActivity { int status = mDownloadCursor.getInt(mStatusColumnId); if (Downloads.Impl.isStatusSuccess(status)) { // Open it if it downloaded successfully - openCurrentDownload(); + openOrDeleteCurrentDownload(false); } else { // Check to see if there is an error. checkStatus(id); diff --git a/src/com/android/browser/OpenDownloadReceiver.java b/src/com/android/browser/OpenDownloadReceiver.java new file mode 100644 index 0000000..498afc0 --- /dev/null +++ b/src/com/android/browser/OpenDownloadReceiver.java @@ -0,0 +1,99 @@ +/* + * Copyright (C) 2010 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.browser; + +import android.content.ActivityNotFoundException; +import android.content.BroadcastReceiver; +import android.content.ContentResolver; +import android.content.Context; +import android.content.Intent; +import android.database.Cursor; +import android.database.DatabaseUtils; +import android.net.Uri; +import android.provider.Downloads; +import android.provider.MediaStore; +import android.widget.Toast; + +import java.io.File; + +/** + * This {@link BroadcastReceiver} handles {@link Intent}s to open and delete + * files downloaded by the Browser. + */ +public class OpenDownloadReceiver extends BroadcastReceiver { + public void onReceive(Context context, Intent intent) { + ContentResolver cr = context.getContentResolver(); + Uri data = intent.getData(); + Cursor cursor = cr.query(data, + new String[] { Downloads.Impl._ID, Downloads.Impl._DATA, + Downloads.Impl.COLUMN_MIME_TYPE }, null, null, null); + if (cursor.moveToFirst()) { + String filename = cursor.getString(1); + String mimetype = cursor.getString(2); + String action = intent.getAction(); + if (Downloads.ACTION_NOTIFICATION_CLICKED.equals(action)) { + Intent launchIntent = new Intent(Intent.ACTION_VIEW); + Uri path = Uri.parse(filename); + // If there is no scheme, then it must be a file + if (path.getScheme() == null) { + path = Uri.fromFile(new File(filename)); + } + launchIntent.setDataAndType(path, mimetype); + launchIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + try { + context.startActivity(launchIntent); + } catch (ActivityNotFoundException ex) { + Toast.makeText(context, + R.string.download_no_application_title, + Toast.LENGTH_LONG).show(); + } + } else if (Intent.ACTION_DELETE.equals(action)) { + if (deleteFile(cr, filename, mimetype)) { + cr.delete(data, null, null); + } + } + } + cursor.close(); + } + + /** + * Remove the file from the SD card + * @param cr ContentResolver used to delete the file. + * @param filename Name of the file to delete. + * @param mimetype Mimetype of the file to delete. + * @return boolean True on success, false on failure. + */ + // FIXME: Once there are receivers in other packages to delete downloaded + // files, this should be moved to a common place so mutiple packages can + // share the code. + private boolean deleteFile(ContentResolver cr, String filename, + String mimetype) { + Uri uri; + if (mimetype.startsWith("image")) { + uri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI; + } else if (mimetype.startsWith("audio")) { + uri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI; + } else if (mimetype.startsWith("video")) { + uri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI; + } else { + File file = new File(filename); + return file.delete(); + } + return cr.delete(uri, MediaStore.MediaColumns.DATA + " = " + + DatabaseUtils.sqlEscapeString(filename), null) > 0; + } +} |