da43d11966084dfeb386c15e3ff666f69efff3a1
[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 View view = null;
123 view = inflater.inflate(R.layout.file_download_fragment, container, false);
124 mView = view;
125
126 ProgressBar progressBar = (ProgressBar)mView.findViewById(R.id.progressBar);
127 mProgressListener = new ProgressListener(progressBar);
128
129 ((Button)mView.findViewById(R.id.cancelBtn)).setOnClickListener(this);
130
131 return view;
132 }
133
134
135 /**
136 * {@inheritDoc}
137 */
138 @Override
139 public void onAttach(Activity activity) {
140 super.onAttach(activity);
141 Log.e(TAG, "PREVIEW_DOWNLOAD_FRAGMENT ONATTACH " + ((mFile == null)?" (NULL)":mFile.getFileName()));
142 try {
143 mContainerActivity = (ContainerActivity) activity;
144
145 } catch (ClassCastException e) {
146 throw new ClassCastException(activity.toString() + " must implement " + FileFragment.ContainerActivity.class.getSimpleName());
147 }
148 }
149
150
151 /**
152 * {@inheritDoc}
153 */
154 @Override
155 public void onActivityCreated(Bundle savedInstanceState) {
156 super.onActivityCreated(savedInstanceState);
157 Log.e(TAG, "PREVIEW_DOWNLOAD_FRAGMENT ONACTIVITYCREATED " + ((mFile == null)?" (NULL)":mFile.getFileName()));
158 if (mAccount != null) {
159 mStorageManager = new FileDataStorageManager(mAccount, getActivity().getApplicationContext().getContentResolver());;
160 }
161 }
162
163
164 @Override
165 public void onSaveInstanceState(Bundle outState) {
166 super.onSaveInstanceState(outState);
167 outState.putParcelable(FileDownloadFragment.EXTRA_FILE, mFile);
168 outState.putParcelable(FileDownloadFragment.EXTRA_ACCOUNT, mAccount);
169 }
170
171 @Override
172 public void onStart() {
173 super.onStart();
174 Log.e(TAG, "FILE_DOWNLOAD_FRAGMENT ONSTART " + mFile.getFileName());
175 listenForTransferProgress();
176 }
177
178 @Override
179 public void onResume() {
180 Log.e(TAG, "PREVIEW_DOWNLOAD_FRAGMENT ONRESUME " + mFile.getFileName());
181 super.onResume();
182
183 mDownloadFinishReceiver = new DownloadFinishReceiver();
184 IntentFilter filter = new IntentFilter(
185 FileDownloader.DOWNLOAD_FINISH_MESSAGE);
186 getActivity().registerReceiver(mDownloadFinishReceiver, filter);
187 }
188
189
190 @Override
191 public void onPause() {
192 super.onPause();
193 Log.e(TAG, "PREVIEW_DOWNLOAD_FRAGMENT ONPAUSE " + mFile.getFileName());
194
195 getActivity().unregisterReceiver(mDownloadFinishReceiver);
196 mDownloadFinishReceiver = null;
197 }
198
199
200 @Override
201 public void onStop() {
202 super.onStop();
203 Log.e(TAG, "FILE_DOWNLOAD_FRAGMENT ONSTOP " + mFile.getFileName());
204 leaveTransferProgress();
205 }
206
207 @Override
208 public void onDestroy() {
209 super.onDestroy();
210 Log.e(TAG, "FILE_DOWNLOAD_FRAGMENT ONDESTROY " + mFile.getFileName());
211 }
212
213
214 @Override
215 public View getView() {
216 if (!mListening) {
217 listenForTransferProgress();
218 }
219 return super.getView() == null ? mView : super.getView();
220 }
221
222
223 @Override
224 public void onClick(View v) {
225 switch (v.getId()) {
226 case R.id.cancelBtn: {
227 FileDownloaderBinder downloaderBinder = mContainerActivity.getFileDownloaderBinder();
228 if (downloaderBinder != null && downloaderBinder.isDownloading(mAccount, mFile)) {
229 downloaderBinder.cancel(mAccount, mFile);
230 leaveTransferProgress();
231 if (mFile.isDown()) {
232 setButtonsForDown();
233 } else {
234 setButtonsForRemote();
235 }
236 }
237 break;
238 }
239 default:
240 Log.e(TAG, "Incorrect view clicked!");
241 }
242 }
243
244
245 /**
246 * {@inheritDoc}
247 */
248 public OCFile getFile(){
249 return mFile;
250 }
251
252
253 /**
254 * Updates the view depending upon the state of the downloading file.
255 *
256 * @param transferring When true, the view must be updated assuming that the holded file is
257 * downloading, no matter what the downloaderBinder says.
258 */
259 public void updateView(boolean transferring) {
260 // configure UI for depending upon local state of the file
261 FileDownloaderBinder downloaderBinder = mContainerActivity.getFileDownloaderBinder();
262 if (transferring || (downloaderBinder != null && downloaderBinder.isDownloading(mAccount, mFile))) {
263 setButtonsForTransferring();
264
265 } else if (mFile.isDown()) {
266
267 setButtonsForDown();
268
269 } else {
270 setButtonsForRemote();
271 }
272 getView().invalidate();
273 }
274
275
276 /**
277 * Enables or disables buttons for a file being downloaded
278 */
279 private void setButtonsForTransferring() {
280 Button downloadButton = (Button) getView().findViewById(R.id.cancelBtn);
281 downloadButton.setText(R.string.common_cancel);
282
283 // show the progress bar for the transfer
284 ProgressBar progressBar = (ProgressBar)getView().findViewById(R.id.progressBar);
285 progressBar.setVisibility(View.VISIBLE);
286 TextView progressText = (TextView)getView().findViewById(R.id.progressText);
287 progressText.setText(R.string.downloader_download_in_progress_ticker);
288 }
289
290
291 /**
292 * Enables or disables buttons for a file locally available
293 */
294 private void setButtonsForDown() {
295 Button downloadButton = (Button) getView().findViewById(R.id.cancelBtn);
296 downloadButton.setVisibility(View.GONE);
297
298 // hides the progress bar
299 ProgressBar progressBar = (ProgressBar)getView().findViewById(R.id.progressBar);
300 progressBar.setVisibility(View.GONE);
301
302 // updates the text message
303 TextView progressText = (TextView)getView().findViewById(R.id.progressText);
304 progressText.setText(R.string.common_loading);
305 }
306
307
308 /**
309 * Enables or disables buttons for a file not locally available
310 */
311 private void setButtonsForRemote() {
312 Button downloadButton = (Button) getView().findViewById(R.id.cancelBtn);
313 downloadButton.setVisibility(View.GONE);
314 //downloadButton.setText(R.string.filedetails_download);
315
316 // hides the progress bar
317 ProgressBar progressBar = (ProgressBar)getView().findViewById(R.id.progressBar);
318 progressBar.setVisibility(View.GONE);
319
320 // updates the text message
321 TextView progressText = (TextView)getView().findViewById(R.id.progressText);
322 progressText.setText(R.string.downloader_not_downloaded_yet);
323 }
324
325
326 /**
327 * Once the file download has finished -> update view
328 */
329 private class DownloadFinishReceiver extends BroadcastReceiver {
330 @Override
331 public void onReceive(Context context, Intent intent) {
332 String accountName = intent.getStringExtra(FileDownloader.ACCOUNT_NAME);
333 if (accountName.equals(mAccount.name)) {
334 boolean downloadWasFine = intent.getBooleanExtra(FileDownloader.EXTRA_DOWNLOAD_RESULT, false);
335 String downloadedRemotePath = intent.getStringExtra(FileDownloader.EXTRA_REMOTE_PATH);
336 if (mFile.getRemotePath().equals(downloadedRemotePath)) {
337 if (downloadWasFine) {
338 mFile = mStorageManager.getFileByPath(downloadedRemotePath);
339 }
340 updateView(false);
341 getActivity().removeStickyBroadcast(intent);
342 mContainerActivity.notifySuccessfulDownload(mFile, intent, downloadWasFine);
343 }
344 }
345 }
346 }
347
348
349 public void listenForTransferProgress() {
350 if (mProgressListener != null && !mListening) {
351 if (mContainerActivity.getFileDownloaderBinder() != null) {
352 mContainerActivity.getFileDownloaderBinder().addDatatransferProgressListener(mProgressListener, mAccount, mFile);
353 mListening = true;
354 setButtonsForTransferring();
355 }
356 }
357 }
358
359
360 public void leaveTransferProgress() {
361 if (mProgressListener != null) {
362 if (mContainerActivity.getFileDownloaderBinder() != null) {
363 mContainerActivity.getFileDownloaderBinder().removeDatatransferProgressListener(mProgressListener, mAccount, mFile);
364 }
365 }
366 }
367
368
369 /**
370 * Helper class responsible for updating the progress bar shown for file uploading or downloading
371 *
372 * @author David A. Velasco
373 */
374 private class ProgressListener implements OnDatatransferProgressListener {
375 int mLastPercent = 0;
376 WeakReference<ProgressBar> mProgressBar = null;
377
378 ProgressListener(ProgressBar progressBar) {
379 mProgressBar = new WeakReference<ProgressBar>(progressBar);
380 }
381
382 @Override
383 public void onTransferProgress(long progressRate) {
384 // old method, nothing here
385 };
386
387 @Override
388 public void onTransferProgress(long progressRate, long totalTransferredSoFar, long totalToTransfer, String filename) {
389 int percent = (int)(100.0*((double)totalTransferredSoFar)/((double)totalToTransfer));
390 if (percent != mLastPercent) {
391 ProgressBar pb = mProgressBar.get();
392 if (pb != null) {
393 pb.setProgress(percent);
394 pb.postInvalidate();
395 }
396 }
397 mLastPercent = percent;
398 }
399
400 };
401
402
403
404 }