6734c0436051f07012e397eb9905f228c1ba52e4
[pub/Android/ownCloud.git] / src / com / owncloud / android / ui / fragment / 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.fragment;
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
45 import com.owncloud.android.R;
46
47 import eu.alefzero.webdav.OnDatatransferProgressListener;
48
49 /**
50 * This Fragment is used to monitor the progress of a file downloading.
51 *
52 * @author David A. Velasco
53 */
54 public class FileDownloadFragment extends SherlockFragment implements OnClickListener,FileFragment {
55
56 public static final String EXTRA_FILE = "FILE";
57 public static final String EXTRA_ACCOUNT = "ACCOUNT";
58
59 private FileFragment.ContainerActivity mContainerActivity;
60
61 private View mView;
62 private OCFile mFile;
63 private Account mAccount;
64 private FileDataStorageManager mStorageManager;
65
66 private DownloadFinishReceiver mDownloadFinishReceiver;
67 public ProgressListener mProgressListener;
68 private boolean mListening;
69
70 private static final String TAG = FileDownloadFragment.class.getSimpleName();
71
72
73 /**
74 * Creates an empty details fragment.
75 *
76 * It's necessary to keep a public constructor without parameters; the system uses it when tries to reinstantiate a fragment automatically.
77 */
78 public FileDownloadFragment() {
79 mFile = null;
80 mAccount = null;
81 mStorageManager = null;
82 mProgressListener = null;
83 mListening = false;
84 }
85
86
87 /**
88 * Creates a details fragment.
89 *
90 * When 'fileToDetail' or 'ocAccount' are null, creates a dummy layout (to use when a file wasn't tapped before).
91 *
92 * @param fileToDetail An {@link OCFile} to show in the fragment
93 * @param ocAccount An ownCloud account; needed to start downloads
94 */
95 public FileDownloadFragment(OCFile fileToDetail, Account ocAccount) {
96 mFile = fileToDetail;
97 mAccount = ocAccount;
98 mStorageManager = null; // we need a context to init this; the container activity is not available yet at this moment
99 mProgressListener = null;
100 mListening = false;
101 }
102
103
104 @Override
105 public void onCreate(Bundle savedInstanceState) {
106 super.onCreate(savedInstanceState);
107 Log.e(TAG, "PREVIEW_DOWNLOAD_FRAGMENT ONCREATE " + ((mFile == null)? "(NULL)" : mFile.getFileName()));
108 }
109
110
111 @Override
112 public View onCreateView(LayoutInflater inflater, ViewGroup container,
113 Bundle savedInstanceState) {
114 super.onCreateView(inflater, container, savedInstanceState);
115
116 if (savedInstanceState != null) {
117 mFile = savedInstanceState.getParcelable(FileDownloadFragment.EXTRA_FILE);
118 mAccount = savedInstanceState.getParcelable(FileDownloadFragment.EXTRA_ACCOUNT);
119 }
120
121 if(mFile != null && mAccount != null) {
122 //mLayout = R.layout.file_details_fragment;
123 }
124
125 View view = null;
126 view = inflater.inflate(R.layout.file_download_fragment, container, false);
127 mView = view;
128
129 ProgressBar progressBar = (ProgressBar)mView.findViewById(R.id.progressBar);
130 mProgressListener = new ProgressListener(progressBar);
131
132 return view;
133 }
134
135
136 /**
137 * {@inheritDoc}
138 */
139 @Override
140 public void onAttach(Activity activity) {
141 super.onAttach(activity);
142 Log.e(TAG, "PREVIEW_DOWNLOAD_FRAGMENT ONATTACH " + ((mFile == null)?" (NULL)":mFile.getFileName()));
143 try {
144 mContainerActivity = (ContainerActivity) activity;
145
146 } catch (ClassCastException e) {
147 throw new ClassCastException(activity.toString() + " must implement " + FileFragment.ContainerActivity.class.getSimpleName());
148 }
149 }
150
151
152 /**
153 * {@inheritDoc}
154 */
155 @Override
156 public void onActivityCreated(Bundle savedInstanceState) {
157 super.onActivityCreated(savedInstanceState);
158 Log.e(TAG, "PREVIEW_DOWNLOAD_FRAGMENT ONACTIVITYCREATED " + ((mFile == null)?" (NULL)":mFile.getFileName()));
159 if (mAccount != null) {
160 mStorageManager = new FileDataStorageManager(mAccount, getActivity().getApplicationContext().getContentResolver());;
161 }
162 }
163
164
165 @Override
166 public void onSaveInstanceState(Bundle outState) {
167 super.onSaveInstanceState(outState);
168 outState.putParcelable(FileDownloadFragment.EXTRA_FILE, mFile);
169 outState.putParcelable(FileDownloadFragment.EXTRA_ACCOUNT, mAccount);
170 }
171
172 @Override
173 public void onStart() {
174 super.onStart();
175 Log.e(TAG, "FILE_DOWNLOAD_FRAGMENT ONSTART " + mFile.getFileName());
176 listenForTransferProgress();
177 }
178
179 @Override
180 public void onResume() {
181 Log.e(TAG, "PREVIEW_DOWNLOAD_FRAGMENT ONRESUME " + mFile.getFileName());
182 super.onResume();
183
184 mDownloadFinishReceiver = new DownloadFinishReceiver();
185 IntentFilter filter = new IntentFilter(
186 FileDownloader.DOWNLOAD_FINISH_MESSAGE);
187 getActivity().registerReceiver(mDownloadFinishReceiver, filter);
188 }
189
190
191 @Override
192 public void onPause() {
193 super.onPause();
194 Log.e(TAG, "PREVIEW_DOWNLOAD_FRAGMENT ONPAUSE " + mFile.getFileName());
195
196 getActivity().unregisterReceiver(mDownloadFinishReceiver);
197 mDownloadFinishReceiver = null;
198 }
199
200
201 @Override
202 public void onStop() {
203 super.onStop();
204 Log.e(TAG, "FILE_DOWNLOAD_FRAGMENT ONSTOP " + mFile.getFileName());
205 leaveTransferProgress();
206 }
207
208 @Override
209 public void onDestroy() {
210 super.onDestroy();
211 Log.e(TAG, "FILE_DOWNLOAD_FRAGMENT ONDESTROY " + mFile.getFileName());
212 }
213
214
215 @Override
216 public View getView() {
217 if (!mListening) {
218 listenForTransferProgress();
219 }
220 return super.getView() == null ? mView : super.getView();
221 }
222
223
224 @Override
225 public void onClick(View v) {
226 switch (v.getId()) {
227 case R.id.cancelBtn: {
228 FileDownloaderBinder downloaderBinder = mContainerActivity.getFileDownloaderBinder();
229 if (downloaderBinder != null && downloaderBinder.isDownloading(mAccount, mFile)) {
230 downloaderBinder.cancel(mAccount, mFile);
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 }