AttachmentActionHandler.java revision 5ba812e028d7b57e1014caa762e842b25e6752b8
1/* 2 * Copyright (C) 2012 Google Inc. 3 * Licensed to The Android Open Source Project. 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18package com.android.mail.browse; 19 20import android.app.DialogFragment; 21import android.app.Fragment; 22import android.app.FragmentManager; 23import android.app.FragmentTransaction; 24import android.content.ActivityNotFoundException; 25import android.content.ContentValues; 26import android.content.Context; 27import android.content.DialogInterface; 28import android.content.Intent; 29import android.net.Uri; 30import android.os.Handler; 31import android.os.Parcelable; 32 33import com.android.mail.providers.Attachment; 34import com.android.mail.providers.UIProvider.AttachmentColumns; 35import com.android.mail.providers.UIProvider.AttachmentDestination; 36import com.android.mail.providers.UIProvider.AttachmentState; 37import com.android.mail.utils.LogTag; 38import com.android.mail.utils.LogUtils; 39import com.android.mail.utils.Utils; 40 41import java.util.ArrayList; 42import java.util.List; 43 44public class AttachmentActionHandler { 45 private static final String PROGRESS_FRAGMENT_TAG = "attachment-progress"; 46 47 private Attachment mAttachment; 48 private boolean mDialogClosed; 49 50 private final AttachmentCommandHandler mCommandHandler; 51 private final AttachmentViewInterface mView; 52 private final Context mContext; 53 private final Handler mHandler; 54 private FragmentManager mFragmentManager; 55 56 private static final String LOG_TAG = LogTag.getLogTag(); 57 58 public AttachmentActionHandler(Context context, AttachmentViewInterface view) { 59 mCommandHandler = new AttachmentCommandHandler(context); 60 mView = view; 61 mContext = context; 62 mDialogClosed = false; 63 mHandler = new Handler(); 64 } 65 66 public void initialize(FragmentManager fragmentManager) { 67 mFragmentManager = fragmentManager; 68 } 69 70 public void setAttachment(Attachment attachment) { 71 mAttachment = attachment; 72 } 73 74 public void showAttachment(int destination) { 75 // If the caller requested that this attachments be saved to the external storage, we should 76 // verify that the it was saved there. 77 if (mAttachment.isPresentLocally() && 78 (destination == AttachmentDestination.CACHE || 79 mAttachment.destination == destination)) { 80 mView.viewAttachment(); 81 } else { 82 showDownloadingDialog(destination); 83 startDownloadingAttachment(destination); 84 } 85 } 86 87 public void showAndDownloadAttachments() { 88 final List<Attachment> attachments = mView.getAttachments(); 89 90 for (final Attachment attachment : attachments) { 91 if (!attachment.isPresentLocally()) { 92 startDownloadingAttachment(attachment, AttachmentDestination.CACHE); 93 } 94 } 95 96 mView.viewAttachment(); 97 } 98 99 public void startDownloadingAttachment(int destination) { 100 startDownloadingAttachment(mAttachment, destination); 101 } 102 103 private void startDownloadingAttachment(Attachment attachment, int destination) { 104 final ContentValues params = new ContentValues(2); 105 params.put(AttachmentColumns.STATE, AttachmentState.DOWNLOADING); 106 params.put(AttachmentColumns.DESTINATION, destination); 107 108 mCommandHandler.sendCommand(attachment.uri, params); 109 } 110 111 public void cancelAttachment() { 112 final ContentValues params = new ContentValues(1); 113 params.put(AttachmentColumns.STATE, AttachmentState.NOT_SAVED); 114 115 mCommandHandler.sendCommand(mAttachment.uri, params); 116 } 117 118 public void startRedownloadingAttachment(Attachment attachment) { 119 showDownloadingDialog(attachment.destination); 120 final ContentValues params = new ContentValues(2); 121 params.put(AttachmentColumns.STATE, AttachmentState.REDOWNLOADING); 122 params.put(AttachmentColumns.DESTINATION, attachment.destination); 123 124 mCommandHandler.sendCommand(attachment.uri, params); 125 } 126 127 /** 128 * Displays a loading dialog to be used for downloading attachments. 129 * Must be called on the UI thread. 130 */ 131 private void showDownloadingDialog(int destination) { 132 final FragmentTransaction ft = mFragmentManager.beginTransaction(); 133 final Fragment prev = mFragmentManager.findFragmentByTag(PROGRESS_FRAGMENT_TAG); 134 if (prev != null) { 135 ft.remove(prev); 136 } 137 ft.addToBackStack(null); 138 139 // Create and show the dialog. 140 final DialogFragment newFragment = AttachmentProgressDialogFragment.newInstance( 141 mAttachment, destination); 142 newFragment.show(ft, PROGRESS_FRAGMENT_TAG); 143 } 144 145 public void onDismiss(DialogInterface dialog) { 146 mDialogClosed = true; 147 } 148 149 public void onCancel(DialogInterface dialog) { 150 cancelAttachment(); 151 } 152 153 /** 154 * Update progress-related views. Will also trigger a view intent if a progress dialog was 155 * previously brought up (by tapping 'View') and the download has now finished. 156 */ 157 public void updateStatus(boolean loaderResult) { 158 final boolean showProgress = mAttachment.shouldShowProgress(); 159 160 final AttachmentProgressDialogFragment dialog = (AttachmentProgressDialogFragment) 161 mFragmentManager.findFragmentByTag(PROGRESS_FRAGMENT_TAG); 162 if (dialog != null && dialog.isShowingDialogForAttachment(mAttachment)) { 163 dialog.setProgress(mAttachment.downloadedSize); 164 165 // We don't want the progress bar to switch back to indeterminate mode after 166 // have been in determinate progress mode. 167 final boolean indeterminate = !showProgress && dialog.isIndeterminate(); 168 dialog.setIndeterminate(indeterminate); 169 170 if (loaderResult && !mAttachment.isDownloading()) { 171 mHandler.post(new Runnable() { 172 @Override 173 public void run() { 174 dialog.dismiss(); 175 } 176 }); 177 } 178 179 if (mAttachment.state == AttachmentState.SAVED) { 180 mView.viewAttachment(); 181 } 182 } else { 183 mView.updateProgress(showProgress); 184 } 185 186 // Call on update status for the view so that it can do some specific things. 187 mView.onUpdateStatus(); 188 } 189 190 public boolean isProgressDialogVisible() { 191 final Fragment dialog = mFragmentManager.findFragmentByTag(PROGRESS_FRAGMENT_TAG); 192 return dialog != null && dialog.isVisible(); 193 } 194 195 public void shareAttachment() { 196 if (mAttachment.contentUri == null) { 197 return; 198 } 199 200 Intent intent = new Intent(Intent.ACTION_SEND); 201 intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION 202 | Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET); 203 204 final Uri uri = Utils.normalizeUri(mAttachment.contentUri); 205 intent.putExtra(Intent.EXTRA_STREAM, uri); 206 intent.setType(Utils.normalizeMimeType(mAttachment.contentType)); 207 208 try { 209 mContext.startActivity(intent); 210 } catch (ActivityNotFoundException e) { 211 // couldn't find activity for SEND intent 212 LogUtils.e(LOG_TAG, "Couldn't find Activity for intent", e); 213 } 214 } 215 216 public void shareAttachments(ArrayList<Parcelable> uris) { 217 Intent intent = new Intent(Intent.ACTION_SEND_MULTIPLE); 218 intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION 219 | Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET); 220 221 intent.setType("image/*"); 222 intent.putParcelableArrayListExtra( 223 Intent.EXTRA_STREAM, uris); 224 225 try { 226 mContext.startActivity(intent); 227 } catch (ActivityNotFoundException e) { 228 // couldn't find activity for SEND_MULTIPLE intent 229 LogUtils.e(LOG_TAG, "Couldn't find Activity for intent", e); 230 } 231 } 232 233 /** 234 * Returns true if this is the first time this method has been called after 235 * the progress dialog was closed. Necessary to prevent a brief flicker where the 236 * cancel button would appear after closing the progress dialog. Subsequent 237 * calls to this method will return false until the progress dialog is 238 * opened again. 239 * @return true if this is the first time this method has been called 240 * since a progress dialog was visible. false otherwise. 241 */ 242 public boolean dialogJustClosed() { 243 final boolean closed = mDialogClosed; 244 mDialogClosed = false; 245 return closed; 246 } 247} 248