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