1 /* ownCloud Android client application 
   3  *   Copyright (C) 2012-2013  ownCloud Inc. 
   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. 
  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. 
  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/>. 
  19 package com
.owncloud
.android
.ui
.preview
; 
  21 import java
.lang
.ref
.WeakReference
; 
  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
; 
  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
; 
  46 import com
.owncloud
.android
.R
; 
  48 import eu
.alefzero
.webdav
.OnDatatransferProgressListener
; 
  51  * This Fragment is used to monitor the progress of a file downloading. 
  53  * @author David A. Velasco 
  55 public class FileDownloadFragment 
extends SherlockFragment 
implements OnClickListener
, FileFragment 
{ 
  57     public static final String EXTRA_FILE 
= "FILE"; 
  58     public static final String EXTRA_ACCOUNT 
= "ACCOUNT"; 
  60     private FileFragment
.ContainerActivity mContainerActivity
; 
  64     private Account mAccount
; 
  65     private FileDataStorageManager mStorageManager
; 
  67     private DownloadFinishReceiver mDownloadFinishReceiver
; 
  68     public ProgressListener mProgressListener
; 
  69     private boolean mListening
; 
  71     private static final String TAG 
= FileDownloadFragment
.class.getSimpleName(); 
  75      * Creates an empty details fragment. 
  77      * It's necessary to keep a public constructor without parameters; the system uses it when tries to reinstantiate a fragment automatically.  
  79     public FileDownloadFragment() { 
  82         mStorageManager 
= null
; 
  83         mProgressListener 
= null
; 
  89      * Creates a details fragment. 
  91      * When 'fileToDetail' or 'ocAccount' are null, creates a dummy layout (to use when a file wasn't tapped before). 
  93      * @param fileToDetail      An {@link OCFile} to show in the fragment 
  94      * @param ocAccount         An ownCloud account; needed to start downloads 
  96     public FileDownloadFragment(OCFile fileToDetail
, Account ocAccount
) { 
  99         mStorageManager 
= null
; // we need a context to init this; the container activity is not available yet at this moment  
 100         mProgressListener 
= null
; 
 106     public void onCreate(Bundle savedInstanceState
) { 
 107         super.onCreate(savedInstanceState
); 
 108         Log
.e(TAG
, "PREVIEW_DOWNLOAD_FRAGMENT ONCREATE " + ((mFile 
== null
)? 
"(NULL)" : mFile
.getFileName())); 
 113     public View 
onCreateView(LayoutInflater inflater
, ViewGroup container
, 
 114             Bundle savedInstanceState
) { 
 115         super.onCreateView(inflater
, container
, savedInstanceState
); 
 117         if (savedInstanceState 
!= null
) { 
 118             mFile 
= savedInstanceState
.getParcelable(FileDownloadFragment
.EXTRA_FILE
); 
 119             mAccount 
= savedInstanceState
.getParcelable(FileDownloadFragment
.EXTRA_ACCOUNT
); 
 123         view 
= inflater
.inflate(R
.layout
.file_download_fragment
, container
, false
); 
 126         ProgressBar progressBar 
= (ProgressBar
)mView
.findViewById(R
.id
.progressBar
); 
 127         mProgressListener 
= new ProgressListener(progressBar
); 
 129         ((Button
)mView
.findViewById(R
.id
.cancelBtn
)).setOnClickListener(this); 
 139     public void onAttach(Activity activity
) { 
 140         super.onAttach(activity
); 
 141         Log
.e(TAG
, "PREVIEW_DOWNLOAD_FRAGMENT ONATTACH " + ((mFile 
== null
)?
" (NULL)":mFile
.getFileName())); 
 143             mContainerActivity 
= (ContainerActivity
) activity
; 
 145         } catch (ClassCastException e
) { 
 146             throw new ClassCastException(activity
.toString() + " must implement " + FileFragment
.ContainerActivity
.class.getSimpleName()); 
 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());; 
 165     public void onSaveInstanceState(Bundle outState
) { 
 166         super.onSaveInstanceState(outState
); 
 167         outState
.putParcelable(FileDownloadFragment
.EXTRA_FILE
, mFile
); 
 168         outState
.putParcelable(FileDownloadFragment
.EXTRA_ACCOUNT
, mAccount
); 
 172     public void onStart() { 
 174         Log
.e(TAG
, "FILE_DOWNLOAD_FRAGMENT ONSTART " + mFile
.getFileName()); 
 175         listenForTransferProgress(); 
 179     public void onResume() { 
 180         Log
.e(TAG
, "PREVIEW_DOWNLOAD_FRAGMENT ONRESUME " + mFile
.getFileName()); 
 183         mDownloadFinishReceiver 
= new DownloadFinishReceiver(); 
 184         IntentFilter filter 
= new IntentFilter( 
 185                 FileDownloader
.DOWNLOAD_FINISH_MESSAGE
); 
 186         getActivity().registerReceiver(mDownloadFinishReceiver
, filter
); 
 191     public void onPause() { 
 193         Log
.e(TAG
, "PREVIEW_DOWNLOAD_FRAGMENT ONPAUSE " + mFile
.getFileName()); 
 195         getActivity().unregisterReceiver(mDownloadFinishReceiver
); 
 196         mDownloadFinishReceiver 
= null
; 
 201     public void onStop() { 
 203         Log
.e(TAG
, "FILE_DOWNLOAD_FRAGMENT ONSTOP " + mFile
.getFileName()); 
 204         leaveTransferProgress(); 
 208     public void onDestroy() { 
 210         Log
.e(TAG
, "FILE_DOWNLOAD_FRAGMENT ONDESTROY " + mFile
.getFileName()); 
 215     public View 
getView() { 
 217             listenForTransferProgress(); 
 219         return super.getView() == null ? mView 
: super.getView(); 
 224     public void onClick(View v
) { 
 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()) { 
 234                         setButtonsForRemote(); 
 240                 Log
.e(TAG
, "Incorrect view clicked!"); 
 248     public OCFile 
getFile(){ 
 254      * Updates the view depending upon the state of the downloading file. 
 256      * @param   transferring    When true, the view must be updated assuming that the holded file is  
 257      *                          downloading, no matter what the downloaderBinder says. 
 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(); 
 265         } else if (mFile
.isDown()) { 
 270             setButtonsForRemote(); 
 272         getView().invalidate(); 
 277      * Enables or disables buttons for a file being downloaded 
 279     private void setButtonsForTransferring() { 
 280         Button downloadButton 
= (Button
) getView().findViewById(R
.id
.cancelBtn
); 
 281         downloadButton
.setText(R
.string
.common_cancel
); 
 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
); 
 292      * Enables or disables buttons for a file locally available  
 294     private void setButtonsForDown() { 
 295         Button downloadButton 
= (Button
) getView().findViewById(R
.id
.cancelBtn
); 
 296         downloadButton
.setVisibility(View
.GONE
); 
 298         // hides the progress bar 
 299         ProgressBar progressBar 
= (ProgressBar
)getView().findViewById(R
.id
.progressBar
); 
 300         progressBar
.setVisibility(View
.GONE
); 
 302         // updates the text message 
 303         TextView progressText 
= (TextView
)getView().findViewById(R
.id
.progressText
); 
 304         progressText
.setText(R
.string
.common_loading
); 
 309      * Enables or disables buttons for a file not locally available  
 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); 
 316         // hides the progress bar 
 317         ProgressBar progressBar 
= (ProgressBar
)getView().findViewById(R
.id
.progressBar
); 
 318         progressBar
.setVisibility(View
.GONE
); 
 320         // updates the text message 
 321         TextView progressText 
= (TextView
)getView().findViewById(R
.id
.progressText
); 
 322         progressText
.setText(R
.string
.downloader_not_downloaded_yet
); 
 327      * Once the file download has finished -> update view 
 329     private class DownloadFinishReceiver 
extends BroadcastReceiver 
{ 
 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
); 
 341                     getActivity().removeStickyBroadcast(intent
); 
 342                     mContainerActivity
.notifySuccessfulDownload(mFile
, intent
, downloadWasFine
); 
 349     public void listenForTransferProgress() { 
 350         if (mProgressListener 
!= null 
&& !mListening
) { 
 351             if (mContainerActivity
.getFileDownloaderBinder() != null
) { 
 352                 mContainerActivity
.getFileDownloaderBinder().addDatatransferProgressListener(mProgressListener
, mAccount
, mFile
); 
 354                 setButtonsForTransferring(); 
 360     public void leaveTransferProgress() { 
 361         if (mProgressListener 
!= null
) { 
 362             if (mContainerActivity
.getFileDownloaderBinder() != null
) { 
 363                 mContainerActivity
.getFileDownloaderBinder().removeDatatransferProgressListener(mProgressListener
, mAccount
, mFile
); 
 370      * Helper class responsible for updating the progress bar shown for file uploading or downloading   
 372      * @author David A. Velasco 
 374     private class ProgressListener 
implements OnDatatransferProgressListener 
{ 
 375         int mLastPercent 
= 0; 
 376         WeakReference
<ProgressBar
> mProgressBar 
= null
; 
 378         ProgressListener(ProgressBar progressBar
) { 
 379             mProgressBar 
= new WeakReference
<ProgressBar
>(progressBar
); 
 383         public void onTransferProgress(long progressRate
) { 
 384             // old method, nothing here 
 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(); 
 393                     pb
.setProgress(percent
); 
 397             mLastPercent 
= percent
;