blob: 18faf8b369626b7a659f9f5cea8906ade573bbd8 [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.setOnCreateContextMenuListener(this);
Leon Scroggins24837452010-01-13 13:43:35 -0500106
The Android Open Source Project0c908882009-03-03 19:32:16 -0800107 Intent intent = getIntent();
Leon Scroggins24837452010-01-13 13:43:35 -0500108 final int groupToShow = intent == null || intent.getData() == null
109 ? 0 : checkStatus(ContentUris.parseId(intent.getData()));
110 if (mDownloadAdapter.getGroupCount() > groupToShow) {
111 mListView.post(new Runnable() {
112 public void run() {
113 if (mDownloadAdapter.getGroupCount() > groupToShow) {
114 mListView.expandGroup(groupToShow);
115 }
116 }
117 });
The Android Open Source Project0c908882009-03-03 19:32:16 -0800118 }
119 }
120 }
Leon Scrogginsfedc4932010-01-26 14:15:01 -0500121
The Android Open Source Project0c908882009-03-03 19:32:16 -0800122 @Override
Leon Scrogginsb67db6b2010-02-26 17:58:31 -0500123 protected void onResume() {
124 super.onResume();
125 if (mDownloadCursor != null) {
126 String where = null;
127 for (mDownloadCursor.moveToFirst(); !mDownloadCursor.isAfterLast();
128 mDownloadCursor.moveToNext()) {
129 if (!Downloads.Impl.isStatusCompleted(
130 mDownloadCursor.getInt(mStatusColumnId))) {
131 // Only want to check files that have completed.
132 continue;
133 }
134 int filenameColumnId = mDownloadCursor.getColumnIndexOrThrow(
135 Downloads.Impl._DATA);
136 String filename = mDownloadCursor.getString(filenameColumnId);
Leon Scroggins3ee3fef2010-03-08 14:34:14 -0500137 if (filename != null) {
138 File file = new File(filename);
139 if (!file.exists()) {
140 long id = mDownloadCursor.getLong(mIdColumnId);
141 if (where == null) {
142 where = Downloads.Impl._ID + " = '" + id + "'";
143 } else {
144 where += " OR " + Downloads.Impl._ID + " = '" + id
145 + "'";
146 }
Leon Scrogginsb67db6b2010-02-26 17:58:31 -0500147 }
148 }
149 }
150 if (where != null) {
151 getContentResolver().delete(Downloads.Impl.CONTENT_URI, where,
152 null);
153 }
154 }
155 }
156
157 @Override
The Android Open Source Project0c908882009-03-03 19:32:16 -0800158 public boolean onCreateOptionsMenu(Menu menu) {
159 if (mDownloadCursor != null) {
160 MenuInflater inflater = getMenuInflater();
161 inflater.inflate(R.menu.downloadhistory, menu);
162 }
163 return true;
164 }
165
166 @Override
167 public boolean onPrepareOptionsMenu(Menu menu) {
168 boolean showCancel = getCancelableCount() > 0;
169 menu.findItem(R.id.download_menu_cancel_all).setEnabled(showCancel);
The Android Open Source Project0c908882009-03-03 19:32:16 -0800170 return super.onPrepareOptionsMenu(menu);
171 }
172
173 @Override
174 public boolean onOptionsItemSelected(MenuItem item) {
175 switch (item.getItemId()) {
176 case R.id.download_menu_cancel_all:
177 promptCancelAll();
178 return true;
The Android Open Source Project0c908882009-03-03 19:32:16 -0800179 }
180 return false;
181 }
182
Leon Scroggins9be17332010-01-14 15:44:06 -0500183 /**
184 * Remove the file from the list of downloads.
185 * @param id Unique ID of the download to remove.
186 */
187 private void clearFromDownloads(long id) {
188 getContentResolver().delete(ContentUris.withAppendedId(
189 Downloads.Impl.CONTENT_URI, id), null, null);
190 }
191
The Android Open Source Project0c908882009-03-03 19:32:16 -0800192 @Override
193 public boolean onContextItemSelected(MenuItem item) {
Leon Scroggins24837452010-01-13 13:43:35 -0500194 if (!mDownloadAdapter.moveCursorToPackedChildPosition(
195 mContextMenuPosition)) {
196 return false;
197 }
The Android Open Source Project0c908882009-03-03 19:32:16 -0800198 switch (item.getItemId()) {
199 case R.id.download_menu_open:
200 hideCompletedDownload();
Leon Scrogginsfedc4932010-01-26 14:15:01 -0500201 openOrDeleteCurrentDownload(false);
The Android Open Source Project0c908882009-03-03 19:32:16 -0800202 return true;
Leon Scroggins9be17332010-01-14 15:44:06 -0500203
204 case R.id.download_menu_delete:
Leon Scroggins9be17332010-01-14 15:44:06 -0500205 new AlertDialog.Builder(this)
206 .setTitle(R.string.download_delete_file)
207 .setIcon(android.R.drawable.ic_dialog_alert)
Leon Scrogginsfedc4932010-01-26 14:15:01 -0500208 .setMessage(mDownloadCursor.getString(mTitleColumnId))
Leon Scroggins9be17332010-01-14 15:44:06 -0500209 .setNegativeButton(R.string.cancel, null)
210 .setPositiveButton(R.string.ok,
211 new DialogInterface.OnClickListener() {
212 public void onClick(DialogInterface dialog,
213 int whichButton) {
Leon Scrogginsfedc4932010-01-26 14:15:01 -0500214 openOrDeleteCurrentDownload(true);
Leon Scroggins9be17332010-01-14 15:44:06 -0500215 }
216 })
217 .show();
218 break;
219
The Android Open Source Project0c908882009-03-03 19:32:16 -0800220 case R.id.download_menu_clear:
221 case R.id.download_menu_cancel:
Leon Scroggins9be17332010-01-14 15:44:06 -0500222 clearFromDownloads(mDownloadCursor.getLong(mIdColumnId));
The Android Open Source Project0c908882009-03-03 19:32:16 -0800223 return true;
224 }
225 return false;
226 }
227
228 @Override
Leon Scrogginsd080b182010-02-26 14:16:41 -0500229 protected void onPause() {
230 super.onPause();
231 if (mContentObserver != null) {
232 getContentResolver().unregisterContentObserver(mContentObserver);
233 // Note that we do not need to undo this in onResume, because the
234 // ContextMenu does not get reinvoked when the Activity resumes.
235 }
236 }
237
238 /*
239 * ContentObserver to update the ContextMenu if it is open when the
240 * corresponding download completes.
241 */
242 private class ChangeObserver extends ContentObserver {
243 private final Uri mTrack;
244 public ChangeObserver(Uri track) {
245 super(new Handler());
246 mTrack = track;
247 }
248
249 @Override
250 public boolean deliverSelfNotifications() {
251 return false;
252 }
253
254 @Override
255 public void onChange(boolean selfChange) {
Leon Scroggins2c0f6112010-03-12 18:09:39 -0500256 Cursor cursor = null;
257 try {
258 cursor = getContentResolver().query(mTrack,
259 new String[] { Downloads.Impl.COLUMN_STATUS }, null, null,
260 null);
261 if (cursor.moveToFirst() && Downloads.Impl.isStatusSuccess(
262 cursor.getInt(0))) {
263 // Do this right away, so we get no more updates.
264 getContentResolver().unregisterContentObserver(
265 mContentObserver);
266 // Post a runnable in case this ContentObserver gets notified
267 // before the one that updates the ListView.
268 mListView.post(new Runnable() {
269 public void run() {
270 // Close the context menu, reopen with up to date data.
271 closeContextMenu();
272 openContextMenu(mSelectedView);
273 }
274 });
275 }
276 } catch (IllegalStateException e) {
277 Log.e(LOGTAG, "onChange", e);
278 } finally {
279 if (cursor != null) cursor.close();
Leon Scrogginsd080b182010-02-26 14:16:41 -0500280 }
Leon Scrogginsd080b182010-02-26 14:16:41 -0500281 }
282 }
283
284 @Override
The Android Open Source Project0c908882009-03-03 19:32:16 -0800285 public void onCreateContextMenu(ContextMenu menu, View v,
286 ContextMenuInfo menuInfo) {
287 if (mDownloadCursor != null) {
Leon Scroggins24837452010-01-13 13:43:35 -0500288 ExpandableListView.ExpandableListContextMenuInfo info
289 = (ExpandableListView.ExpandableListContextMenuInfo) menuInfo;
290 long packedPosition = info.packedPosition;
291 // Only show a context menu for the child views
292 if (!mDownloadAdapter.moveCursorToPackedChildPosition(
293 packedPosition)) {
294 return;
295 }
296 mContextMenuPosition = packedPosition;
The Android Open Source Project0c908882009-03-03 19:32:16 -0800297 menu.setHeaderTitle(mDownloadCursor.getString(mTitleColumnId));
298
299 MenuInflater inflater = getMenuInflater();
300 int status = mDownloadCursor.getInt(mStatusColumnId);
Jean-Baptiste Queru1e5bad92010-01-14 16:09:03 -0800301 if (Downloads.Impl.isStatusSuccess(status)) {
The Android Open Source Project0c908882009-03-03 19:32:16 -0800302 inflater.inflate(R.menu.downloadhistorycontextfinished, menu);
Jean-Baptiste Queru1e5bad92010-01-14 16:09:03 -0800303 } else if (Downloads.Impl.isStatusError(status)) {
The Android Open Source Project0c908882009-03-03 19:32:16 -0800304 inflater.inflate(R.menu.downloadhistorycontextfailed, menu);
305 } else {
Leon Scrogginsd080b182010-02-26 14:16:41 -0500306 // In this case, the download is in progress. Set a
307 // ContentObserver so that we can know when it completes,
308 // and if it does, we can then update the context menu
309 Uri track = ContentUris.withAppendedId(
310 Downloads.Impl.CONTENT_URI,
311 mDownloadCursor.getLong(mIdColumnId));
312 if (mContentObserver != null) {
313 getContentResolver().unregisterContentObserver(
314 mContentObserver);
315 }
316 mContentObserver = new ChangeObserver(track);
317 mSelectedView = v;
318 getContentResolver().registerContentObserver(track, false,
319 mContentObserver);
The Android Open Source Project0c908882009-03-03 19:32:16 -0800320 inflater.inflate(R.menu.downloadhistorycontextrunning, menu);
321 }
322 }
Leon Scroggins24837452010-01-13 13:43:35 -0500323 super.onCreateContextMenu(menu, v, menuInfo);
The Android Open Source Project0c908882009-03-03 19:32:16 -0800324 }
325
326 /**
327 * This function is called to check the status of the download and if it
328 * has an error show an error dialog.
329 * @param id Row id of the download to check
Leon Scroggins24837452010-01-13 13:43:35 -0500330 * @return Group which contains the download
The Android Open Source Project0c908882009-03-03 19:32:16 -0800331 */
Leon Scroggins24837452010-01-13 13:43:35 -0500332 private int checkStatus(final long id) {
333 int groupToShow = mDownloadAdapter.groupFromChildId(id);
334 if (-1 == groupToShow) return 0;
335 int status = mDownloadCursor.getInt(mStatusColumnId);
Jean-Baptiste Queru1e5bad92010-01-14 16:09:03 -0800336 if (!Downloads.Impl.isStatusError(status)) {
Leon Scroggins24837452010-01-13 13:43:35 -0500337 return groupToShow;
The Android Open Source Project0c908882009-03-03 19:32:16 -0800338 }
Jean-Baptiste Queru1e5bad92010-01-14 16:09:03 -0800339 if (status == Downloads.Impl.STATUS_FILE_ERROR) {
Leon Scroggins24837452010-01-13 13:43:35 -0500340 String title = mDownloadCursor.getString(mTitleColumnId);
341 if (title == null || title.length() == 0) {
342 title = getString(R.string.download_unknown_filename);
The Android Open Source Project0c908882009-03-03 19:32:16 -0800343 }
Leon Scroggins24837452010-01-13 13:43:35 -0500344 String msg = getString(R.string.download_file_error_dlg_msg, title);
345 new AlertDialog.Builder(this)
346 .setTitle(R.string.download_file_error_dlg_title)
347 .setIcon(android.R.drawable.ic_popup_disk_full)
348 .setMessage(msg)
349 .setPositiveButton(R.string.ok, null)
350 .setNegativeButton(R.string.retry,
351 new DialogInterface.OnClickListener() {
352 public void onClick(DialogInterface dialog,
353 int whichButton) {
354 resumeDownload(id);
355 }
356 })
357 .show();
358 } else {
359 new AlertDialog.Builder(this)
360 .setTitle(R.string.download_failed_generic_dlg_title)
361 .setIcon(R.drawable.ssl_icon)
362 .setMessage(BrowserDownloadAdapter.getErrorText(status))
363 .setPositiveButton(R.string.ok, null)
364 .show();
The Android Open Source Project0c908882009-03-03 19:32:16 -0800365 }
Leon Scroggins24837452010-01-13 13:43:35 -0500366 return groupToShow;
The Android Open Source Project0c908882009-03-03 19:32:16 -0800367 }
368
369 /**
370 * Resume a given download
371 * @param id Row id of the download to resume
372 */
373 private void resumeDownload(final long id) {
374 // the relevant functionality doesn't exist in the download manager
375 }
376
377 /**
The Android Open Source Project0c908882009-03-03 19:32:16 -0800378 * Return the number of items in the list that can be canceled.
379 * @return count
380 */
381 private int getCancelableCount() {
382 // Count the number of items that will be canceled.
383 int count = 0;
384 if (mDownloadCursor != null) {
Leon Scrogginsb67db6b2010-02-26 17:58:31 -0500385 for (mDownloadCursor.moveToFirst(); !mDownloadCursor.isAfterLast();
The Android Open Source Project0c908882009-03-03 19:32:16 -0800386 mDownloadCursor.moveToNext()) {
387 int status = mDownloadCursor.getInt(mStatusColumnId);
Jean-Baptiste Queru1e5bad92010-01-14 16:09:03 -0800388 if (!Downloads.Impl.isStatusCompleted(status)) {
The Android Open Source Project0c908882009-03-03 19:32:16 -0800389 count++;
390 }
391 }
392 }
393
394 return count;
395 }
396
397 /**
398 * Prompt the user if they would like to clear the download history
399 */
400 private void promptCancelAll() {
401 int count = getCancelableCount();
402
403 // If there is nothing to do, just return
404 if (count == 0) {
405 return;
406 }
407
408 // Don't show the dialog if there is only one download
409 if (count == 1) {
410 cancelAllDownloads();
411 return;
412 }
413 String msg =
414 getString(R.string.download_cancel_dlg_msg, count);
415 new AlertDialog.Builder(this)
416 .setTitle(R.string.download_cancel_dlg_title)
417 .setIcon(R.drawable.ssl_icon)
418 .setMessage(msg)
419 .setPositiveButton(R.string.ok,
420 new DialogInterface.OnClickListener() {
421 public void onClick(DialogInterface dialog,
422 int whichButton) {
423 cancelAllDownloads();
424 }
425 })
426 .setNegativeButton(R.string.cancel, null)
427 .show();
428 }
429
430 /**
431 * Cancel all downloads. As canceled downloads are not
432 * listed, we removed them from the db. Removing a download
433 * record, cancels the download.
434 */
435 private void cancelAllDownloads() {
436 if (mDownloadCursor.moveToFirst()) {
437 StringBuilder where = new StringBuilder();
438 boolean firstTime = true;
439 while (!mDownloadCursor.isAfterLast()) {
440 int status = mDownloadCursor.getInt(mStatusColumnId);
Jean-Baptiste Queru1e5bad92010-01-14 16:09:03 -0800441 if (!Downloads.Impl.isStatusCompleted(status)) {
The Android Open Source Project0c908882009-03-03 19:32:16 -0800442 if (firstTime) {
443 firstTime = false;
444 } else {
445 where.append(" OR ");
446 }
447 where.append("( ");
Jean-Baptiste Queru1e5bad92010-01-14 16:09:03 -0800448 where.append(Downloads.Impl._ID);
The Android Open Source Project0c908882009-03-03 19:32:16 -0800449 where.append(" = '");
450 where.append(mDownloadCursor.getLong(mIdColumnId));
451 where.append("' )");
452 }
453 mDownloadCursor.moveToNext();
454 }
455 if (!firstTime) {
Jean-Baptiste Queru1e5bad92010-01-14 16:09:03 -0800456 getContentResolver().delete(Downloads.Impl.CONTENT_URI,
The Android Open Source Project0c908882009-03-03 19:32:16 -0800457 where.toString(), null);
458 }
459 }
460 }
461
462 private int getClearableCount() {
463 int count = 0;
464 if (mDownloadCursor.moveToFirst()) {
465 while (!mDownloadCursor.isAfterLast()) {
466 int status = mDownloadCursor.getInt(mStatusColumnId);
Jean-Baptiste Queru1e5bad92010-01-14 16:09:03 -0800467 if (Downloads.Impl.isStatusCompleted(status)) {
The Android Open Source Project0c908882009-03-03 19:32:16 -0800468 count++;
469 }
470 mDownloadCursor.moveToNext();
471 }
472 }
473 return count;
474 }
Leon Scroggins4cf7de02010-01-21 10:05:59 -0500475
The Android Open Source Project0c908882009-03-03 19:32:16 -0800476 /**
Leon Scrogginsfedc4932010-01-26 14:15:01 -0500477 * Open or delete content where the download db cursor currently is. Sends
478 * an Intent to perform the action.
479 * @param delete If true, delete the content. Otherwise open it.
The Android Open Source Project0c908882009-03-03 19:32:16 -0800480 */
Leon Scrogginsfedc4932010-01-26 14:15:01 -0500481 private void openOrDeleteCurrentDownload(boolean delete) {
482 int packageColumnId = mDownloadCursor.getColumnIndexOrThrow(
483 Downloads.Impl.COLUMN_NOTIFICATION_PACKAGE);
484 String packageName = mDownloadCursor.getString(packageColumnId);
485 Intent intent = new Intent(delete ? Intent.ACTION_DELETE
486 : Downloads.Impl.ACTION_NOTIFICATION_CLICKED);
487 Uri contentUri = ContentUris.withAppendedId(
488 Downloads.Impl.CONTENT_URI,
489 mDownloadCursor.getLong(mIdColumnId));
490 intent.setData(contentUri);
491 intent.setPackage(packageName);
492 sendBroadcast(intent);
The Android Open Source Project0c908882009-03-03 19:32:16 -0800493 }
494
Leon Scroggins24837452010-01-13 13:43:35 -0500495 @Override
496 public boolean onChildClick(ExpandableListView parent, View v,
497 int groupPosition, int childPosition, long id) {
The Android Open Source Project0c908882009-03-03 19:32:16 -0800498 // Open the selected item
Leon Scroggins24837452010-01-13 13:43:35 -0500499 mDownloadAdapter.moveCursorToChildPosition(groupPosition,
500 childPosition);
The Android Open Source Project0c908882009-03-03 19:32:16 -0800501
502 hideCompletedDownload();
503
504 int status = mDownloadCursor.getInt(mStatusColumnId);
Jean-Baptiste Queru1e5bad92010-01-14 16:09:03 -0800505 if (Downloads.Impl.isStatusSuccess(status)) {
The Android Open Source Project0c908882009-03-03 19:32:16 -0800506 // Open it if it downloaded successfully
Leon Scrogginsfedc4932010-01-26 14:15:01 -0500507 openOrDeleteCurrentDownload(false);
The Android Open Source Project0c908882009-03-03 19:32:16 -0800508 } else {
509 // Check to see if there is an error.
510 checkStatus(id);
511 }
Leon Scroggins24837452010-01-13 13:43:35 -0500512 return true;
The Android Open Source Project0c908882009-03-03 19:32:16 -0800513 }
514
515 /**
516 * hides the notification for the download pointed by mDownloadCursor
517 * if the download has completed.
518 */
519 private void hideCompletedDownload() {
520 int status = mDownloadCursor.getInt(mStatusColumnId);
521
Jean-Baptiste Queru1e5bad92010-01-14 16:09:03 -0800522 int visibilityColumn = mDownloadCursor.getColumnIndexOrThrow(
523 Downloads.Impl.COLUMN_VISIBILITY);
The Android Open Source Project0c908882009-03-03 19:32:16 -0800524 int visibility = mDownloadCursor.getInt(visibilityColumn);
525
Jean-Baptiste Queru1e5bad92010-01-14 16:09:03 -0800526 if (Downloads.Impl.isStatusCompleted(status) &&
527 visibility == Downloads.Impl.VISIBILITY_VISIBLE_NOTIFY_COMPLETED) {
The Android Open Source Project0c908882009-03-03 19:32:16 -0800528 ContentValues values = new ContentValues();
Jean-Baptiste Queru1e5bad92010-01-14 16:09:03 -0800529 values.put(Downloads.Impl.COLUMN_VISIBILITY, Downloads.Impl.VISIBILITY_VISIBLE);
The Android Open Source Project0c908882009-03-03 19:32:16 -0800530 getContentResolver().update(
Jean-Baptiste Queru1e5bad92010-01-14 16:09:03 -0800531 ContentUris.withAppendedId(Downloads.Impl.CONTENT_URI,
The Android Open Source Project0c908882009-03-03 19:32:16 -0800532 mDownloadCursor.getLong(mIdColumnId)), values, null, null);
533 }
534 }
535}