1 /* ownCloud Android client application 
   2  *   Copyright (C) 2011  Bartek Przybylski 
   4  *   This program is free software: you can redistribute it and/or modify 
   5  *   it under the terms of the GNU General Public License as published by 
   6  *   the Free Software Foundation, either version 3 of the License, or 
   7  *   (at your option) any later version. 
   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. 
  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/>. 
  18 package eu
.alefzero
.owncloud
.ui
.fragment
; 
  20 import java
.util
.List
; 
  22 import android
.accounts
.Account
; 
  23 import android
.accounts
.AccountManager
; 
  24 import android
.app
.ActionBar
.LayoutParams
; 
  25 import android
.content
.BroadcastReceiver
; 
  26 import android
.content
.Context
; 
  27 import android
.content
.Intent
; 
  28 import android
.content
.IntentFilter
; 
  29 import android
.content
.pm
.PackageManager
; 
  30 import android
.graphics
.Bitmap
; 
  31 import android
.graphics
.BitmapFactory
; 
  32 import android
.graphics
.BitmapFactory
.Options
; 
  33 import android
.graphics
.Path
.FillType
; 
  34 import android
.net
.Uri
; 
  35 import android
.os
.Bundle
; 
  36 import android
.util
.Log
; 
  37 import android
.view
.LayoutInflater
; 
  38 import android
.view
.View
; 
  39 import android
.view
.View
.OnClickListener
; 
  40 import android
.view
.ViewGroup
; 
  41 import android
.widget
.Button
; 
  42 import android
.widget
.ImageView
; 
  43 import android
.widget
.TextView
; 
  44 import android
.widget
.Toast
; 
  46 import com
.actionbarsherlock
.app
.SherlockFragment
; 
  48 import eu
.alefzero
.owncloud
.DisplayUtils
; 
  49 import eu
.alefzero
.owncloud
.R
; 
  50 import eu
.alefzero
.owncloud
.authenticator
.AccountAuthenticator
; 
  51 import eu
.alefzero
.owncloud
.datamodel
.OCFile
; 
  52 import eu
.alefzero
.owncloud
.files
.services
.FileDownloader
; 
  53 import eu
.alefzero
.owncloud
.utils
.OwnCloudVersion
; 
  56  * This Fragment is used to display the details about a file. 
  58  * @author Bartek Przybylski 
  61 public class FileDetailFragment 
extends SherlockFragment 
implements 
  64     public static final String EXTRA_FILE 
= "FILE"; 
  66     private DownloadFinishReceiver mDownloadFinishReceiver
; 
  67     private Intent mIntent
; 
  71     private static final String TAG 
= "FileDetailFragment"; 
  74      * Default constructor - contains real layout 
  76     public FileDetailFragment(){ 
  77         mLayout 
= R
.layout
.file_details_fragment
; 
  81      * Creates a dummy layout. For use if the user never has 
  82      * tapped on a file before 
  84      * @param useEmptyView If true, use empty layout 
  86     public FileDetailFragment(boolean useEmptyView
){ 
  88             mLayout 
= R
.layout
.file_details_empty
; 
  90             mLayout 
= R
.layout
.file_details_fragment
; 
  95      * Use this when creating the fragment and display 
  96      * a file at the same time 
  98      * @param showDetailsIntent The Intent with the required parameters 
  99      * @see FileDetailFragment#updateFileDetails(Intent) 
 101     public FileDetailFragment(Intent showDetailsIntent
) { 
 102         mIntent 
= showDetailsIntent
; 
 103         mLayout 
= R
.layout
.file_details_fragment
; 
 107     public void onResume() { 
 109         mDownloadFinishReceiver 
= new DownloadFinishReceiver(); 
 110         IntentFilter filter 
= new IntentFilter( 
 111                 FileDownloader
.DOWNLOAD_FINISH_MESSAGE
); 
 112         getActivity().registerReceiver(mDownloadFinishReceiver
, filter
); 
 116     public void onPause() { 
 118         getActivity().unregisterReceiver(mDownloadFinishReceiver
); 
 119         mDownloadFinishReceiver 
= null
; 
 123     public View 
onCreateView(LayoutInflater inflater
, ViewGroup container
, 
 124             Bundle savedInstanceState
) { 
 126         view 
= inflater
.inflate(mLayout
, container
, false
); 
 128         if(mLayout 
== R
.layout
.file_details_fragment
){ 
 129             // Phones will launch an activity with this intent 
 131                 mIntent 
= getActivity().getIntent(); 
 140     public View 
getView() { 
 141         return super.getView() == null ? mView 
: super.getView(); 
 145     public void onClick(View v
) { 
 146         Toast
.makeText(getActivity(), "Downloading", Toast
.LENGTH_LONG
).show(); 
 147         Intent i 
= new Intent(getActivity(), FileDownloader
.class); 
 148         i
.putExtra(FileDownloader
.EXTRA_ACCOUNT
, 
 149                 mIntent
.getParcelableExtra(FileDownloader
.EXTRA_ACCOUNT
)); 
 150         i
.putExtra(FileDownloader
.EXTRA_REMOTE_PATH
, mFile
.getRemotePath()); 
 151         i
.putExtra(FileDownloader
.EXTRA_FILE_PATH
, mFile
.getURLDecodedRemotePath()); 
 152         i
.putExtra(FileDownloader
.EXTRA_FILE_SIZE
, mFile
.getFileLength()); 
 153         getActivity().startService(i
); 
 157      * Can be used to get the file that is currently being displayed. 
 158      * @return The file on the screen. 
 160     public OCFile 
getDisplayedFile(){ 
 165      * Use this method to signal this Activity that it shall update its view. 
 167      * @param intent The {@link Intent} that contains extra information about 
 168      *            this file The intent needs to have these extras: 
 171      *            {@link FileDetailFragment#EXTRA_FILE}: An {@link OCFile} 
 172      *            {@link FileDownloader#EXTRA_ACCOUNT}: The Account that file 
 173      *            belongs to (required for downloading) 
 175     public void updateFileDetails(Intent intent
) { 
 181      * Updates the view with all relevant details about that file. 
 183     private void updateFileDetails() { 
 184         mFile 
= mIntent
.getParcelableExtra(EXTRA_FILE
); 
 185         Button downloadButton 
= (Button
) getView().findViewById(R
.id
.fdDownloadBtn
); 
 189             setFilename(mFile
.getFileName()); 
 190             setFiletype(DisplayUtils
.convertMIMEtoPrettyPrint(mFile
 
 192             setFilesize(mFile
.getFileLength()); 
 193             if(ocVersionSupportsTimeCreated()){ 
 194                 setTimeCreated(mFile
.getCreationTimestamp()); 
 197             setTimeModified(mFile
.getModificationTimestamp()); 
 200             if (mFile
.getStoragePath() != null
) { 
 201                 ImageView preview 
= (ImageView
) getView().findViewById(R
.id
.fdPreview
); 
 203                     if (mFile
.getMimetype().startsWith("image/")) { 
 204                         BitmapFactory
.Options options 
= new Options(); 
 205                         options
.inScaled 
= true
; 
 206                         options
.inMutable 
= false
; 
 207                         options
.inPreferQualityOverSpeed 
= false
; 
 208                         options
.inPurgeable 
= true
; 
 210                         Bitmap bmp 
= BitmapFactory
.decodeFile(mFile
.getStoragePath(), options
); 
 212                         int width 
= options
.outWidth
; 
 213                         int height 
= options
.outHeight
; 
 215                         if (width 
>= 2048 || height 
>= 2048) { 
 216                             scale 
= (int) (Math
.ceil(Math
.max(height
, width
)/2048.)); 
 217                             options
.inSampleSize 
= scale
; 
 220                             bmp 
= BitmapFactory
.decodeFile(mFile
.getStoragePath(), options
); 
 222                         preview
.setImageBitmap(bmp
); 
 224                 } catch (OutOfMemoryError e
) { 
 225                     preview
.setVisibility(View
.INVISIBLE
); 
 226                     Log
.e(TAG
, "Out of memory occured for file with size " + mFile
.getFileLength()); 
 228                 downloadButton
.setText(R
.string
.filedetails_open
); 
 229                 downloadButton
.setOnClickListener(new OnClickListener() { 
 231                     public void onClick(View v
) { 
 232                         Intent i 
= new Intent(Intent
.ACTION_VIEW
); 
 233                         i
.setDataAndType(Uri
.parse("file://"+mFile
.getStoragePath()), mFile
.getMimetype()); 
 234                         List list 
= getActivity().getPackageManager().queryIntentActivities(i
, PackageManager
.MATCH_DEFAULT_ONLY
); 
 235                         if (list
.size() > 0) { 
 238                             Toast
.makeText(getActivity(), "There is no application to handle file " + mFile
.getFileName(), Toast
.LENGTH_SHORT
).show(); 
 243                 // Make download button effective 
 244                 downloadButton
.setOnClickListener(this); 
 250      * Updates the filename in view 
 251      * @param filename to set 
 253     private void setFilename(String filename
) { 
 254         TextView tv 
= (TextView
) getView().findViewById(R
.id
.fdFilename
); 
 256             tv
.setText(filename
); 
 260      * Updates the MIME type in view 
 261      * @param mimetype to set 
 263     private void setFiletype(String mimetype
) { 
 264         TextView tv 
= (TextView
) getView().findViewById(R
.id
.fdType
); 
 266             tv
.setText(mimetype
); 
 270      * Updates the file size in view 
 271      * @param filesize in bytes to set 
 273     private void setFilesize(long filesize
) { 
 274         TextView tv 
= (TextView
) getView().findViewById(R
.id
.fdSize
); 
 276             tv
.setText(DisplayUtils
.bytesToHumanReadable(filesize
)); 
 280      * Updates the time that the file was created in view 
 281      * @param milliseconds Unix time to set 
 283     private void setTimeCreated(long milliseconds
){ 
 284         TextView tv 
= (TextView
) getView().findViewById(R
.id
.fdCreated
); 
 285         TextView tvLabel 
= (TextView
) getView().findViewById(R
.id
.fdCreatedLabel
); 
 287             tv
.setText(DisplayUtils
.unixTimeToHumanReadable(milliseconds
)); 
 288             tv
.setVisibility(View
.VISIBLE
); 
 289             tvLabel
.setVisibility(View
.VISIBLE
); 
 294      * Updates the time that the file was last modified 
 295      * @param milliseconds Unix time to set 
 297     private void setTimeModified(long milliseconds
){ 
 298         TextView tv 
= (TextView
) getView().findViewById(R
.id
.fdModified
); 
 300             tv
.setText(DisplayUtils
.unixTimeToHumanReadable(milliseconds
)); 
 305      * In ownCloud 3.0.3 and 4.0.0 there is a bug that SabreDAV does not return 
 306      * the time that the file was created. There is a chance that this will 
 307      * be fixed in future versions. Use this method to check if this version of 
 308      * ownCloud has this fix. 
 309      * @return True, if ownCloud the ownCloud version is > 3.0.4 and 4.0.1 
 311     private boolean ocVersionSupportsTimeCreated(){ 
 313             Account ocAccount 
= mIntent
.getParcelableExtra(FileDownloader
.EXTRA_ACCOUNT
); 
 314             if(ocAccount 
!= null
){ 
 315                 AccountManager accManager 
= (AccountManager
) getActivity().getSystemService(Context
.ACCOUNT_SERVICE
); 
 316                 OwnCloudVersion ocVersion 
= new OwnCloudVersion(accManager
 
 317                         .getUserData(ocAccount
, AccountAuthenticator
.KEY_OC_VERSION
)); 
 318                 if(ocVersion
.compareTo(new OwnCloudVersion(0x030004)) >= 0 || ocVersion
.compareTo(new OwnCloudVersion(0x040001)) >= 0){ 
 327      * Once the file download has finished -> update view 
 328      * @author Bartek Przybylski 
 330     private class DownloadFinishReceiver 
extends BroadcastReceiver 
{ 
 332         public void onReceive(Context context
, Intent intent
) { 
 333             ((OCFile
)mIntent
.getParcelableExtra(EXTRA_FILE
)).setStoragePath(intent
.getStringExtra(FileDownloader
.EXTRA_FILE_PATH
)); 
 334             updateFileDetails(mIntent
);