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 18 package com.android.mail.browse; 19 20 21 import android.app.DialogFragment; 22 import android.app.Fragment; 23 import android.app.FragmentManager; 24 import android.app.FragmentTransaction; 25 import android.content.ActivityNotFoundException; 26 import android.content.ContentValues; 27 import android.content.Context; 28 import android.content.Intent; 29 import android.net.Uri; 30 import android.os.Handler; 31 import android.os.Parcelable; 32 33 import com.android.mail.providers.Attachment; 34 import com.android.mail.providers.UIProvider; 35 import com.android.mail.providers.UIProvider.AttachmentColumns; 36 import com.android.mail.providers.UIProvider.AttachmentContentValueKeys; 37 import com.android.mail.providers.UIProvider.AttachmentDestination; 38 import com.android.mail.providers.UIProvider.AttachmentState; 39 import com.android.mail.utils.LogTag; 40 import com.android.mail.utils.LogUtils; 41 import com.android.mail.utils.Utils; 42 43 import java.util.ArrayList; 44 45 public class AttachmentActionHandler { 46 private static final String PROGRESS_FRAGMENT_TAG = "attachment-progress"; 47 48 private Attachment mAttachment; 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 private boolean mViewOnFinish; 56 57 private static final String LOG_TAG = LogTag.getLogTag(); 58 59 public AttachmentActionHandler(Context context, AttachmentViewInterface view) { 60 mCommandHandler = new AttachmentCommandHandler(context); 61 mView = view; 62 mContext = context; 63 mHandler = new Handler(); 64 mViewOnFinish = true; 65 } 66 67 public void initialize(FragmentManager fragmentManager) { 68 mFragmentManager = fragmentManager; 69 } 70 71 public void setAttachment(Attachment attachment) { 72 mAttachment = attachment; 73 } 74 75 public void setViewOnFinish(boolean viewOnFinish) { 76 mViewOnFinish = viewOnFinish; 77 } 78 79 public void showAttachment(int destination) { 80 if (mView == null) { 81 return; 82 } 83 84 // If the caller requested that this attachments be saved to the external storage, we should 85 // verify that the it was saved there. 86 if (mAttachment.isPresentLocally() && 87 (destination == AttachmentDestination.CACHE || 88 mAttachment.destination == destination)) { 89 mView.viewAttachment(); 90 } else { 91 showDownloadingDialog(); 92 startDownloadingAttachment(destination); 93 } 94 } 95 96 /** 97 * Start downloading the full size attachment set with 98 * {@link #setAttachment(Attachment)} immediately. 99 */ 100 public void startDownloadingAttachment(int destination) { 101 startDownloadingAttachment(destination, UIProvider.AttachmentRendition.BEST, 0, false); 102 } 103 104 public void startDownloadingAttachment( 105 int destination, int rendition, int additionalPriority, boolean delayDownload) { 106 startDownloadingAttachment( 107 mAttachment, destination, rendition, additionalPriority, delayDownload); 108 } 109 110 private void startDownloadingAttachment( 111 Attachment attachment, int destination, int rendition, int additionalPriority, 112 boolean delayDownload) { 113 final ContentValues params = new ContentValues(5); 114 params.put(AttachmentColumns.STATE, AttachmentState.DOWNLOADING); 115 params.put(AttachmentColumns.DESTINATION, destination); 116 params.put(AttachmentContentValueKeys.RENDITION, rendition); 117 params.put(AttachmentContentValueKeys.ADDITIONAL_PRIORITY, additionalPriority); 118 params.put(AttachmentContentValueKeys.DELAY_DOWNLOAD, delayDownload); 119 120 mCommandHandler.sendCommand(attachment.uri, params); 121 } 122 123 public void cancelAttachment() { 124 final ContentValues params = new ContentValues(1); 125 params.put(AttachmentColumns.STATE, AttachmentState.NOT_SAVED); 126 127 mCommandHandler.sendCommand(mAttachment.uri, params); 128 } 129 130 public void startRedownloadingAttachment(Attachment attachment) { 131 final ContentValues params = new ContentValues(2); 132 params.put(AttachmentColumns.STATE, AttachmentState.REDOWNLOADING); 133 params.put(AttachmentColumns.DESTINATION, attachment.destination); 134 135 mCommandHandler.sendCommand(attachment.uri, params); 136 } 137 138 /** 139 * Displays a loading dialog to be used for downloading attachments. 140 * Must be called on the UI thread. 141 */ 142 public void showDownloadingDialog() { 143 final FragmentTransaction ft = mFragmentManager.beginTransaction(); 144 final Fragment prev = mFragmentManager.findFragmentByTag(PROGRESS_FRAGMENT_TAG); 145 if (prev != null) { 146 ft.remove(prev); 147 } 148 ft.addToBackStack(null); 149 150 // Create and show the dialog. 151 final DialogFragment newFragment = AttachmentProgressDialogFragment.newInstance( 152 mAttachment); 153 newFragment.show(ft, PROGRESS_FRAGMENT_TAG); 154 } 155 156 /** 157 * Update progress-related views. Will also trigger a view intent if a progress dialog was 158 * previously brought up (by tapping 'View') and the download has now finished. 159 */ 160 public void updateStatus(boolean loaderResult) { 161 if (mView == null) { 162 return; 163 } 164 165 final boolean showProgress = mAttachment.shouldShowProgress(); 166 167 final AttachmentProgressDialogFragment dialog = (AttachmentProgressDialogFragment) 168 mFragmentManager.findFragmentByTag(PROGRESS_FRAGMENT_TAG); 169 if (dialog != null && dialog.isShowingDialogForAttachment(mAttachment)) { 170 dialog.setProgress(mAttachment.downloadedSize); 171 172 // We don't want the progress bar to switch back to indeterminate mode after 173 // have been in determinate progress mode. 174 final boolean indeterminate = !showProgress && dialog.isIndeterminate(); 175 dialog.setIndeterminate(indeterminate); 176 177 if (loaderResult && mAttachment.isDownloadFinishedOrFailed()) { 178 mHandler.post(new Runnable() { 179 @Override 180 public void run() { 181 dialog.dismiss(); 182 } 183 }); 184 } 185 186 if (mAttachment.state == AttachmentState.SAVED && mViewOnFinish) { 187 mView.viewAttachment(); 188 } 189 } else { 190 mView.updateProgress(showProgress); 191 } 192 193 // Call on update status for the view so that it can do some specific things. 194 mView.onUpdateStatus(); 195 } 196 197 public boolean isProgressDialogVisible() { 198 final Fragment dialog = mFragmentManager.findFragmentByTag(PROGRESS_FRAGMENT_TAG); 199 return dialog != null && dialog.isVisible(); 200 } 201 202 public void shareAttachment() { 203 if (mAttachment.contentUri == null) { 204 return; 205 } 206 207 Intent intent = new Intent(Intent.ACTION_SEND); 208 intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION 209 | Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET); 210 211 final Uri uri = Utils.normalizeUri(mAttachment.contentUri); 212 intent.putExtra(Intent.EXTRA_STREAM, uri); 213 intent.setType(Utils.normalizeMimeType(mAttachment.getContentType())); 214 215 try { 216 mContext.startActivity(intent); 217 } catch (ActivityNotFoundException e) { 218 // couldn't find activity for SEND intent 219 LogUtils.e(LOG_TAG, "Couldn't find Activity for intent", e); 220 } 221 } 222 223 public void shareAttachments(ArrayList<Parcelable> uris) { 224 Intent intent = new Intent(Intent.ACTION_SEND_MULTIPLE); 225 intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION 226 | Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET); 227 228 intent.setType("image/*"); 229 intent.putParcelableArrayListExtra( 230 Intent.EXTRA_STREAM, uris); 231 232 try { 233 mContext.startActivity(intent); 234 } catch (ActivityNotFoundException e) { 235 // couldn't find activity for SEND_MULTIPLE intent 236 LogUtils.e(LOG_TAG, "Couldn't find Activity for intent", e); 237 } 238 } 239 } 240