diff options
| -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 6ef43fa09..22c721dab 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 2a3b69c93..0f8f721e2 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 bbc804d5f..5cace19f4 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 000000000..498afc001 --- /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; + } +} |
