Improved layout for downloads in image gallery
[pub/Android/ownCloud.git] / src / com / owncloud / android / ui / preview / FileDownloadFragment.java
1 /* ownCloud Android client application
2 *
3 * Copyright (C) 2012-2013 ownCloud Inc.
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 *
18 */
19 package com.owncloud.android.ui.preview;
20
21 import java.lang.ref.WeakReference;
22
23 import android.accounts.Account;
24 import android.app.Activity;
25 import android.content.BroadcastReceiver;
26 import android.content.Context;
27 import android.content.Intent;
28 import android.content.IntentFilter;
29 import android.os.Bundle;
30 import android.util.Log;
31 import android.view.LayoutInflater;
32 import android.view.View;
33 import android.view.View.OnClickListener;
34 import android.view.ViewGroup;
35 import android.widget.Button;
36 import android.widget.ProgressBar;
37 import android.widget.TextView;
38
39 import com.actionbarsherlock.app.SherlockFragment;
40 import com.owncloud.android.datamodel.FileDataStorageManager;
41 import com.owncloud.android.datamodel.OCFile;
42 import com.owncloud.android.files.services.FileDownloader;
43 import com.owncloud.android.files.services.FileDownloader.FileDownloaderBinder;
44 import com.owncloud.android.ui.fragment.FileFragment;
45
46 import com.owncloud.android.R;
47
48 import eu.alefzero.webdav.OnDatatransferProgressListener;
49
50 /**
51 * This Fragment is used to monitor the progress of a file downloading.
52 *
53 * @author David A. Velasco
54 */
55 public class FileDownloadFragment extends SherlockFragment implements OnClickListener,FileFragment {
56
57 public static final String EXTRA_FILE = "FILE";
58 public static final String EXTRA_ACCOUNT = "ACCOUNT";
59
60 private FileFragment.ContainerActivity mContainerActivity;
61
62 private View mView;
63 private OCFile mFile;
64 private Account mAccount;
65 private FileDataStorageManager mStorageManager;
66
67 private DownloadFinishReceiver mDownloadFinishReceiver;
68 public ProgressListener mProgressListener;
69 private boolean mListening;
70
71 private static final String TAG = FileDownloadFragment.class.getSimpleName();
72
73
74 /**
75 * Creates an empty details fragment.
76 *
77 * It's necessary to keep a public constructor without parameters; the system uses it when tries to reinstantiate a fragment automatically.
78 */
79 public FileDownloadFragment() {
80 mFile = null;
81 mAccount = null;
82 mStorageManager = null;
83 mProgressListener = null;
84 mListening = false;
85 }
86
87
88 /**
89 * Creates a details fragment.
90 *
91 * When 'fileToDetail' or 'ocAccount' are null, creates a dummy layout (to use when a file wasn't tapped before).
92 *
93 * @param fileToDetail An {@link OCFile} to show in the fragment
94 * @param ocAccount An ownCloud account; needed to start downloads
95 */
96 public FileDownloadFragment(OCFile fileToDetail, Account ocAccount) {
97 mFile = fileToDetail;
98 mAccount = ocAccount;
99 mStorageManager = null; // we need a context to init this; the container activity is not available yet at this moment
100 mProgressListener = null;
101 mListening = false;
102 }
103
104
105 @Override
106 public void onCreate(Bundle savedInstanceState) {
107 super.onCreate(savedInstanceState);
108 Log.e(TAG, "PREVIEW_DOWNLOAD_FRAGMENT ONCREATE " + ((mFile == null)? "(NULL)" : mFile.getFileName()));
109 }
110
111
112 @Override
113 public View onCreateView(LayoutInflater inflater, ViewGroup container,
114 Bundle savedInstanceState) {
115 super.onCreateView(inflater, container, savedInstanceState);
116
117 if (savedInstanceState != null) {
118 mFile = savedInstanceState.getParcelable(FileDownloadFragment.EXTRA_FILE);
119 mAccount = savedInstanceState.getParcelable(FileDownloadFragment.EXTRA_ACCOUNT);
120 }
121
122 if(mFile != null && mAccount != null) {
123 //mLayout = R.layout.file_details_fragment;
124 }
125
126 View view = null;
127 view = inflater.inflate(R.layout.file_download_fragment, container, false);
128 mView = view;
129
130 ProgressBar progressBar = (ProgressBar)mView.findViewById(R.id.progressBar);
131 mProgressListener = new ProgressListener(progressBar);
132
133 return view;
134 }
135
136
137 /**
138 * {@inheritDoc}
139 */
140 @Override
141 public void onAttach(Activity activity) {
142 super.onAttach(activity);
143 Log.e(TAG, "PREVIEW_DOWNLOAD_FRAGMENT ONATTACH " + ((mFile == null)?" (NULL)":mFile.getFileName()));
144 try {
145 mContainerActivity = (ContainerActivity) activity;
146
147 } catch (ClassCastException e) {
148 throw new ClassCastException(activity.toString() + " must implement " + FileFragment.ContainerActivity.class.getSimpleName());
149 }
150 }
151
152
153 /**
154 * {@inheritDoc}
155 */
156 @Override
157 public void onActivityCreated(Bundle savedInstanceState) {
158 super.onActivityCreated(savedInstanceState);
159 Log.e(TAG, "PREVIEW_DOWNLOAD_FRAGMENT ONACTIVITYCREATED " + ((mFile == null)?" (NULL)":mFile.getFileName()));
160 if (mAccount != null) {
161 mStorageManager = new FileDataStorageManager(mAccount, getActivity().getApplicationContext().getContentResolver());;
162 }
163 }
164
165
166 @Override
167 public void onSaveInstanceState(Bundle outState) {
168 super.onSaveInstanceState(outState);
169 outState.putParcelable(FileDownloadFragment.EXTRA_FILE, mFile);
170 outState.putParcelable(FileDownloadFragment.EXTRA_ACCOUNT, mAccount);
171 }
172
173 @Override
174 public void onStart() {
175 super.onStart();
176 Log.e(TAG, "FILE_DOWNLOAD_FRAGMENT ONSTART " + mFile.getFileName());
177 listenForTransferProgress();
178 }
179
180 @Override
181 public void onResume() {
182 Log.e(TAG, "PREVIEW_DOWNLOAD_FRAGMENT ONRESUME " + mFile.getFileName());
183 super.onResume();
184
185 mDownloadFinishReceiver = new DownloadFinishReceiver();
186 IntentFilter filter = new IntentFilter(
187 FileDownloader.DOWNLOAD_FINISH_MESSAGE);
188 getActivity().registerReceiver(mDownloadFinishReceiver, filter);
189 }
190
191
192 @Override
193 public void onPause() {
194 super.onPause();
195 Log.e(TAG, "PREVIEW_DOWNLOAD_FRAGMENT ONPAUSE " + mFile.getFileName());
196
197 getActivity().unregisterReceiver(mDownloadFinishReceiver);
198 mDownloadFinishReceiver = null;
199 }
200
201
202 @Override
203 public void onStop() {
204 super.onStop();
205 Log.e(TAG, "FILE_DOWNLOAD_FRAGMENT ONSTOP " + mFile.getFileName());
206 leaveTransferProgress();
207 }
208
209 @Override
210 public void onDestroy() {
211 super.onDestroy();
212 Log.e(TAG, "FILE_DOWNLOAD_FRAGMENT ONDESTROY " + mFile.getFileName());
213 }
214
215
216 @Override
217 public View getView() {
218 if (!mListening) {
219 listenForTransferProgress();
220 }
221 return super.getView() == null ? mView : super.getView();
222 }
223
224
225 @Override
226 public void onClick(View v) {
227 switch (v.getId()) {
228 case R.id.cancelBtn: {
229 FileDownloaderBinder downloaderBinder = mContainerActivity.getFileDownloaderBinder();
230 if (downloaderBinder != null && downloaderBinder.isDownloading(mAccount, mFile)) {
231 downloaderBinder.cancel(mAccount, mFile);
232 if (mFile.isDown()) {
233 setButtonsForDown();
234 } else {
235 setButtonsForRemote();
236 }
237 }
238 break;
239 }
240 default:
241 Log.e(TAG, "Incorrect view clicked!");
242 }
243 }
244
245
246 /**
247 * {@inheritDoc}
248 */
249 public OCFile getFile(){
250 return mFile;
251 }
252
253
254 /**
255 * Updates the view depending upon the state of the downloading file.
256 *
257 * @param transferring When true, the view must be updated assuming that the holded file is
258 * downloading, no matter what the downloaderBinder says.
259 */
260 public void updateView(boolean transferring) {
261 // configure UI for depending upon local state of the file
262 FileDownloaderBinder downloaderBinder = mContainerActivity.getFileDownloaderBinder();
263 if (transferring || (downloaderBinder != null && downloaderBinder.isDownloading(mAccount, mFile))) {
264 setButtonsForTransferring();
265
266 } else if (mFile.isDown()) {
267
268 setButtonsForDown();
269
270 } else {
271 setButtonsForRemote();
272 }
273 getView().invalidate();
274 }
275
276
277 /**
278 * Enables or disables buttons for a file being downloaded
279 */
280 private void setButtonsForTransferring() {
281 Button downloadButton = (Button) getView().findViewById(R.id.cancelBtn);
282 downloadButton.setText(R.string.common_cancel);
283
284 // show the progress bar for the transfer
285 ProgressBar progressBar = (ProgressBar)getView().findViewById(R.id.progressBar);
286 progressBar.setVisibility(View.VISIBLE);
287 TextView progressText = (TextView)getView().findViewById(R.id.progressText);
288 progressText.setText(R.string.downloader_download_in_progress_ticker);
289 }
290
291
292 /**
293 * Enables or disables buttons for a file locally available
294 */
295 private void setButtonsForDown() {
296 Button downloadButton = (Button) getView().findViewById(R.id.cancelBtn);
297 downloadButton.setVisibility(View.GONE);
298
299 // hides the progress bar
300 ProgressBar progressBar = (ProgressBar)getView().findViewById(R.id.progressBar);
301 progressBar.setVisibility(View.GONE);
302
303 // updates the text message
304 TextView progressText = (TextView)getView().findViewById(R.id.progressText);
305 progressText.setText(R.string.common_loading);
306 }
307
308
309 /**
310 * Enables or disables buttons for a file not locally available
311 */
312 private void setButtonsForRemote() {
313 Button downloadButton = (Button) getView().findViewById(R.id.cancelBtn);
314 downloadButton.setVisibility(View.GONE);
315 //downloadButton.setText(R.string.filedetails_download);
316
317 // hides the progress bar
318 ProgressBar progressBar = (ProgressBar)getView().findViewById(R.id.progressBar);
319 progressBar.setVisibility(View.GONE);
320
321 // updates the text message
322 TextView progressText = (TextView)getView().findViewById(R.id.progressText);
323 progressText.setText(R.string.downloader_not_downloaded_yet);
324 }
325
326
327 /**
328 * Once the file download has finished -> update view
329 */
330 private class DownloadFinishReceiver extends BroadcastReceiver {
331 @Override
332 public void onReceive(Context context, Intent intent) {
333 String accountName = intent.getStringExtra(FileDownloader.ACCOUNT_NAME);
334 if (accountName.equals(mAccount.name)) {
335 boolean downloadWasFine = intent.getBooleanExtra(FileDownloader.EXTRA_DOWNLOAD_RESULT, false);
336 String downloadedRemotePath = intent.getStringExtra(FileDownloader.EXTRA_REMOTE_PATH);
337 if (mFile.getRemotePath().equals(downloadedRemotePath)) {
338 if (downloadWasFine) {
339 mFile = mStorageManager.getFileByPath(downloadedRemotePath);
340 }
341 updateView(false);
342 getActivity().removeStickyBroadcast(intent);
343 mContainerActivity.notifySuccessfulDownload(mFile, intent, downloadWasFine);
344 }
345 }
346 }
347 }
348
349
350 public void listenForTransferProgress() {
351 if (mProgressListener != null && !mListening) {
352 if (mContainerActivity.getFileDownloaderBinder() != null) {
353 mContainerActivity.getFileDownloaderBinder().addDatatransferProgressListener(mProgressListener, mAccount, mFile);
354 mListening = true;
355 setButtonsForTransferring();
356 }
357 }
358 }
359
360
361 public void leaveTransferProgress() {
362 if (mProgressListener != null) {
363 if (mContainerActivity.getFileDownloaderBinder() != null) {
364 mContainerActivity.getFileDownloaderBinder().removeDatatransferProgressListener(mProgressListener, mAccount, mFile);
365 }
366 }
367 }
368
369
370 /**
371 * Helper class responsible for updating the progress bar shown for file uploading or downloading
372 *
373 * @author David A. Velasco
374 */
375 private class ProgressListener implements OnDatatransferProgressListener {
376 int mLastPercent = 0;
377 WeakReference<ProgressBar> mProgressBar = null;
378
379 ProgressListener(ProgressBar progressBar) {
380 mProgressBar = new WeakReference<ProgressBar>(progressBar);
381 }
382
383 @Override
384 public void onTransferProgress(long progressRate) {
385 // old method, nothing here
386 };
387
388 @Override
389 public void onTransferProgress(long progressRate, long totalTransferredSoFar, long totalToTransfer, String filename) {
390 int percent = (int)(100.0*((double)totalTransferredSoFar)/((double)totalToTransfer));
391 if (percent != mLastPercent) {
392 ProgressBar pb = mProgressBar.get();
393 if (pb != null) {
394 pb.setProgress(percent);
395 pb.postInvalidate();
396 }
397 }
398 mLastPercent = percent;
399 }
400
401 };
402
403
404
405 }