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