Review and reenable calls to refresh list of files where necessary, for events out...
[pub/Android/ownCloud.git] / src / com / owncloud / android / ui / fragment / FileDetailFragment.java
1 /* ownCloud Android client application
2 * Copyright (C) 2011 Bartek Przybylski
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 version 2,
7 * as published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16 *
17 */
18 package com.owncloud.android.ui.fragment;
19
20 import java.lang.ref.WeakReference;
21 import java.util.ArrayList;
22 import java.util.List;
23
24 import android.accounts.Account;
25 import android.content.Intent;
26 import android.os.Bundle;
27 import android.view.LayoutInflater;
28 import android.view.View;
29 import android.view.View.OnClickListener;
30 import android.view.ViewGroup;
31 import android.widget.CheckBox;
32 import android.widget.ImageView;
33 import android.widget.ProgressBar;
34 import android.widget.TextView;
35
36 import com.actionbarsherlock.view.Menu;
37 import com.actionbarsherlock.view.MenuInflater;
38 import com.actionbarsherlock.view.MenuItem;
39 import com.owncloud.android.R;
40 import com.owncloud.android.datamodel.FileDataStorageManager;
41 import com.owncloud.android.datamodel.OCFile;
42 import com.owncloud.android.files.services.FileObserverService;
43 import com.owncloud.android.files.services.FileDownloader.FileDownloaderBinder;
44 import com.owncloud.android.files.services.FileUploader.FileUploaderBinder;
45 import com.owncloud.android.lib.common.network.OnDatatransferProgressListener;
46 import com.owncloud.android.ui.activity.FileActivity;
47 import com.owncloud.android.ui.activity.FileDisplayActivity;
48 import com.owncloud.android.ui.dialog.ConfirmationDialogFragment;
49 import com.owncloud.android.ui.dialog.EditNameDialog;
50 import com.owncloud.android.ui.dialog.EditNameDialog.EditNameDialogListener;
51 import com.owncloud.android.utils.DisplayUtils;
52 import com.owncloud.android.utils.Log_OC;
53
54
55 /**
56 * This Fragment is used to display the details about a file.
57 *
58 * @author Bartek Przybylski
59 * @author David A. Velasco
60 */
61 public class FileDetailFragment extends FileFragment implements
62 OnClickListener,
63 ConfirmationDialogFragment.ConfirmationDialogFragmentListener, EditNameDialogListener {
64
65 private int mLayout;
66 private View mView;
67 private Account mAccount;
68
69 public ProgressListener mProgressListener;
70
71 private static final String TAG = FileDetailFragment.class.getSimpleName();
72 public static final String FTAG_CONFIRMATION = "REMOVE_CONFIRMATION_FRAGMENT";
73
74
75 /**
76 * Creates an empty details fragment.
77 *
78 * It's necessary to keep a public constructor without parameters; the system uses it when tries to reinstantiate a fragment automatically.
79 */
80 public FileDetailFragment() {
81 super();
82 mAccount = null;
83 mLayout = R.layout.file_details_empty;
84 mProgressListener = null;
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 FileDetailFragment(OCFile fileToDetail, Account ocAccount) {
96 super(fileToDetail);
97 mAccount = ocAccount;
98 mLayout = R.layout.file_details_empty;
99 mProgressListener = null;
100 }
101
102
103 @Override
104 public void onCreate(Bundle savedInstanceState) {
105 super.onCreate(savedInstanceState);
106 setHasOptionsMenu(true);
107 }
108
109
110 @Override
111 public View onCreateView(LayoutInflater inflater, ViewGroup container,
112 Bundle savedInstanceState) {
113 //super.onCreateView(inflater, container, savedInstanceState);
114
115 if (savedInstanceState != null) {
116 setFile((OCFile)savedInstanceState.getParcelable(FileActivity.EXTRA_FILE));
117 mAccount = savedInstanceState.getParcelable(FileActivity.EXTRA_ACCOUNT);
118 }
119
120 if(getFile() != null && mAccount != null) {
121 mLayout = R.layout.file_details_fragment;
122 }
123
124 View view = null;
125 view = inflater.inflate(mLayout, null);
126 mView = view;
127
128 if (mLayout == R.layout.file_details_fragment) {
129 mView.findViewById(R.id.fdKeepInSync).setOnClickListener(this);
130 ProgressBar progressBar = (ProgressBar)mView.findViewById(R.id.fdProgressBar);
131 mProgressListener = new ProgressListener(progressBar);
132 mView.findViewById(R.id.fdCancelBtn).setOnClickListener(this);
133 }
134
135 updateFileDetails(false, false);
136 return view;
137 }
138
139 /*-*
140 * {@inheritDoc}
141 *-/
142 @Override
143 public void onActivityCreated(Bundle savedInstanceState) {
144 super.onActivityCreated(savedInstanceState);
145 if (mAccount != null) {
146 OCFile file = ((FileActivity)getActivity()).getStorageManager().
147 getFileByPath(getFile().getRemotePath());
148 if (file != null) {
149 setFile(file);
150 }
151 }
152 }
153 */
154
155
156 @Override
157 public void onSaveInstanceState(Bundle outState) {
158 super.onSaveInstanceState(outState);
159 outState.putParcelable(FileActivity.EXTRA_FILE, getFile());
160 outState.putParcelable(FileActivity.EXTRA_ACCOUNT, mAccount);
161 }
162
163 @Override
164 public void onStart() {
165 super.onStart();
166 listenForTransferProgress();
167 }
168
169 @Override
170 public void onStop() {
171 super.onStop();
172 leaveTransferProgress();
173 }
174
175
176 @Override
177 public View getView() {
178 return super.getView() == null ? mView : super.getView();
179 }
180
181
182 /**
183 * {@inheritDoc}
184 */
185 @Override
186 public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
187 super.onCreateOptionsMenu(menu, inflater);
188 inflater.inflate(R.menu.file_actions_menu, menu);
189 MenuItem item = menu.findItem(R.id.action_see_details);
190 if (item != null) {
191 item.setVisible(false);
192 item.setEnabled(false);
193 }
194
195 // Send file
196 item = menu.findItem(R.id.action_send_file);
197 boolean sendEnabled = getString(R.string.send_files_to_other_apps).equalsIgnoreCase("on");
198 if (item != null) {
199 if (sendEnabled) {
200 item.setVisible(true);
201 item.setEnabled(true);
202 } else {
203 item.setVisible(false);
204 item.setEnabled(false);
205
206 }
207 }
208 }
209
210
211 /**
212 * {@inheritDoc}
213 */
214 @Override
215 public void onPrepareOptionsMenu (Menu menu) {
216 super.onPrepareOptionsMenu(menu);
217
218 List<Integer> toHide = new ArrayList<Integer>();
219 List<Integer> toShow = new ArrayList<Integer>();
220 OCFile file = getFile();
221
222 FileDownloaderBinder downloaderBinder = mContainerActivity.getFileDownloaderBinder();
223 boolean downloading = downloaderBinder != null && downloaderBinder.isDownloading(mAccount, file);
224 FileUploaderBinder uploaderBinder = mContainerActivity.getFileUploaderBinder();
225 boolean uploading = uploaderBinder != null && uploaderBinder.isUploading(mAccount, getFile());
226
227 if (downloading || uploading) {
228 toHide.add(R.id.action_download_file);
229 toHide.add(R.id.action_rename_file);
230 toHide.add(R.id.action_remove_file);
231 toHide.add(R.id.action_open_file_with);
232 if (!downloading) {
233 toHide.add(R.id.action_cancel_download);
234 toShow.add(R.id.action_cancel_upload);
235 } else {
236 toHide.add(R.id.action_cancel_upload);
237 toShow.add(R.id.action_cancel_download);
238 }
239
240 } else if (file != null && file.isDown()) {
241 toHide.add(R.id.action_download_file);
242 toHide.add(R.id.action_cancel_download);
243 toHide.add(R.id.action_cancel_upload);
244
245 toShow.add(R.id.action_rename_file);
246 toShow.add(R.id.action_remove_file);
247 toShow.add(R.id.action_open_file_with);
248 toShow.add(R.id.action_sync_file);
249
250 } else if (file != null) {
251 toHide.add(R.id.action_open_file_with);
252 toHide.add(R.id.action_cancel_download);
253 toHide.add(R.id.action_cancel_upload);
254 toHide.add(R.id.action_sync_file);
255
256 toShow.add(R.id.action_rename_file);
257 toShow.add(R.id.action_remove_file);
258 toShow.add(R.id.action_download_file);
259
260 } else {
261 toHide.add(R.id.action_open_file_with);
262 toHide.add(R.id.action_cancel_download);
263 toHide.add(R.id.action_cancel_upload);
264 toHide.add(R.id.action_sync_file);
265 toHide.add(R.id.action_download_file);
266 toHide.add(R.id.action_rename_file);
267 toHide.add(R.id.action_remove_file);
268
269 }
270
271 // Options shareLink
272 if (!file.isShareByLink()) {
273 toHide.add(R.id.action_unshare_file);
274 } else {
275 toShow.add(R.id.action_unshare_file);
276 }
277
278 MenuItem item = null;
279 for (int i : toHide) {
280 item = menu.findItem(i);
281 if (item != null) {
282 item.setVisible(false);
283 item.setEnabled(false);
284 }
285 }
286 for (int i : toShow) {
287 item = menu.findItem(i);
288 if (item != null) {
289 item.setVisible(true);
290 item.setEnabled(true);
291 }
292 }
293 }
294
295
296 /**
297 * {@inheritDoc}
298 */
299 @Override
300 public boolean onOptionsItemSelected(MenuItem item) {
301 switch (item.getItemId()) {
302 case R.id.action_share_file: {
303 mContainerActivity.getFileOperationsHelper().shareFileWithLink(getFile());
304 return true;
305 }
306 case R.id.action_unshare_file: {
307 mContainerActivity.getFileOperationsHelper().unshareFileWithLink(getFile());
308 return true;
309 }
310 case R.id.action_open_file_with: {
311 mContainerActivity.getFileOperationsHelper().openFile(getFile());
312 return true;
313 }
314 case R.id.action_remove_file: {
315 showDialogToRemoveFile();
316 return true;
317 }
318 case R.id.action_rename_file: {
319 showDialogToRenameFile();
320 return true;
321 }
322 case R.id.action_cancel_download:
323 case R.id.action_cancel_upload: {
324 ((FileDisplayActivity)mContainerActivity).cancelTransference(getFile());
325 return true;
326 }
327 case R.id.action_download_file:
328 case R.id.action_sync_file: {
329 mContainerActivity.getFileOperationsHelper().syncFile(getFile());
330 return true;
331 }
332 case R.id.action_send_file: {
333 // Obtain the file
334 if (!getFile().isDown()) { // Download the file
335 Log_OC.d(TAG, getFile().getRemotePath() + " : File must be downloaded");
336 ((FileDisplayActivity)mContainerActivity).startDownloadForSending(getFile());
337
338 } else {
339 ((FileDisplayActivity)mContainerActivity).getFileOperationsHelper().sendDownloadedFile(getFile());
340 }
341 return true;
342 }
343 default:
344 return false;
345 }
346 }
347
348 @Override
349 public void onClick(View v) {
350 switch (v.getId()) {
351 case R.id.fdKeepInSync: {
352 toggleKeepInSync();
353 break;
354 }
355 case R.id.fdCancelBtn: {
356 ((FileDisplayActivity)mContainerActivity).cancelTransference(getFile());
357 break;
358 }
359 default:
360 Log_OC.e(TAG, "Incorrect view clicked!");
361 }
362 }
363
364
365 private void toggleKeepInSync() {
366 CheckBox cb = (CheckBox) getView().findViewById(R.id.fdKeepInSync);
367 OCFile file = getFile();
368 file.setKeepInSync(cb.isChecked());
369 mContainerActivity.getStorageManager().saveFile(file);
370
371 /// register the OCFile instance in the observer service to monitor local updates;
372 /// if necessary, the file is download
373 Intent intent = new Intent(getActivity().getApplicationContext(),
374 FileObserverService.class);
375 intent.putExtra(FileObserverService.KEY_FILE_CMD,
376 (cb.isChecked()?
377 FileObserverService.CMD_ADD_OBSERVED_FILE:
378 FileObserverService.CMD_DEL_OBSERVED_FILE));
379 intent.putExtra(FileObserverService.KEY_CMD_ARG_FILE, file);
380 intent.putExtra(FileObserverService.KEY_CMD_ARG_ACCOUNT, mAccount);
381 getActivity().startService(intent);
382
383 if (file.keepInSync()) {
384 mContainerActivity.getFileOperationsHelper().syncFile(getFile());
385 }
386 }
387
388 private void showDialogToRemoveFile() {
389 OCFile file = getFile();
390 ConfirmationDialogFragment confDialog = ConfirmationDialogFragment.newInstance(
391 R.string.confirmation_remove_alert,
392 new String[]{file.getFileName()},
393 file.isDown() ? R.string.confirmation_remove_remote_and_local : R.string.confirmation_remove_remote,
394 file.isDown() ? R.string.confirmation_remove_local : -1,
395 R.string.common_cancel);
396 confDialog.setOnConfirmationListener(this);
397 confDialog.show(getFragmentManager(), FTAG_CONFIRMATION);
398 }
399
400
401 private void showDialogToRenameFile() {
402 OCFile file = getFile();
403 String fileName = file.getFileName();
404 int extensionStart = file.isFolder() ? -1 : fileName.lastIndexOf(".");
405 int selectionEnd = (extensionStart >= 0) ? extensionStart : fileName.length();
406 EditNameDialog dialog = EditNameDialog.newInstance(getString(R.string.rename_dialog_title), fileName, 0, selectionEnd, this);
407 dialog.show(getFragmentManager(), "nameeditdialog");
408 }
409
410
411 @Override
412 public void onConfirmation(String callerTag) {
413 OCFile file = getFile();
414 if (callerTag.equals(FTAG_CONFIRMATION)) {
415 if (mContainerActivity.getStorageManager().getFileById(file.getFileId()) != null) {
416 mContainerActivity.getFileOperationsHelper().removeFile(file, true);
417 }
418 }
419 }
420
421 @Override
422 public void onNeutral(String callerTag) {
423 OCFile file = getFile();
424 mContainerActivity.getStorageManager().removeFile(file, false, true); // TODO perform in background task / new thread
425 if (file.getStoragePath() != null) {
426 file.setStoragePath(null);
427 updateFileDetails(file, mAccount);
428 }
429 }
430
431 @Override
432 public void onCancel(String callerTag) {
433 Log_OC.d(TAG, "REMOVAL CANCELED");
434 }
435
436
437 /**
438 * Check if the fragment was created with an empty layout. An empty fragment can't show file details, must be replaced.
439 *
440 * @return True when the fragment was created with the empty layout.
441 */
442 public boolean isEmpty() {
443 return (mLayout == R.layout.file_details_empty || getFile() == null || mAccount == null);
444 }
445
446
447 /**
448 * Use this method to signal this Activity that it shall update its view.
449 *
450 * @param file : An {@link OCFile}
451 */
452 public void updateFileDetails(OCFile file, Account ocAccount) {
453 setFile(file);
454 mAccount = ocAccount;
455 updateFileDetails(false, false);
456 }
457
458 /**
459 * Updates the view with all relevant details about that file.
460 *
461 * TODO Remove parameter when the transferring state of files is kept in database.
462 *
463 * @param transferring Flag signaling if the file should be considered as downloading or uploading,
464 * although {@link FileDownloaderBinder#isDownloading(Account, OCFile)} and
465 * {@link FileUploaderBinder#isUploading(Account, OCFile)} return false.
466 *
467 * @param refresh If 'true', try to refresh the whole file from the database
468 */
469 public void updateFileDetails(boolean transferring, boolean refresh) {
470 if (readyToShow()) {
471 FileDataStorageManager storageManager = mContainerActivity.getStorageManager();
472 if (refresh && storageManager != null) {
473 setFile(storageManager.getFileByPath(getFile().getRemotePath()));
474 }
475 OCFile file = getFile();
476
477 // set file details
478 setFilename(file.getFileName());
479 setFiletype(file.getMimetype());
480 setFilesize(file.getFileLength());
481 if(ocVersionSupportsTimeCreated()){
482 setTimeCreated(file.getCreationTimestamp());
483 }
484
485 setTimeModified(file.getModificationTimestamp());
486
487 CheckBox cb = (CheckBox)getView().findViewById(R.id.fdKeepInSync);
488 cb.setChecked(file.keepInSync());
489
490 // configure UI for depending upon local state of the file
491 FileDownloaderBinder downloaderBinder = mContainerActivity.getFileDownloaderBinder();
492 FileUploaderBinder uploaderBinder = mContainerActivity.getFileUploaderBinder();
493 if (transferring || (downloaderBinder != null && downloaderBinder.isDownloading(mAccount, file)) || (uploaderBinder != null && uploaderBinder.isUploading(mAccount, file))) {
494 setButtonsForTransferring();
495
496 } else if (file.isDown()) {
497
498 setButtonsForDown();
499
500 } else {
501 // TODO load default preview image; when the local file is removed, the preview remains there
502 setButtonsForRemote();
503 }
504 }
505 getView().invalidate();
506 }
507
508 /**
509 * Checks if the fragment is ready to show details of a OCFile
510 *
511 * @return 'True' when the fragment is ready to show details of a file
512 */
513 private boolean readyToShow() {
514 return (getFile() != null && mAccount != null && mLayout == R.layout.file_details_fragment);
515 }
516
517
518 /**
519 * Updates the filename in view
520 * @param filename to set
521 */
522 private void setFilename(String filename) {
523 TextView tv = (TextView) getView().findViewById(R.id.fdFilename);
524 if (tv != null)
525 tv.setText(filename);
526 }
527
528 /**
529 * Updates the MIME type in view
530 * @param mimetype to set
531 */
532 private void setFiletype(String mimetype) {
533 TextView tv = (TextView) getView().findViewById(R.id.fdType);
534 if (tv != null) {
535 String printableMimetype = DisplayUtils.convertMIMEtoPrettyPrint(mimetype);;
536 tv.setText(printableMimetype);
537 }
538 ImageView iv = (ImageView) getView().findViewById(R.id.fdIcon);
539 if (iv != null) {
540 iv.setImageResource(DisplayUtils.getResourceId(mimetype));
541 }
542 }
543
544 /**
545 * Updates the file size in view
546 * @param filesize in bytes to set
547 */
548 private void setFilesize(long filesize) {
549 TextView tv = (TextView) getView().findViewById(R.id.fdSize);
550 if (tv != null)
551 tv.setText(DisplayUtils.bytesToHumanReadable(filesize));
552 }
553
554 /**
555 * Updates the time that the file was created in view
556 * @param milliseconds Unix time to set
557 */
558 private void setTimeCreated(long milliseconds){
559 TextView tv = (TextView) getView().findViewById(R.id.fdCreated);
560 TextView tvLabel = (TextView) getView().findViewById(R.id.fdCreatedLabel);
561 if(tv != null){
562 tv.setText(DisplayUtils.unixTimeToHumanReadable(milliseconds));
563 tv.setVisibility(View.VISIBLE);
564 tvLabel.setVisibility(View.VISIBLE);
565 }
566 }
567
568 /**
569 * Updates the time that the file was last modified
570 * @param milliseconds Unix time to set
571 */
572 private void setTimeModified(long milliseconds){
573 TextView tv = (TextView) getView().findViewById(R.id.fdModified);
574 if(tv != null){
575 tv.setText(DisplayUtils.unixTimeToHumanReadable(milliseconds));
576 }
577 }
578
579 /**
580 * Enables or disables buttons for a file being downloaded
581 */
582 private void setButtonsForTransferring() {
583 if (!isEmpty()) {
584 // let's protect the user from himself ;)
585 getView().findViewById(R.id.fdKeepInSync).setEnabled(false);
586
587 // show the progress bar for the transfer
588 getView().findViewById(R.id.fdProgressBlock).setVisibility(View.VISIBLE);
589 TextView progressText = (TextView)getView().findViewById(R.id.fdProgressText);
590 progressText.setVisibility(View.VISIBLE);
591 FileDownloaderBinder downloaderBinder = mContainerActivity.getFileDownloaderBinder();
592 FileUploaderBinder uploaderBinder = mContainerActivity.getFileUploaderBinder();
593 if (downloaderBinder != null && downloaderBinder.isDownloading(mAccount, getFile())) {
594 progressText.setText(R.string.downloader_download_in_progress_ticker);
595 } else if (uploaderBinder != null && uploaderBinder.isUploading(mAccount, getFile())) {
596 progressText.setText(R.string.uploader_upload_in_progress_ticker);
597 }
598 }
599 }
600
601 /**
602 * Enables or disables buttons for a file locally available
603 */
604 private void setButtonsForDown() {
605 if (!isEmpty()) {
606 getView().findViewById(R.id.fdKeepInSync).setEnabled(true);
607
608 // hides the progress bar
609 getView().findViewById(R.id.fdProgressBlock).setVisibility(View.GONE);
610 TextView progressText = (TextView)getView().findViewById(R.id.fdProgressText);
611 progressText.setVisibility(View.GONE);
612 }
613 }
614
615 /**
616 * Enables or disables buttons for a file not locally available
617 */
618 private void setButtonsForRemote() {
619 if (!isEmpty()) {
620 getView().findViewById(R.id.fdKeepInSync).setEnabled(true);
621
622 // hides the progress bar
623 getView().findViewById(R.id.fdProgressBlock).setVisibility(View.GONE);
624 TextView progressText = (TextView)getView().findViewById(R.id.fdProgressText);
625 progressText.setVisibility(View.GONE);
626 }
627 }
628
629
630 /**
631 * In ownCloud 3.X.X and 4.X.X there is a bug that SabreDAV does not return
632 * the time that the file was created. There is a chance that this will
633 * be fixed in future versions. Use this method to check if this version of
634 * ownCloud has this fix.
635 * @return True, if ownCloud the ownCloud version is supporting creation time
636 */
637 private boolean ocVersionSupportsTimeCreated(){
638 /*if(mAccount != null){
639 AccountManager accManager = (AccountManager) getActivity().getSystemService(Context.ACCOUNT_SERVICE);
640 OwnCloudVersion ocVersion = new OwnCloudVersion(accManager
641 .getUserData(mAccount, AccountAuthenticator.KEY_OC_VERSION));
642 if(ocVersion.compareTo(new OwnCloudVersion(0x030000)) < 0) {
643 return true;
644 }
645 }*/
646 return false;
647 }
648
649
650 public void onDismiss(EditNameDialog dialog) {
651 if (dialog.getResult()) {
652 String newFilename = dialog.getNewFilename();
653 Log_OC.d(TAG, "name edit dialog dismissed with new name " + newFilename);
654 mContainerActivity.getFileOperationsHelper().renameFile(getFile(), newFilename);
655 }
656 }
657
658
659 public void listenForTransferProgress() {
660 if (mProgressListener != null) {
661 if (mContainerActivity.getFileDownloaderBinder() != null) {
662 mContainerActivity.getFileDownloaderBinder().addDatatransferProgressListener(mProgressListener, mAccount, getFile());
663 }
664 if (mContainerActivity.getFileUploaderBinder() != null) {
665 mContainerActivity.getFileUploaderBinder().addDatatransferProgressListener(mProgressListener, mAccount, getFile());
666 }
667 }
668 }
669
670
671 public void leaveTransferProgress() {
672 if (mProgressListener != null) {
673 if (mContainerActivity.getFileDownloaderBinder() != null) {
674 mContainerActivity.getFileDownloaderBinder().removeDatatransferProgressListener(mProgressListener, mAccount, getFile());
675 }
676 if (mContainerActivity.getFileUploaderBinder() != null) {
677 mContainerActivity.getFileUploaderBinder().removeDatatransferProgressListener(mProgressListener, mAccount, getFile());
678 }
679 }
680 }
681
682
683
684 /**
685 * Helper class responsible for updating the progress bar shown for file uploading or downloading
686 *
687 * @author David A. Velasco
688 */
689 private class ProgressListener implements OnDatatransferProgressListener {
690 int mLastPercent = 0;
691 WeakReference<ProgressBar> mProgressBar = null;
692
693 ProgressListener(ProgressBar progressBar) {
694 mProgressBar = new WeakReference<ProgressBar>(progressBar);
695 }
696
697 @Override
698 public void onTransferProgress(long progressRate, long totalTransferredSoFar, long totalToTransfer, String filename) {
699 int percent = (int)(100.0*((double)totalTransferredSoFar)/((double)totalToTransfer));
700 if (percent != mLastPercent) {
701 ProgressBar pb = mProgressBar.get();
702 if (pb != null) {
703 pb.setProgress(percent);
704 pb.postInvalidate();
705 }
706 }
707 mLastPercent = percent;
708 }
709
710 };
711
712 }