blob: 6a5ef283df9ef9a3b8d852e7c038d4f2b58724fc [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;
Leon Scroggins2c0f6112010-03-12 18:09:39 -050034import android.util.Log;
The Android Open Source Project0c908882009-03-03 19:32:16 -080035import android.view.ContextMenu;
36import android.view.ContextMenu.ContextMenuInfo;
37import android.view.LayoutInflater;
38import android.view.Menu;
39import android.view.MenuItem;
40import android.view.MenuInflater;
41import android.view.View;
42import android.view.ViewGroup.LayoutParams;
43import android.widget.AdapterView;
Leon Scroggins24837452010-01-13 13:43:35 -050044import android.widget.ExpandableListView;
The Android Open Source Project0c908882009-03-03 19:32:16 -080045
46import java.io.File;
47import java.util.List;
48
49/**
50 * View showing the user's current browser downloads
51 */
Leon Scroggins24837452010-01-13 13:43:35 -050052public class BrowserDownloadPage extends ExpandableListActivity {
Leon Scroggins24837452010-01-13 13:43:35 -050053 private ExpandableListView mListView;
The Android Open Source Project0c908882009-03-03 19:32:16 -080054 private Cursor mDownloadCursor;
55 private BrowserDownloadAdapter mDownloadAdapter;
56 private int mStatusColumnId;
57 private int mIdColumnId;
58 private int mTitleColumnId;
Leon Scroggins24837452010-01-13 13:43:35 -050059 private long mContextMenuPosition;
Leon Scrogginsd080b182010-02-26 14:16:41 -050060 // Used to update the ContextMenu if an item is being downloaded and the
61 // user opens the ContextMenu.
62 private ContentObserver mContentObserver;
63 // Only meaningful while a ContentObserver is registered. The ContextMenu
64 // will be reopened on this View.
65 private View mSelectedView;
66
Leon Scroggins2c0f6112010-03-12 18:09:39 -050067 private final static String LOGTAG = "BrowserDownloadPage";
The Android Open Source Project0c908882009-03-03 19:32:16 -080068 @Override
69 public void onCreate(Bundle icicle) {
70 super.onCreate(icicle);
71 setContentView(R.layout.browser_downloads_page);
72
73 setTitle(getText(R.string.download_title));
74
Leon Scroggins24837452010-01-13 13:43:35 -050075 mListView = (ExpandableListView) findViewById(android.R.id.list);
Mihai Preda83817df2009-04-28 14:24:47 +020076 mListView.setEmptyView(findViewById(R.id.empty));
Jean-Baptiste Queru1e5bad92010-01-14 16:09:03 -080077 mDownloadCursor = managedQuery(Downloads.Impl.CONTENT_URI,
Leon Scrogginsfedc4932010-01-26 14:15:01 -050078 new String [] {Downloads.Impl._ID, Downloads.Impl.COLUMN_TITLE,
79 Downloads.Impl.COLUMN_STATUS, Downloads.Impl.COLUMN_TOTAL_BYTES,
80 Downloads.Impl.COLUMN_CURRENT_BYTES,
81 Downloads.Impl.COLUMN_DESCRIPTION,
82 Downloads.Impl.COLUMN_NOTIFICATION_PACKAGE,
83 Downloads.Impl.COLUMN_LAST_MODIFICATION,
84 Downloads.Impl.COLUMN_VISIBILITY,
Leon Scrogginsb67db6b2010-02-26 17:58:31 -050085 Downloads.Impl._DATA,
Leon Scrogginsfedc4932010-01-26 14:15:01 -050086 Downloads.Impl.COLUMN_MIME_TYPE},
Jean-Baptiste Queru1e5bad92010-01-14 16:09:03 -080087 null, Downloads.Impl.COLUMN_LAST_MODIFICATION + " DESC");
The Android Open Source Project0c908882009-03-03 19:32:16 -080088
89 // only attach everything to the listbox if we can access
90 // the download database. Otherwise, just show it empty
91 if (mDownloadCursor != null) {
92 mStatusColumnId =
Jean-Baptiste Queru1e5bad92010-01-14 16:09:03 -080093 mDownloadCursor.getColumnIndexOrThrow(Downloads.Impl.COLUMN_STATUS);
The Android Open Source Project0c908882009-03-03 19:32:16 -080094 mIdColumnId =
Jean-Baptiste Queru1e5bad92010-01-14 16:09:03 -080095 mDownloadCursor.getColumnIndexOrThrow(Downloads.Impl._ID);
The Android Open Source Project0c908882009-03-03 19:32:16 -080096 mTitleColumnId =
Jean-Baptiste Queru1e5bad92010-01-14 16:09:03 -080097 mDownloadCursor.getColumnIndexOrThrow(Downloads.Impl.COLUMN_TITLE);
The Android Open Source Project0c908882009-03-03 19:32:16 -080098
99 // Create a list "controller" for the data
100 mDownloadAdapter = new BrowserDownloadAdapter(this,
Leon Scroggins24837452010-01-13 13:43:35 -0500101 mDownloadCursor, mDownloadCursor.getColumnIndexOrThrow(
Jean-Baptiste Queru1e5bad92010-01-14 16:09:03 -0800102 Downloads.Impl.COLUMN_LAST_MODIFICATION));
Mihai Preda83817df2009-04-28 14:24:47 +0200103
Leon Scroggins24837452010-01-13 13:43:35 -0500104 setListAdapter(mDownloadAdapter);
The Android Open Source Project0c908882009-03-03 19:32:16 -0800105 mListView.setScrollBarStyle(View.SCROLLBARS_INSIDE_INSET);
106 mListView.setOnCreateContextMenuListener(this);
Leon Scroggins24837452010-01-13 13:43:35 -0500107
The Android Open Source Project0c908882009-03-03 19:32:16 -0800108 Intent intent = getIntent();
Leon Scroggins24837452010-01-13 13:43:35 -0500109 final int groupToShow = intent == null || intent.getData() == null
110 ? 0 : checkStatus(ContentUris.parseId(intent.getData()));
111 if (mDownloadAdapter.getGroupCount() > groupToShow) {
112 mListView.post(new Runnable() {
113 public void run() {
114 if (mDownloadAdapter.getGroupCount() > groupToShow) {
115 mListView.expandGroup(groupToShow);
116 }
117 }
118 });
The Android Open Source Project0c908882009-03-03 19:32:16 -0800119 }
120 }
121 }
Leon Scrogginsfedc4932010-01-26 14:15:01 -0500122
The Android Open Source Project0c908882009-03-03 19:32:16 -0800123 @Override
Leon Scrogginsb67db6b2010-02-26 17:58:31 -0500124 protected void onResume() {
125 super.onResume();
126 if (mDownloadCursor != null) {
127 String where = null;
128 for (mDownloadCursor.moveToFirst(); !mDownloadCursor.isAfterLast();
129 mDownloadCursor.moveToNext()) {
130 if (!Downloads.Impl.isStatusCompleted(
131 mDownloadCursor.getInt(mStatusColumnId))) {
132 // Only want to check files that have completed.
133 continue;
134 }
135 int filenameColumnId = mDownloadCursor.getColumnIndexOrThrow(
136 Downloads.Impl._DATA);
137 String filename = mDownloadCursor.getString(filenameColumnId);
Leon Scroggins3ee3fef2010-03-08 14:34:14 -0500138 if (filename != null) {
139 File file = new File(filename);
140 if (!file.exists()) {
141 long id = mDownloadCursor.getLong(mIdColumnId);
142 if (where == null) {
143 where = Downloads.Impl._ID + " = '" + id + "'";
144 } else {
145 where += " OR " + Downloads.Impl._ID + " = '" + id
146 + "'";
147 }
Leon Scrogginsb67db6b2010-02-26 17:58:31 -0500148 }
149 }
150 }
151 if (where != null) {
152 getContentResolver().delete(Downloads.Impl.CONTENT_URI, where,
153 null);
154 }
155 }
156 }
157
158 @Override
The Android Open Source Project0c908882009-03-03 19:32:16 -0800159 public boolean onCreateOptionsMenu(Menu menu) {
160 if (mDownloadCursor != null) {
161 MenuInflater inflater = getMenuInflater();
162 inflater.inflate(R.menu.downloadhistory, menu);
163 }
164 return true;
165 }
166
167 @Override
168 public boolean onPrepareOptionsMenu(Menu menu) {
169 boolean showCancel = getCancelableCount() > 0;
170 menu.findItem(R.id.download_menu_cancel_all).setEnabled(showCancel);
The Android Open Source Project0c908882009-03-03 19:32:16 -0800171 return super.onPrepareOptionsMenu(menu);
172 }
173
174 @Override
175 public boolean onOptionsItemSelected(MenuItem item) {
176 switch (item.getItemId()) {
177 case R.id.download_menu_cancel_all:
178 promptCancelAll();
179 return true;
The Android Open Source Project0c908882009-03-03 19:32:16 -0800180 }
181 return false;
182 }
183
Leon Scroggins9be17332010-01-14 15:44:06 -0500184 /**
185 * Remove the file from the list of downloads.
186 * @param id Unique ID of the download to remove.
187 */
188 private void clearFromDownloads(long id) {
189 getContentResolver().delete(ContentUris.withAppendedId(
190 Downloads.Impl.CONTENT_URI, id), null, null);
191 }
192
The Android Open Source Project0c908882009-03-03 19:32:16 -0800193 @Override
194 public boolean onContextItemSelected(MenuItem item) {
Leon Scroggins24837452010-01-13 13:43:35 -0500195 if (!mDownloadAdapter.moveCursorToPackedChildPosition(
196 mContextMenuPosition)) {
197 return false;
198 }
The Android Open Source Project0c908882009-03-03 19:32:16 -0800199 switch (item.getItemId()) {
200 case R.id.download_menu_open:
201 hideCompletedDownload();
Leon Scrogginsfedc4932010-01-26 14:15:01 -0500202 openOrDeleteCurrentDownload(false);
The Android Open Source Project0c908882009-03-03 19:32:16 -0800203 return true;
Leon Scroggins9be17332010-01-14 15:44:06 -0500204
205 case R.id.download_menu_delete:
Leon Scroggins9be17332010-01-14 15:44:06 -0500206 new AlertDialog.Builder(this)
207 .setTitle(R.string.download_delete_file)
208 .setIcon(android.R.drawable.ic_dialog_alert)
Leon Scrogginsfedc4932010-01-26 14:15:01 -0500209 .setMessage(mDownloadCursor.getString(mTitleColumnId))
Leon Scroggins9be17332010-01-14 15:44:06 -0500210 .setNegativeButton(R.string.cancel, null)
211 .setPositiveButton(R.string.ok,
212 new DialogInterface.OnClickListener() {
213 public void onClick(DialogInterface dialog,
214 int whichButton) {
Leon Scrogginsfedc4932010-01-26 14:15:01 -0500215 openOrDeleteCurrentDownload(true);
Leon Scroggins9be17332010-01-14 15:44:06 -0500216 }
217 })
218 .show();
219 break;
220
The Android Open Source Project0c908882009-03-03 19:32:16 -0800221 case R.id.download_menu_clear:
222 case R.id.download_menu_cancel:
Leon Scroggins9be17332010-01-14 15:44:06 -0500223 clearFromDownloads(mDownloadCursor.getLong(mIdColumnId));
The Android Open Source Project0c908882009-03-03 19:32:16 -0800224 return true;
225 }
226 return false;
227 }
228
229 @Override
Leon Scrogginsd080b182010-02-26 14:16:41 -0500230 protected void onPause() {
231 super.onPause();
232 if (mContentObserver != null) {
233 getContentResolver().unregisterContentObserver(mContentObserver);
234 // Note that we do not need to undo this in onResume, because the
235 // ContextMenu does not get reinvoked when the Activity resumes.
236 }
237 }
238
239 /*
240 * ContentObserver to update the ContextMenu if it is open when the
241 * corresponding download completes.
242 */
243 private class ChangeObserver extends ContentObserver {
244 private final Uri mTrack;
245 public ChangeObserver(Uri track) {
246 super(new Handler());
247 mTrack = track;
248 }
249
250 @Override
251 public boolean deliverSelfNotifications() {
252 return false;
253 }
254
255 @Override
256 public void onChange(boolean selfChange) {
Leon Scroggins2c0f6112010-03-12 18:09:39 -0500257 Cursor cursor = null;
258 try {
259 cursor = getContentResolver().query(mTrack,
260 new String[] { Downloads.Impl.COLUMN_STATUS }, null, null,
261 null);
262 if (cursor.moveToFirst() && Downloads.Impl.isStatusSuccess(
263 cursor.getInt(0))) {
264 // Do this right away, so we get no more updates.
265 getContentResolver().unregisterContentObserver(
266 mContentObserver);
267 // Post a runnable in case this ContentObserver gets notified
268 // before the one that updates the ListView.
269 mListView.post(new Runnable() {
270 public void run() {
271 // Close the context menu, reopen with up to date data.
272 closeContextMenu();
273 openContextMenu(mSelectedView);
274 }
275 });
276 }
277 } catch (IllegalStateException e) {
278 Log.e(LOGTAG, "onChange", e);
279 } finally {
280 if (cursor != null) cursor.close();
Leon Scrogginsd080b182010-02-26 14:16:41 -0500281 }
Leon Scrogginsd080b182010-02-26 14:16:41 -0500282 }
283 }
284
285 @Override
The Android Open Source Project0c908882009-03-03 19:32:16 -0800286 public void onCreateContextMenu(ContextMenu menu, View v,
287 ContextMenuInfo menuInfo) {
288 if (mDownloadCursor != null) {
Leon Scroggins24837452010-01-13 13:43:35 -0500289 ExpandableListView.ExpandableListContextMenuInfo info
290 = (ExpandableListView.ExpandableListContextMenuInfo) menuInfo;
291 long packedPosition = info.packedPosition;
292 // Only show a context menu for the child views
293 if (!mDownloadAdapter.moveCursorToPackedChildPosition(
294 packedPosition)) {
295 return;
296 }
297 mContextMenuPosition = packedPosition;
The Android Open Source Project0c908882009-03-03 19:32:16 -0800298 menu.setHeaderTitle(mDownloadCursor.getString(mTitleColumnId));
299
300 MenuInflater inflater = getMenuInflater();
301 int status = mDownloadCursor.getInt(mStatusColumnId);
Jean-Baptiste Queru1e5bad92010-01-14 16:09:03 -0800302 if (Downloads.Impl.isStatusSuccess(status)) {
The Android Open Source Project0c908882009-03-03 19:32:16 -0800303 inflater.inflate(R.menu.downloadhistorycontextfinished, menu);
Jean-Baptiste Queru1e5bad92010-01-14 16:09:03 -0800304 } else if (Downloads.Impl.isStatusError(status)) {
The Android Open Source Project0c908882009-03-03 19:32:16 -0800305 inflater.inflate(R.menu.downloadhistorycontextfailed, menu);
306 } else {
Leon Scrogginsd080b182010-02-26 14:16:41 -0500307 // In this case, the download is in progress. Set a
308 // ContentObserver so that we can know when it completes,
309 // and if it does, we can then update the context menu
310 Uri track = ContentUris.withAppendedId(
311 Downloads.Impl.CONTENT_URI,
312 mDownloadCursor.getLong(mIdColumnId));
313 if (mContentObserver != null) {
314 getContentResolver().unregisterContentObserver(
315 mContentObserver);
316 }
317 mContentObserver = new ChangeObserver(track);
318 mSelectedView = v;
319 getContentResolver().registerContentObserver(track, false,
320 mContentObserver);
The Android Open Source Project0c908882009-03-03 19:32:16 -0800321 inflater.inflate(R.menu.downloadhistorycontextrunning, menu);
322 }
323 }
Leon Scroggins24837452010-01-13 13:43:35 -0500324 super.onCreateContextMenu(menu, v, menuInfo);
The Android Open Source Project0c908882009-03-03 19:32:16 -0800325 }
326
327 /**
328 * This function is called to check the status of the download and if it
329 * has an error show an error dialog.
330 * @param id Row id of the download to check
Leon Scroggins24837452010-01-13 13:43:35 -0500331 * @return Group which contains the download
The Android Open Source Project0c908882009-03-03 19:32:16 -0800332 */
Leon Scroggins24837452010-01-13 13:43:35 -0500333 private int checkStatus(final long id) {
334 int groupToShow = mDownloadAdapter.groupFromChildId(id);
335 if (-1 == groupToShow) return 0;
336 int status = mDownloadCursor.getInt(mStatusColumnId);
Jean-Baptiste Queru1e5bad92010-01-14 16:09:03 -0800337 if (!Downloads.Impl.isStatusError(status)) {
Leon Scroggins24837452010-01-13 13:43:35 -0500338 return groupToShow;
The Android Open Source Project0c908882009-03-03 19:32:16 -0800339 }
Jean-Baptiste Queru1e5bad92010-01-14 16:09:03 -0800340 if (status == Downloads.Impl.STATUS_FILE_ERROR) {
Leon Scroggins24837452010-01-13 13:43:35 -0500341 String title = mDownloadCursor.getString(mTitleColumnId);
342 if (title == null || title.length() == 0) {
343 title = getString(R.string.download_unknown_filename);
The Android Open Source Project0c908882009-03-03 19:32:16 -0800344 }
Leon Scroggins24837452010-01-13 13:43:35 -0500345 String msg = getString(R.string.download_file_error_dlg_msg, title);
346 new AlertDialog.Builder(this)
347 .setTitle(R.string.download_file_error_dlg_title)
348 .setIcon(android.R.drawable.ic_popup_disk_full)
349 .setMessage(msg)
350 .setPositiveButton(R.string.ok, null)
351 .setNegativeButton(R.string.retry,
352 new DialogInterface.OnClickListener() {
353 public void onClick(DialogInterface dialog,
354 int whichButton) {
355 resumeDownload(id);
356 }
357 })
358 .show();
359 } else {
360 new AlertDialog.Builder(this)
361 .setTitle(R.string.download_failed_generic_dlg_title)
362 .setIcon(R.drawable.ssl_icon)
363 .setMessage(BrowserDownloadAdapter.getErrorText(status))
364 .setPositiveButton(R.string.ok, null)
365 .show();
The Android Open Source Project0c908882009-03-03 19:32:16 -0800366 }
Leon Scroggins24837452010-01-13 13:43:35 -0500367 return groupToShow;
The Android Open Source Project0c908882009-03-03 19:32:16 -0800368 }
369
370 /**
371 * Resume a given download
372 * @param id Row id of the download to resume
373 */
374 private void resumeDownload(final long id) {
375 // the relevant functionality doesn't exist in the download manager
376 }
377
378 /**
The Android Open Source Project0c908882009-03-03 19:32:16 -0800379 * Return the number of items in the list that can be canceled.
380 * @return count
381 */
382 private int getCancelableCount() {
383 // Count the number of items that will be canceled.
384 int count = 0;
385 if (mDownloadCursor != null) {
Leon Scrogginsb67db6b2010-02-26 17:58:31 -0500386 for (mDownloadCursor.moveToFirst(); !mDownloadCursor.isAfterLast();
The Android Open Source Project0c908882009-03-03 19:32:16 -0800387 mDownloadCursor.moveToNext()) {
388 int status = mDownloadCursor.getInt(mStatusColumnId);
Jean-Baptiste Queru1e5bad92010-01-14 16:09:03 -0800389 if (!Downloads.Impl.isStatusCompleted(status)) {
The Android Open Source Project0c908882009-03-03 19:32:16 -0800390 count++;
391 }
392 }
393 }
394
395 return count;
396 }
397
398 /**
399 * Prompt the user if they would like to clear the download history
400 */
401 private void promptCancelAll() {
402 int count = getCancelableCount();
403
404 // If there is nothing to do, just return
405 if (count == 0) {
406 return;
407 }
408
409 // Don't show the dialog if there is only one download
410 if (count == 1) {
411 cancelAllDownloads();
412 return;
413 }
414 String msg =
415 getString(R.string.download_cancel_dlg_msg, count);
416 new AlertDialog.Builder(this)
417 .setTitle(R.string.download_cancel_dlg_title)
418 .setIcon(R.drawable.ssl_icon)
419 .setMessage(msg)
420 .setPositiveButton(R.string.ok,
421 new DialogInterface.OnClickListener() {
422 public void onClick(DialogInterface dialog,
423 int whichButton) {
424 cancelAllDownloads();
425 }
426 })
427 .setNegativeButton(R.string.cancel, null)
428 .show();
429 }
430
431 /**
432 * Cancel all downloads. As canceled downloads are not
433 * listed, we removed them from the db. Removing a download
434 * record, cancels the download.
435 */
436 private void cancelAllDownloads() {
437 if (mDownloadCursor.moveToFirst()) {
438 StringBuilder where = new StringBuilder();
439 boolean firstTime = true;
440 while (!mDownloadCursor.isAfterLast()) {
441 int status = mDownloadCursor.getInt(mStatusColumnId);
Jean-Baptiste Queru1e5bad92010-01-14 16:09:03 -0800442 if (!Downloads.Impl.isStatusCompleted(status)) {
The Android Open Source Project0c908882009-03-03 19:32:16 -0800443 if (firstTime) {
444 firstTime = false;
445 } else {
446 where.append(" OR ");
447 }
448 where.append("( ");
Jean-Baptiste Queru1e5bad92010-01-14 16:09:03 -0800449 where.append(Downloads.Impl._ID);
The Android Open Source Project0c908882009-03-03 19:32:16 -0800450 where.append(" = '");
451 where.append(mDownloadCursor.getLong(mIdColumnId));
452 where.append("' )");
453 }
454 mDownloadCursor.moveToNext();
455 }
456 if (!firstTime) {
Jean-Baptiste Queru1e5bad92010-01-14 16:09:03 -0800457 getContentResolver().delete(Downloads.Impl.CONTENT_URI,
The Android Open Source Project0c908882009-03-03 19:32:16 -0800458 where.toString(), null);
459 }
460 }
461 }
462
463 private int getClearableCount() {
464 int count = 0;
465 if (mDownloadCursor.moveToFirst()) {
466 while (!mDownloadCursor.isAfterLast()) {
467 int status = mDownloadCursor.getInt(mStatusColumnId);
Jean-Baptiste Queru1e5bad92010-01-14 16:09:03 -0800468 if (Downloads.Impl.isStatusCompleted(status)) {
The Android Open Source Project0c908882009-03-03 19:32:16 -0800469 count++;
470 }
471 mDownloadCursor.moveToNext();
472 }
473 }
474 return count;
475 }
Leon Scroggins4cf7de02010-01-21 10:05:59 -0500476
The Android Open Source Project0c908882009-03-03 19:32:16 -0800477 /**
Leon Scrogginsfedc4932010-01-26 14:15:01 -0500478 * Open or delete content where the download db cursor currently is. Sends
479 * an Intent to perform the action.
480 * @param delete If true, delete the content. Otherwise open it.
The Android Open Source Project0c908882009-03-03 19:32:16 -0800481 */
Leon Scrogginsfedc4932010-01-26 14:15:01 -0500482 private void openOrDeleteCurrentDownload(boolean delete) {
483 int packageColumnId = mDownloadCursor.getColumnIndexOrThrow(
484 Downloads.Impl.COLUMN_NOTIFICATION_PACKAGE);
485 String packageName = mDownloadCursor.getString(packageColumnId);
486 Intent intent = new Intent(delete ? Intent.ACTION_DELETE
487 : Downloads.Impl.ACTION_NOTIFICATION_CLICKED);
488 Uri contentUri = ContentUris.withAppendedId(
489 Downloads.Impl.CONTENT_URI,
490 mDownloadCursor.getLong(mIdColumnId));
491 intent.setData(contentUri);
492 intent.setPackage(packageName);
493 sendBroadcast(intent);
The Android Open Source Project0c908882009-03-03 19:32:16 -0800494 }
495
Leon Scroggins24837452010-01-13 13:43:35 -0500496 @Override
497 public boolean onChildClick(ExpandableListView parent, View v,
498 int groupPosition, int childPosition, long id) {
The Android Open Source Project0c908882009-03-03 19:32:16 -0800499 // Open the selected item
Leon Scroggins24837452010-01-13 13:43:35 -0500500 mDownloadAdapter.moveCursorToChildPosition(groupPosition,
501 childPosition);
The Android Open Source Project0c908882009-03-03 19:32:16 -0800502
503 hideCompletedDownload();
504
505 int status = mDownloadCursor.getInt(mStatusColumnId);
Jean-Baptiste Queru1e5bad92010-01-14 16:09:03 -0800506 if (Downloads.Impl.isStatusSuccess(status)) {
The Android Open Source Project0c908882009-03-03 19:32:16 -0800507 // Open it if it downloaded successfully
Leon Scrogginsfedc4932010-01-26 14:15:01 -0500508 openOrDeleteCurrentDownload(false);
The Android Open Source Project0c908882009-03-03 19:32:16 -0800509 } else {
510 // Check to see if there is an error.
511 checkStatus(id);
512 }
Leon Scroggins24837452010-01-13 13:43:35 -0500513 return true;
The Android Open Source Project0c908882009-03-03 19:32:16 -0800514 }
515
516 /**
517 * hides the notification for the download pointed by mDownloadCursor
518 * if the download has completed.
519 */
520 private void hideCompletedDownload() {
521 int status = mDownloadCursor.getInt(mStatusColumnId);
522
Jean-Baptiste Queru1e5bad92010-01-14 16:09:03 -0800523 int visibilityColumn = mDownloadCursor.getColumnIndexOrThrow(
524 Downloads.Impl.COLUMN_VISIBILITY);
The Android Open Source Project0c908882009-03-03 19:32:16 -0800525 int visibility = mDownloadCursor.getInt(visibilityColumn);
526
Jean-Baptiste Queru1e5bad92010-01-14 16:09:03 -0800527 if (Downloads.Impl.isStatusCompleted(status) &&
528 visibility == Downloads.Impl.VISIBILITY_VISIBLE_NOTIFY_COMPLETED) {
The Android Open Source Project0c908882009-03-03 19:32:16 -0800529 ContentValues values = new ContentValues();
Jean-Baptiste Queru1e5bad92010-01-14 16:09:03 -0800530 values.put(Downloads.Impl.COLUMN_VISIBILITY, Downloads.Impl.VISIBILITY_VISIBLE);
The Android Open Source Project0c908882009-03-03 19:32:16 -0800531 getContentResolver().update(
Jean-Baptiste Queru1e5bad92010-01-14 16:09:03 -0800532 ContentUris.withAppendedId(Downloads.Impl.CONTENT_URI,
The Android Open Source Project0c908882009-03-03 19:32:16 -0800533 mDownloadCursor.getLong(mIdColumnId)), values, null, null);
534 }
535 }
536}