AttachmentActionHandler.java revision 47ca4e2a4c2d7387a7dd8d1925e2512acc553eab
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        final ContentValues params = new ContentValues(2);
120        params.put(AttachmentColumns.STATE, AttachmentState.REDOWNLOADING);
121        params.put(AttachmentColumns.DESTINATION, attachment.destination);
122
123        mCommandHandler.sendCommand(attachment.uri, params);
124    }
125
126    /**
127     * Displays a loading dialog to be used for downloading attachments.
128     * Must be called on the UI thread.
129     */
130    private void showDownloadingDialog(int destination) {
131        final FragmentTransaction ft = mFragmentManager.beginTransaction();
132        final Fragment prev = mFragmentManager.findFragmentByTag(PROGRESS_FRAGMENT_TAG);
133        if (prev != null) {
134            ft.remove(prev);
135        }
136        ft.addToBackStack(null);
137
138         // Create and show the dialog.
139        final DialogFragment newFragment = AttachmentProgressDialogFragment.newInstance(
140                mAttachment, destination);
141        newFragment.show(ft, PROGRESS_FRAGMENT_TAG);
142    }
143
144    public void onDismiss(DialogInterface dialog) {
145        mDialogClosed = true;
146    }
147
148    public void onCancel(DialogInterface dialog) {
149        cancelAttachment();
150    }
151
152    /**
153     * Update progress-related views. Will also trigger a view intent if a progress dialog was
154     * previously brought up (by tapping 'View') and the download has now finished.
155     */
156    public void updateStatus(boolean loaderResult) {
157        final boolean showProgress = mAttachment.shouldShowProgress();
158
159        final AttachmentProgressDialogFragment dialog = (AttachmentProgressDialogFragment)
160                mFragmentManager.findFragmentByTag(PROGRESS_FRAGMENT_TAG);
161        if (dialog != null && dialog.isShowingDialogForAttachment(mAttachment)) {
162            dialog.setProgress(mAttachment.downloadedSize);
163
164            // We don't want the progress bar to switch back to indeterminate mode after
165            // have been in determinate progress mode.
166            final boolean indeterminate = !showProgress && dialog.isIndeterminate();
167            dialog.setIndeterminate(indeterminate);
168
169            if (loaderResult && !mAttachment.isDownloading()) {
170                mHandler.post(new Runnable() {
171                    @Override
172                    public void run() {
173                        dialog.dismiss();
174                    }
175                });
176            }
177
178            if (mAttachment.state == AttachmentState.SAVED) {
179                mView.viewAttachment();
180            }
181        } else {
182            mView.updateProgress(showProgress);
183        }
184
185        // Call on update status for the view so that it can do some specific things.
186        mView.onUpdateStatus();
187    }
188
189    public boolean isProgressDialogVisible() {
190        final Fragment dialog = mFragmentManager.findFragmentByTag(PROGRESS_FRAGMENT_TAG);
191        return dialog != null && dialog.isVisible();
192    }
193
194    public void shareAttachment() {
195        if (mAttachment.contentUri == null) {
196            return;
197        }
198
199        Intent intent = new Intent(Intent.ACTION_SEND);
200        intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION
201                | Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
202
203        final Uri uri = Utils.normalizeUri(mAttachment.contentUri);
204        intent.putExtra(Intent.EXTRA_STREAM, uri);
205        intent.setType(Utils.normalizeMimeType(mAttachment.contentType));
206
207        try {
208            mContext.startActivity(intent);
209        } catch (ActivityNotFoundException e) {
210            // couldn't find activity for SEND intent
211            LogUtils.e(LOG_TAG, "Couldn't find Activity for intent", e);
212        }
213    }
214
215    public void shareAttachments(ArrayList<Parcelable> uris) {
216        Intent intent = new Intent(Intent.ACTION_SEND_MULTIPLE);
217        intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION
218                | Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
219
220        intent.setType("image/*");
221        intent.putParcelableArrayListExtra(
222                Intent.EXTRA_STREAM, uris);
223
224        try {
225            mContext.startActivity(intent);
226        } catch (ActivityNotFoundException e) {
227            // couldn't find activity for SEND_MULTIPLE intent
228            LogUtils.e(LOG_TAG, "Couldn't find Activity for intent", e);
229        }
230    }
231
232    /**
233     * Returns true if this is the first time this method has been called after
234     * the progress dialog was closed. Necessary to prevent a brief flicker where the
235     * cancel button would appear after closing the progress dialog. Subsequent
236     * calls to this method will return false until the progress dialog is
237     * opened again.
238     * @return true if this is the first time this method has been called
239     * since a progress dialog was visible. false otherwise.
240     */
241    public boolean dialogJustClosed() {
242        final boolean closed = mDialogClosed;
243        mDialogClosed = false;
244        return closed;
245    }
246}
247