blob: e4723148366f09a580c6aa44234b9b80bf3429f6 [file] [log] [blame]
The Android Open Source Project0c908882009-03-03 19:32:16 -08001/*
2 * Copyright (C) 2007 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.browser;
18
The Android Open Source Project0c908882009-03-03 19:32:16 -080019import android.app.AlertDialog;
Leon Scroggins24837452010-01-13 13:43:35 -050020import android.app.ExpandableListActivity;
The Android Open Source Project0c908882009-03-03 19:32:16 -080021import android.content.ActivityNotFoundException;
22import android.content.ContentValues;
23import android.content.DialogInterface;
24import android.content.Intent;
25import android.content.ContentUris;
26import android.content.pm.PackageManager;
27import android.content.pm.ResolveInfo;
Leon Scrogginsd080b182010-02-26 14:16:41 -050028import android.database.ContentObserver;
The Android Open Source Project0c908882009-03-03 19:32:16 -080029import android.database.Cursor;
30import android.net.Uri;
31import android.os.Bundle;
Leon Scrogginsd080b182010-02-26 14:16:41 -050032import android.os.Handler;
The Android Open Source Project0c908882009-03-03 19:32:16 -080033import android.provider.Downloads;
34import android.view.ContextMenu;
35import android.view.ContextMenu.ContextMenuInfo;
36import android.view.LayoutInflater;
37import android.view.Menu;
38import android.view.MenuItem;
39import android.view.MenuInflater;
40import android.view.View;
41import android.view.ViewGroup.LayoutParams;
42import android.widget.AdapterView;
Leon Scroggins24837452010-01-13 13:43:35 -050043import android.widget.ExpandableListView;
The Android Open Source Project0c908882009-03-03 19:32:16 -080044
45import java.io.File;
46import java.util.List;
47
48/**
49 * View showing the user's current browser downloads
50 */
Leon Scroggins24837452010-01-13 13:43:35 -050051public class BrowserDownloadPage extends ExpandableListActivity {
Leon Scroggins24837452010-01-13 13:43:35 -050052 private ExpandableListView mListView;
The Android Open Source Project0c908882009-03-03 19:32:16 -080053 private Cursor mDownloadCursor;
54 private BrowserDownloadAdapter mDownloadAdapter;
55 private int mStatusColumnId;
56 private int mIdColumnId;
57 private int mTitleColumnId;
Leon Scroggins24837452010-01-13 13:43:35 -050058 private long mContextMenuPosition;
Leon Scrogginsd080b182010-02-26 14:16:41 -050059 // Used to update the ContextMenu if an item is being downloaded and the
60 // user opens the ContextMenu.
61 private ContentObserver mContentObserver;
62 // Only meaningful while a ContentObserver is registered. The ContextMenu
63 // will be reopened on this View.
64 private View mSelectedView;
65
The Android Open Source Project0c908882009-03-03 19:32:16 -080066 @Override
67 public void onCreate(Bundle icicle) {
68 super.onCreate(icicle);
69 setContentView(R.layout.browser_downloads_page);
70
71 setTitle(getText(R.string.download_title));
72
Leon Scroggins24837452010-01-13 13:43:35 -050073 mListView = (ExpandableListView) findViewById(android.R.id.list);
Mihai Preda83817df2009-04-28 14:24:47 +020074 mListView.setEmptyView(findViewById(R.id.empty));
Jean-Baptiste Queru1e5bad92010-01-14 16:09:03 -080075 mDownloadCursor = managedQuery(Downloads.Impl.CONTENT_URI,
Leon Scrogginsfedc4932010-01-26 14:15:01 -050076 new String [] {Downloads.Impl._ID, Downloads.Impl.COLUMN_TITLE,
77 Downloads.Impl.COLUMN_STATUS, Downloads.Impl.COLUMN_TOTAL_BYTES,
78 Downloads.Impl.COLUMN_CURRENT_BYTES,
79 Downloads.Impl.COLUMN_DESCRIPTION,
80 Downloads.Impl.COLUMN_NOTIFICATION_PACKAGE,
81 Downloads.Impl.COLUMN_LAST_MODIFICATION,
82 Downloads.Impl.COLUMN_VISIBILITY,
83 Downloads.Impl.COLUMN_MIME_TYPE},
Jean-Baptiste Queru1e5bad92010-01-14 16:09:03 -080084 null, Downloads.Impl.COLUMN_LAST_MODIFICATION + " DESC");
The Android Open Source Project0c908882009-03-03 19:32:16 -080085
86 // only attach everything to the listbox if we can access
87 // the download database. Otherwise, just show it empty
88 if (mDownloadCursor != null) {
89 mStatusColumnId =
Jean-Baptiste Queru1e5bad92010-01-14 16:09:03 -080090 mDownloadCursor.getColumnIndexOrThrow(Downloads.Impl.COLUMN_STATUS);
The Android Open Source Project0c908882009-03-03 19:32:16 -080091 mIdColumnId =
Jean-Baptiste Queru1e5bad92010-01-14 16:09:03 -080092 mDownloadCursor.getColumnIndexOrThrow(Downloads.Impl._ID);
The Android Open Source Project0c908882009-03-03 19:32:16 -080093 mTitleColumnId =
Jean-Baptiste Queru1e5bad92010-01-14 16:09:03 -080094 mDownloadCursor.getColumnIndexOrThrow(Downloads.Impl.COLUMN_TITLE);
The Android Open Source Project0c908882009-03-03 19:32:16 -080095
96 // Create a list "controller" for the data
97 mDownloadAdapter = new BrowserDownloadAdapter(this,
Leon Scroggins24837452010-01-13 13:43:35 -050098 mDownloadCursor, mDownloadCursor.getColumnIndexOrThrow(
Jean-Baptiste Queru1e5bad92010-01-14 16:09:03 -080099 Downloads.Impl.COLUMN_LAST_MODIFICATION));
Mihai Preda83817df2009-04-28 14:24:47 +0200100
Leon Scroggins24837452010-01-13 13:43:35 -0500101 setListAdapter(mDownloadAdapter);
The Android Open Source Project0c908882009-03-03 19:32:16 -0800102 mListView.setScrollBarStyle(View.SCROLLBARS_INSIDE_INSET);
103 mListView.setOnCreateContextMenuListener(this);
Leon Scroggins24837452010-01-13 13:43:35 -0500104
The Android Open Source Project0c908882009-03-03 19:32:16 -0800105 Intent intent = getIntent();
Leon Scroggins24837452010-01-13 13:43:35 -0500106 final int groupToShow = intent == null || intent.getData() == null
107 ? 0 : checkStatus(ContentUris.parseId(intent.getData()));
108 if (mDownloadAdapter.getGroupCount() > groupToShow) {
109 mListView.post(new Runnable() {
110 public void run() {
111 if (mDownloadAdapter.getGroupCount() > groupToShow) {
112 mListView.expandGroup(groupToShow);
113 }
114 }
115 });
The Android Open Source Project0c908882009-03-03 19:32:16 -0800116 }
117 }
118 }
Leon Scrogginsfedc4932010-01-26 14:15:01 -0500119
The Android Open Source Project0c908882009-03-03 19:32:16 -0800120 @Override
121 public boolean onCreateOptionsMenu(Menu menu) {
122 if (mDownloadCursor != null) {
123 MenuInflater inflater = getMenuInflater();
124 inflater.inflate(R.menu.downloadhistory, menu);
125 }
126 return true;
127 }
128
129 @Override
130 public boolean onPrepareOptionsMenu(Menu menu) {
131 boolean showCancel = getCancelableCount() > 0;
132 menu.findItem(R.id.download_menu_cancel_all).setEnabled(showCancel);
The Android Open Source Project0c908882009-03-03 19:32:16 -0800133 return super.onPrepareOptionsMenu(menu);
134 }
135
136 @Override
137 public boolean onOptionsItemSelected(MenuItem item) {
138 switch (item.getItemId()) {
139 case R.id.download_menu_cancel_all:
140 promptCancelAll();
141 return true;
The Android Open Source Project0c908882009-03-03 19:32:16 -0800142 }
143 return false;
144 }
145
Leon Scroggins9be17332010-01-14 15:44:06 -0500146 /**
147 * Remove the file from the list of downloads.
148 * @param id Unique ID of the download to remove.
149 */
150 private void clearFromDownloads(long id) {
151 getContentResolver().delete(ContentUris.withAppendedId(
152 Downloads.Impl.CONTENT_URI, id), null, null);
153 }
154
The Android Open Source Project0c908882009-03-03 19:32:16 -0800155 @Override
156 public boolean onContextItemSelected(MenuItem item) {
Leon Scroggins24837452010-01-13 13:43:35 -0500157 if (!mDownloadAdapter.moveCursorToPackedChildPosition(
158 mContextMenuPosition)) {
159 return false;
160 }
The Android Open Source Project0c908882009-03-03 19:32:16 -0800161 switch (item.getItemId()) {
162 case R.id.download_menu_open:
163 hideCompletedDownload();
Leon Scrogginsfedc4932010-01-26 14:15:01 -0500164 openOrDeleteCurrentDownload(false);
The Android Open Source Project0c908882009-03-03 19:32:16 -0800165 return true;
Leon Scroggins9be17332010-01-14 15:44:06 -0500166
167 case R.id.download_menu_delete:
Leon Scroggins9be17332010-01-14 15:44:06 -0500168 new AlertDialog.Builder(this)
169 .setTitle(R.string.download_delete_file)
170 .setIcon(android.R.drawable.ic_dialog_alert)
Leon Scrogginsfedc4932010-01-26 14:15:01 -0500171 .setMessage(mDownloadCursor.getString(mTitleColumnId))
Leon Scroggins9be17332010-01-14 15:44:06 -0500172 .setNegativeButton(R.string.cancel, null)
173 .setPositiveButton(R.string.ok,
174 new DialogInterface.OnClickListener() {
175 public void onClick(DialogInterface dialog,
176 int whichButton) {
Leon Scrogginsfedc4932010-01-26 14:15:01 -0500177 openOrDeleteCurrentDownload(true);
Leon Scroggins9be17332010-01-14 15:44:06 -0500178 }
179 })
180 .show();
181 break;
182
The Android Open Source Project0c908882009-03-03 19:32:16 -0800183 case R.id.download_menu_clear:
184 case R.id.download_menu_cancel:
Leon Scroggins9be17332010-01-14 15:44:06 -0500185 clearFromDownloads(mDownloadCursor.getLong(mIdColumnId));
The Android Open Source Project0c908882009-03-03 19:32:16 -0800186 return true;
187 }
188 return false;
189 }
190
191 @Override
Leon Scrogginsd080b182010-02-26 14:16:41 -0500192 protected void onPause() {
193 super.onPause();
194 if (mContentObserver != null) {
195 getContentResolver().unregisterContentObserver(mContentObserver);
196 // Note that we do not need to undo this in onResume, because the
197 // ContextMenu does not get reinvoked when the Activity resumes.
198 }
199 }
200
201 /*
202 * ContentObserver to update the ContextMenu if it is open when the
203 * corresponding download completes.
204 */
205 private class ChangeObserver extends ContentObserver {
206 private final Uri mTrack;
207 public ChangeObserver(Uri track) {
208 super(new Handler());
209 mTrack = track;
210 }
211
212 @Override
213 public boolean deliverSelfNotifications() {
214 return false;
215 }
216
217 @Override
218 public void onChange(boolean selfChange) {
219 Cursor cursor = getContentResolver().query(mTrack,
220 new String[] { Downloads.Impl.COLUMN_STATUS }, null, null,
221 null);
222 if (cursor.moveToFirst() && Downloads.Impl.isStatusSuccess(
223 cursor.getInt(0))) {
224 // Do this right away, so we get no more updates.
225 getContentResolver().unregisterContentObserver(
226 mContentObserver);
227 // Post a runnable in case this ContentObserver gets notified
228 // before the one that updates the ListView.
229 mListView.post(new Runnable() {
230 public void run() {
231 // Close the context menu, reopen with up to date data.
232 closeContextMenu();
233 openContextMenu(mSelectedView);
234 }
235 });
236 }
237 cursor.deactivate();
238 }
239 }
240
241 @Override
The Android Open Source Project0c908882009-03-03 19:32:16 -0800242 public void onCreateContextMenu(ContextMenu menu, View v,
243 ContextMenuInfo menuInfo) {
244 if (mDownloadCursor != null) {
Leon Scroggins24837452010-01-13 13:43:35 -0500245 ExpandableListView.ExpandableListContextMenuInfo info
246 = (ExpandableListView.ExpandableListContextMenuInfo) menuInfo;
247 long packedPosition = info.packedPosition;
248 // Only show a context menu for the child views
249 if (!mDownloadAdapter.moveCursorToPackedChildPosition(
250 packedPosition)) {
251 return;
252 }
253 mContextMenuPosition = packedPosition;
The Android Open Source Project0c908882009-03-03 19:32:16 -0800254 menu.setHeaderTitle(mDownloadCursor.getString(mTitleColumnId));
255
256 MenuInflater inflater = getMenuInflater();
257 int status = mDownloadCursor.getInt(mStatusColumnId);
Jean-Baptiste Queru1e5bad92010-01-14 16:09:03 -0800258 if (Downloads.Impl.isStatusSuccess(status)) {
The Android Open Source Project0c908882009-03-03 19:32:16 -0800259 inflater.inflate(R.menu.downloadhistorycontextfinished, menu);
Jean-Baptiste Queru1e5bad92010-01-14 16:09:03 -0800260 } else if (Downloads.Impl.isStatusError(status)) {
The Android Open Source Project0c908882009-03-03 19:32:16 -0800261 inflater.inflate(R.menu.downloadhistorycontextfailed, menu);
262 } else {
Leon Scrogginsd080b182010-02-26 14:16:41 -0500263 // In this case, the download is in progress. Set a
264 // ContentObserver so that we can know when it completes,
265 // and if it does, we can then update the context menu
266 Uri track = ContentUris.withAppendedId(
267 Downloads.Impl.CONTENT_URI,
268 mDownloadCursor.getLong(mIdColumnId));
269 if (mContentObserver != null) {
270 getContentResolver().unregisterContentObserver(
271 mContentObserver);
272 }
273 mContentObserver = new ChangeObserver(track);
274 mSelectedView = v;
275 getContentResolver().registerContentObserver(track, false,
276 mContentObserver);
The Android Open Source Project0c908882009-03-03 19:32:16 -0800277 inflater.inflate(R.menu.downloadhistorycontextrunning, menu);
278 }
279 }
Leon Scroggins24837452010-01-13 13:43:35 -0500280 super.onCreateContextMenu(menu, v, menuInfo);
The Android Open Source Project0c908882009-03-03 19:32:16 -0800281 }
282
283 /**
284 * This function is called to check the status of the download and if it
285 * has an error show an error dialog.
286 * @param id Row id of the download to check
Leon Scroggins24837452010-01-13 13:43:35 -0500287 * @return Group which contains the download
The Android Open Source Project0c908882009-03-03 19:32:16 -0800288 */
Leon Scroggins24837452010-01-13 13:43:35 -0500289 private int checkStatus(final long id) {
290 int groupToShow = mDownloadAdapter.groupFromChildId(id);
291 if (-1 == groupToShow) return 0;
292 int status = mDownloadCursor.getInt(mStatusColumnId);
Jean-Baptiste Queru1e5bad92010-01-14 16:09:03 -0800293 if (!Downloads.Impl.isStatusError(status)) {
Leon Scroggins24837452010-01-13 13:43:35 -0500294 return groupToShow;
The Android Open Source Project0c908882009-03-03 19:32:16 -0800295 }
Jean-Baptiste Queru1e5bad92010-01-14 16:09:03 -0800296 if (status == Downloads.Impl.STATUS_FILE_ERROR) {
Leon Scroggins24837452010-01-13 13:43:35 -0500297 String title = mDownloadCursor.getString(mTitleColumnId);
298 if (title == null || title.length() == 0) {
299 title = getString(R.string.download_unknown_filename);
The Android Open Source Project0c908882009-03-03 19:32:16 -0800300 }
Leon Scroggins24837452010-01-13 13:43:35 -0500301 String msg = getString(R.string.download_file_error_dlg_msg, title);
302 new AlertDialog.Builder(this)
303 .setTitle(R.string.download_file_error_dlg_title)
304 .setIcon(android.R.drawable.ic_popup_disk_full)
305 .setMessage(msg)
306 .setPositiveButton(R.string.ok, null)
307 .setNegativeButton(R.string.retry,
308 new DialogInterface.OnClickListener() {
309 public void onClick(DialogInterface dialog,
310 int whichButton) {
311 resumeDownload(id);
312 }
313 })
314 .show();
315 } else {
316 new AlertDialog.Builder(this)
317 .setTitle(R.string.download_failed_generic_dlg_title)
318 .setIcon(R.drawable.ssl_icon)
319 .setMessage(BrowserDownloadAdapter.getErrorText(status))
320 .setPositiveButton(R.string.ok, null)
321 .show();
The Android Open Source Project0c908882009-03-03 19:32:16 -0800322 }
Leon Scroggins24837452010-01-13 13:43:35 -0500323 return groupToShow;
The Android Open Source Project0c908882009-03-03 19:32:16 -0800324 }
325
326 /**
327 * Resume a given download
328 * @param id Row id of the download to resume
329 */
330 private void resumeDownload(final long id) {
331 // the relevant functionality doesn't exist in the download manager
332 }
333
334 /**
The Android Open Source Project0c908882009-03-03 19:32:16 -0800335 * Return the number of items in the list that can be canceled.
336 * @return count
337 */
338 private int getCancelableCount() {
339 // Count the number of items that will be canceled.
340 int count = 0;
341 if (mDownloadCursor != null) {
342 for (mDownloadCursor.moveToFirst(); !mDownloadCursor.isAfterLast();
343 mDownloadCursor.moveToNext()) {
344 int status = mDownloadCursor.getInt(mStatusColumnId);
Jean-Baptiste Queru1e5bad92010-01-14 16:09:03 -0800345 if (!Downloads.Impl.isStatusCompleted(status)) {
The Android Open Source Project0c908882009-03-03 19:32:16 -0800346 count++;
347 }
348 }
349 }
350
351 return count;
352 }
353
354 /**
355 * Prompt the user if they would like to clear the download history
356 */
357 private void promptCancelAll() {
358 int count = getCancelableCount();
359
360 // If there is nothing to do, just return
361 if (count == 0) {
362 return;
363 }
364
365 // Don't show the dialog if there is only one download
366 if (count == 1) {
367 cancelAllDownloads();
368 return;
369 }
370 String msg =
371 getString(R.string.download_cancel_dlg_msg, count);
372 new AlertDialog.Builder(this)
373 .setTitle(R.string.download_cancel_dlg_title)
374 .setIcon(R.drawable.ssl_icon)
375 .setMessage(msg)
376 .setPositiveButton(R.string.ok,
377 new DialogInterface.OnClickListener() {
378 public void onClick(DialogInterface dialog,
379 int whichButton) {
380 cancelAllDownloads();
381 }
382 })
383 .setNegativeButton(R.string.cancel, null)
384 .show();
385 }
386
387 /**
388 * Cancel all downloads. As canceled downloads are not
389 * listed, we removed them from the db. Removing a download
390 * record, cancels the download.
391 */
392 private void cancelAllDownloads() {
393 if (mDownloadCursor.moveToFirst()) {
394 StringBuilder where = new StringBuilder();
395 boolean firstTime = true;
396 while (!mDownloadCursor.isAfterLast()) {
397 int status = mDownloadCursor.getInt(mStatusColumnId);
Jean-Baptiste Queru1e5bad92010-01-14 16:09:03 -0800398 if (!Downloads.Impl.isStatusCompleted(status)) {
The Android Open Source Project0c908882009-03-03 19:32:16 -0800399 if (firstTime) {
400 firstTime = false;
401 } else {
402 where.append(" OR ");
403 }
404 where.append("( ");
Jean-Baptiste Queru1e5bad92010-01-14 16:09:03 -0800405 where.append(Downloads.Impl._ID);
The Android Open Source Project0c908882009-03-03 19:32:16 -0800406 where.append(" = '");
407 where.append(mDownloadCursor.getLong(mIdColumnId));
408 where.append("' )");
409 }
410 mDownloadCursor.moveToNext();
411 }
412 if (!firstTime) {
Jean-Baptiste Queru1e5bad92010-01-14 16:09:03 -0800413 getContentResolver().delete(Downloads.Impl.CONTENT_URI,
The Android Open Source Project0c908882009-03-03 19:32:16 -0800414 where.toString(), null);
415 }
416 }
417 }
418
419 private int getClearableCount() {
420 int count = 0;
421 if (mDownloadCursor.moveToFirst()) {
422 while (!mDownloadCursor.isAfterLast()) {
423 int status = mDownloadCursor.getInt(mStatusColumnId);
Jean-Baptiste Queru1e5bad92010-01-14 16:09:03 -0800424 if (Downloads.Impl.isStatusCompleted(status)) {
The Android Open Source Project0c908882009-03-03 19:32:16 -0800425 count++;
426 }
427 mDownloadCursor.moveToNext();
428 }
429 }
430 return count;
431 }
Leon Scroggins4cf7de02010-01-21 10:05:59 -0500432
The Android Open Source Project0c908882009-03-03 19:32:16 -0800433 /**
Leon Scrogginsfedc4932010-01-26 14:15:01 -0500434 * Open or delete content where the download db cursor currently is. Sends
435 * an Intent to perform the action.
436 * @param delete If true, delete the content. Otherwise open it.
The Android Open Source Project0c908882009-03-03 19:32:16 -0800437 */
Leon Scrogginsfedc4932010-01-26 14:15:01 -0500438 private void openOrDeleteCurrentDownload(boolean delete) {
439 int packageColumnId = mDownloadCursor.getColumnIndexOrThrow(
440 Downloads.Impl.COLUMN_NOTIFICATION_PACKAGE);
441 String packageName = mDownloadCursor.getString(packageColumnId);
442 Intent intent = new Intent(delete ? Intent.ACTION_DELETE
443 : Downloads.Impl.ACTION_NOTIFICATION_CLICKED);
444 Uri contentUri = ContentUris.withAppendedId(
445 Downloads.Impl.CONTENT_URI,
446 mDownloadCursor.getLong(mIdColumnId));
447 intent.setData(contentUri);
448 intent.setPackage(packageName);
449 sendBroadcast(intent);
The Android Open Source Project0c908882009-03-03 19:32:16 -0800450 }
451
Leon Scroggins24837452010-01-13 13:43:35 -0500452 @Override
453 public boolean onChildClick(ExpandableListView parent, View v,
454 int groupPosition, int childPosition, long id) {
The Android Open Source Project0c908882009-03-03 19:32:16 -0800455 // Open the selected item
Leon Scroggins24837452010-01-13 13:43:35 -0500456 mDownloadAdapter.moveCursorToChildPosition(groupPosition,
457 childPosition);
The Android Open Source Project0c908882009-03-03 19:32:16 -0800458
459 hideCompletedDownload();
460
461 int status = mDownloadCursor.getInt(mStatusColumnId);
Jean-Baptiste Queru1e5bad92010-01-14 16:09:03 -0800462 if (Downloads.Impl.isStatusSuccess(status)) {
The Android Open Source Project0c908882009-03-03 19:32:16 -0800463 // Open it if it downloaded successfully
Leon Scrogginsfedc4932010-01-26 14:15:01 -0500464 openOrDeleteCurrentDownload(false);
The Android Open Source Project0c908882009-03-03 19:32:16 -0800465 } else {
466 // Check to see if there is an error.
467 checkStatus(id);
468 }
Leon Scroggins24837452010-01-13 13:43:35 -0500469 return true;
The Android Open Source Project0c908882009-03-03 19:32:16 -0800470 }
471
472 /**
473 * hides the notification for the download pointed by mDownloadCursor
474 * if the download has completed.
475 */
476 private void hideCompletedDownload() {
477 int status = mDownloadCursor.getInt(mStatusColumnId);
478
Jean-Baptiste Queru1e5bad92010-01-14 16:09:03 -0800479 int visibilityColumn = mDownloadCursor.getColumnIndexOrThrow(
480 Downloads.Impl.COLUMN_VISIBILITY);
The Android Open Source Project0c908882009-03-03 19:32:16 -0800481 int visibility = mDownloadCursor.getInt(visibilityColumn);
482
Jean-Baptiste Queru1e5bad92010-01-14 16:09:03 -0800483 if (Downloads.Impl.isStatusCompleted(status) &&
484 visibility == Downloads.Impl.VISIBILITY_VISIBLE_NOTIFY_COMPLETED) {
The Android Open Source Project0c908882009-03-03 19:32:16 -0800485 ContentValues values = new ContentValues();
Jean-Baptiste Queru1e5bad92010-01-14 16:09:03 -0800486 values.put(Downloads.Impl.COLUMN_VISIBILITY, Downloads.Impl.VISIBILITY_VISIBLE);
The Android Open Source Project0c908882009-03-03 19:32:16 -0800487 getContentResolver().update(
Jean-Baptiste Queru1e5bad92010-01-14 16:09:03 -0800488 ContentUris.withAppendedId(Downloads.Impl.CONTENT_URI,
The Android Open Source Project0c908882009-03-03 19:32:16 -0800489 mDownloadCursor.getLong(mIdColumnId)), values, null, null);
490 }
491 }
492}