• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
onCreate(Bundle savedInstanceState)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 
sendRunningDownloadClickedBroadcast(long id)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 {
show(FragmentManager fm, long id, long size)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
onCreateDialog(Bundle savedInstanceState)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
onDismiss(DialogInterface dialog)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 {
show(FragmentManager fm, long id, int reason)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
onCreateDialog(Bundle savedInstanceState)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
onDismiss(DialogInterface dialog)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