Home | History | Annotate | Download | only in ui
      1 /*
      2  * Copyright (C) 2013 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 
     17 package com.android.providers.downloads.ui;
     18 
     19 import android.app.Activity;
     20 import android.app.AlertDialog;
     21 import android.app.Dialog;
     22 import android.app.DialogFragment;
     23 import android.app.DownloadManager;
     24 import android.app.DownloadManager.Query;
     25 import android.app.FragmentManager;
     26 import android.content.ActivityNotFoundException;
     27 import android.content.ContentUris;
     28 import android.content.Context;
     29 import android.content.DialogInterface;
     30 import android.content.Intent;
     31 import android.database.Cursor;
     32 import android.net.Uri;
     33 import android.os.Bundle;
     34 import android.provider.DocumentsContract;
     35 import android.util.Log;
     36 import android.widget.Toast;
     37 
     38 import com.android.providers.downloads.Constants;
     39 import com.android.providers.downloads.OpenHelper;
     40 import com.android.providers.downloads.RawDocumentsHelper;
     41 
     42 import libcore.io.IoUtils;
     43 
     44 /**
     45  * Intercept all download clicks to provide special behavior. For example,
     46  * PackageInstaller really wants raw file paths.
     47  */
     48 public class TrampolineActivity extends Activity {
     49     private static final String TAG_PAUSED = "paused";
     50     private static final String TAG_FAILED = "failed";
     51 
     52     private static final String KEY_ID = "id";
     53     private static final String KEY_REASON = "reason";
     54     private static final String KEY_SIZE = "size";
     55 
     56     @Override
     57     protected void onCreate(Bundle savedInstanceState) {
     58         super.onCreate(savedInstanceState);
     59 
     60         Uri documentUri = getIntent().getData();
     61         if (RawDocumentsHelper.isRawDocId(DocumentsContract.getDocumentId(documentUri))) {
     62             if (!RawDocumentsHelper.startViewIntent(this, documentUri)) {
     63                 Toast.makeText(this, R.string.download_no_application_title, Toast.LENGTH_SHORT)
     64                         .show();
     65             }
     66             finish();
     67             return;
     68         }
     69 
     70         final long id = ContentUris.parseId(documentUri);
     71         final DownloadManager dm = (DownloadManager) getSystemService(Context.DOWNLOAD_SERVICE);
     72         dm.setAccessAllDownloads(true);
     73 
     74         final int status;
     75         final int reason;
     76         final long size;
     77 
     78         final Cursor cursor = dm.query(new Query().setFilterById(id));
     79         try {
     80             if (cursor.moveToFirst()) {
     81                 status = cursor.getInt(cursor.getColumnIndexOrThrow(DownloadManager.COLUMN_STATUS));
     82                 reason = cursor.getInt(cursor.getColumnIndexOrThrow(DownloadManager.COLUMN_REASON));
     83                 size = cursor.getLong(
     84                         cursor.getColumnIndexOrThrow(DownloadManager.COLUMN_TOTAL_SIZE_BYTES));
     85             } else {
     86                 Toast.makeText(this, R.string.dialog_file_missing_body, Toast.LENGTH_SHORT).show();
     87                 finish();
     88                 return;
     89             }
     90         } finally {
     91             IoUtils.closeQuietly(cursor);
     92         }
     93 
     94         Log.d(Constants.TAG, "Found " + id + " with status " + status + ", reason " + reason);
     95         switch (status) {
     96             case DownloadManager.STATUS_PENDING:
     97             case DownloadManager.STATUS_RUNNING:
     98                 sendRunningDownloadClickedBroadcast(id);
     99                 finish();
    100                 break;
    101 
    102             case DownloadManager.STATUS_PAUSED:
    103                 if (reason == DownloadManager.PAUSED_QUEUED_FOR_WIFI) {
    104                     PausedDialogFragment.show(getFragmentManager(), id, size);
    105                 } else {
    106                     sendRunningDownloadClickedBroadcast(id);
    107                     finish();
    108                 }
    109                 break;
    110 
    111             case DownloadManager.STATUS_SUCCESSFUL:
    112                 if (!OpenHelper.startViewIntent(this, id, 0)) {
    113                     Toast.makeText(this, R.string.download_no_application_title, Toast.LENGTH_SHORT)
    114                             .show();
    115                 }
    116                 finish();
    117                 break;
    118 
    119             case DownloadManager.STATUS_FAILED:
    120                 FailedDialogFragment.show(getFragmentManager(), id, reason);
    121                 break;
    122         }
    123     }
    124 
    125     private void sendRunningDownloadClickedBroadcast(long id) {
    126         final Intent intent = new Intent(Constants.ACTION_LIST);
    127         intent.setPackage(Constants.PROVIDER_PACKAGE_NAME);
    128         intent.putExtra(DownloadManager.EXTRA_NOTIFICATION_CLICK_DOWNLOAD_IDS, new long[] { id });
    129         sendBroadcast(intent);
    130     }
    131 
    132     public static class PausedDialogFragment extends DialogFragment {
    133         public static void show(FragmentManager fm, long id, long size) {
    134             final PausedDialogFragment dialog = new PausedDialogFragment();
    135             final Bundle args = new Bundle();
    136             args.putLong(KEY_ID, id);
    137             args.putLong(KEY_SIZE, size);
    138             dialog.setArguments(args);
    139             dialog.show(fm, TAG_PAUSED);
    140         }
    141 
    142         @Override
    143         public Dialog onCreateDialog(Bundle savedInstanceState) {
    144             final Context context = getActivity();
    145 
    146             final DownloadManager dm = (DownloadManager) context.getSystemService(
    147                     Context.DOWNLOAD_SERVICE);
    148             dm.setAccessAllDownloads(true);
    149 
    150             final long id = getArguments().getLong(KEY_ID);
    151             final long size = getArguments().getLong(KEY_SIZE);
    152 
    153             final AlertDialog.Builder builder = new AlertDialog.Builder(
    154                     context, android.R.style.Theme_DeviceDefault_Light_Dialog_Alert);
    155             builder.setTitle(R.string.dialog_title_queued_body);
    156             builder.setMessage(R.string.dialog_queued_body);
    157 
    158             final Long maxSize = DownloadManager.getMaxBytesOverMobile(context);
    159             if (maxSize != null && size > maxSize) {
    160                 // When we have a max size, we have no choice
    161                 builder.setPositiveButton(R.string.keep_queued_download, null);
    162             } else {
    163                 // Give user the choice of starting now
    164                 builder.setPositiveButton(R.string.start_now_download,
    165                         new DialogInterface.OnClickListener() {
    166                             @Override
    167                             public void onClick(DialogInterface dialog, int which) {
    168                                 dm.forceDownload(id);
    169                             }
    170                         });
    171             }
    172 
    173             builder.setNegativeButton(
    174                     R.string.remove_download, new DialogInterface.OnClickListener() {
    175                         @Override
    176                         public void onClick(DialogInterface dialog, int which) {
    177                             dm.remove(id);
    178                         }
    179                     });
    180 
    181             return builder.create();
    182         }
    183 
    184         @Override
    185         public void onDismiss(DialogInterface dialog) {
    186             super.onDismiss(dialog);
    187             final Activity activity = getActivity();
    188             if (activity != null) {
    189                 activity.finish();
    190             }
    191         }
    192     }
    193 
    194     public static class FailedDialogFragment extends DialogFragment {
    195         public static void show(FragmentManager fm, long id, int reason) {
    196             final FailedDialogFragment dialog = new FailedDialogFragment();
    197             final Bundle args = new Bundle();
    198             args.putLong(KEY_ID, id);
    199             args.putInt(KEY_REASON, reason);
    200             dialog.setArguments(args);
    201             dialog.show(fm, TAG_FAILED);
    202         }
    203 
    204         @Override
    205         public Dialog onCreateDialog(Bundle savedInstanceState) {
    206             final Context context = getActivity();
    207 
    208             final DownloadManager dm = (DownloadManager) context.getSystemService(
    209                     Context.DOWNLOAD_SERVICE);
    210             dm.setAccessAllDownloads(true);
    211 
    212             final long id = getArguments().getLong(KEY_ID);
    213             final int reason = getArguments().getInt(KEY_REASON);
    214 
    215             final AlertDialog.Builder builder = new AlertDialog.Builder(
    216                     context, android.R.style.Theme_DeviceDefault_Light_Dialog_Alert);
    217             builder.setTitle(R.string.dialog_title_not_available);
    218 
    219             switch (reason) {
    220                 case DownloadManager.ERROR_FILE_ALREADY_EXISTS:
    221                     builder.setMessage(R.string.dialog_file_already_exists);
    222                     break;
    223                 case DownloadManager.ERROR_INSUFFICIENT_SPACE:
    224                     builder.setMessage(R.string.dialog_insufficient_space_on_external);
    225                     break;
    226                 case DownloadManager.ERROR_DEVICE_NOT_FOUND:
    227                     builder.setMessage(R.string.dialog_media_not_found);
    228                     break;
    229                 case DownloadManager.ERROR_CANNOT_RESUME:
    230                     builder.setMessage(R.string.dialog_cannot_resume);
    231                     break;
    232                 default:
    233                     builder.setMessage(R.string.dialog_failed_body);
    234             }
    235 
    236             builder.setNegativeButton(
    237                     R.string.delete_download, new DialogInterface.OnClickListener() {
    238                         @Override
    239                         public void onClick(DialogInterface dialog, int which) {
    240                             dm.remove(id);
    241                         }
    242                     });
    243 
    244             builder.setPositiveButton(
    245                     R.string.retry_download, new DialogInterface.OnClickListener() {
    246                         @Override
    247                         public void onClick(DialogInterface dialog, int which) {
    248                             dm.restartDownload(id);
    249                         }
    250                     });
    251 
    252             return builder.create();
    253         }
    254 
    255         @Override
    256         public void onDismiss(DialogInterface dialog) {
    257             super.onDismiss(dialog);
    258             final Activity activity = getActivity();
    259             if (activity != null) {
    260                 activity.finish();
    261             }
    262         }
    263     }
    264 }
    265