package com.owncloud.android.ui.fragment;\r
\r
import java.io.File;\r
+import java.lang.ref.WeakReference;\r
import java.util.ArrayList;\r
import java.util.List;\r
\r
\r
import android.accounts.Account;\r
import android.accounts.AccountManager;\r
-import android.annotation.SuppressLint;\r
import android.app.Activity;\r
import android.content.ActivityNotFoundException;\r
import android.content.BroadcastReceiver;\r
+import android.content.ComponentName;\r
import android.content.Context;\r
import android.content.Intent;\r
import android.content.IntentFilter;\r
-import android.graphics.Bitmap;\r
-import android.graphics.BitmapFactory;\r
-import android.graphics.BitmapFactory.Options;\r
-import android.graphics.Point;\r
+import android.content.ServiceConnection;\r
import android.net.Uri;\r
-import android.os.AsyncTask;\r
import android.os.Bundle;\r
import android.os.Handler;\r
+import android.os.IBinder;\r
import android.support.v4.app.FragmentTransaction;\r
import android.util.Log;\r
-import android.view.Display;\r
import android.view.LayoutInflater;\r
import android.view.View;\r
import android.view.View.OnClickListener;\r
import android.widget.Button;\r
import android.widget.CheckBox;\r
import android.widget.ImageView;\r
+import android.widget.MediaController;\r
+import android.widget.ProgressBar;\r
import android.widget.TextView;\r
import android.widget.Toast;\r
\r
import com.owncloud.android.authenticator.AccountAuthenticator;\r
import com.owncloud.android.datamodel.FileDataStorageManager;\r
import com.owncloud.android.datamodel.OCFile;\r
-import com.owncloud.android.files.services.FileDownloader;\r
import com.owncloud.android.files.services.FileObserverService;\r
import com.owncloud.android.files.services.FileUploader;\r
import com.owncloud.android.files.services.FileDownloader.FileDownloaderBinder;\r
import com.owncloud.android.files.services.FileUploader.FileUploaderBinder;\r
+import com.owncloud.android.media.MediaService;\r
+import com.owncloud.android.media.MediaServiceBinder;\r
import com.owncloud.android.network.OwnCloudClientUtils;\r
import com.owncloud.android.operations.OnRemoteOperationListener;\r
import com.owncloud.android.operations.RemoteOperation;\r
import com.owncloud.android.ui.activity.ConflictsResolveActivity;\r
import com.owncloud.android.ui.activity.FileDetailActivity;\r
import com.owncloud.android.ui.activity.FileDisplayActivity;\r
-import com.owncloud.android.ui.activity.TransferServiceGetter;\r
+import com.owncloud.android.ui.activity.PreviewVideoActivity;\r
import com.owncloud.android.ui.dialog.EditNameDialog;\r
import com.owncloud.android.ui.dialog.EditNameDialog.EditNameDialogListener;\r
import com.owncloud.android.utils.OwnCloudVersion;\r
\r
import com.owncloud.android.R;\r
+\r
+import eu.alefzero.webdav.OnDatatransferProgressListener;\r
import eu.alefzero.webdav.WebdavClient;\r
import eu.alefzero.webdav.WebdavUtils;\r
\r
* This Fragment is used to display the details about a file.\r
* \r
* @author Bartek Przybylski\r
- * \r
+ * @author David A. Velasco\r
*/\r
public class FileDetailFragment extends SherlockFragment implements\r
- OnClickListener, ConfirmationDialogFragment.ConfirmationDialogFragmentListener, OnRemoteOperationListener, EditNameDialogListener {\r
+ OnClickListener, \r
+ ConfirmationDialogFragment.ConfirmationDialogFragmentListener, OnRemoteOperationListener, EditNameDialogListener,\r
+ FileFragment {\r
\r
public static final String EXTRA_FILE = "FILE";\r
public static final String EXTRA_ACCOUNT = "ACCOUNT";\r
\r
- private FileDetailFragment.ContainerActivity mContainerActivity;\r
+ private FileFragment.ContainerActivity mContainerActivity;\r
\r
private int mLayout;\r
private View mView;\r
private OCFile mFile;\r
private Account mAccount;\r
- private ImageView mPreview;\r
+ private FileDataStorageManager mStorageManager;\r
\r
- private DownloadFinishReceiver mDownloadFinishReceiver;\r
+ //private DownloadFinishReceiver mDownloadFinishReceiver;\r
private UploadFinishReceiver mUploadFinishReceiver;\r
+ public ProgressListener mProgressListener;\r
\r
private Handler mHandler;\r
private RemoteOperation mLastRemoteOperation;\r
+ \r
+ private MediaServiceBinder mMediaServiceBinder = null;\r
+ private MediaController mMediaController = null;\r
+ private MediaServiceConnection mMediaServiceConnection = null;\r
\r
private static final String TAG = FileDetailFragment.class.getSimpleName();\r
public static final String FTAG = "FileDetails"; \r
public FileDetailFragment() {\r
mFile = null;\r
mAccount = null;\r
+ mStorageManager = null;\r
mLayout = R.layout.file_details_empty;\r
+ mProgressListener = null;\r
}\r
\r
\r
public FileDetailFragment(OCFile fileToDetail, Account ocAccount) {\r
mFile = fileToDetail;\r
mAccount = ocAccount;\r
+ mStorageManager = null; // we need a context to init this; the container activity is not available yet at this moment \r
mLayout = R.layout.file_details_empty;\r
- \r
- if(fileToDetail != null && ocAccount != null) {\r
- mLayout = R.layout.file_details_fragment;\r
- }\r
+ mProgressListener = null;\r
}\r
\r
\r
mAccount = savedInstanceState.getParcelable(FileDetailFragment.EXTRA_ACCOUNT);\r
}\r
\r
+ if(mFile != null && mAccount != null) {\r
+ mLayout = R.layout.file_details_fragment;\r
+ }\r
+ \r
View view = null;\r
view = inflater.inflate(mLayout, container, false);\r
mView = view;\r
mView.findViewById(R.id.fdOpenBtn).setOnClickListener(this);\r
mView.findViewById(R.id.fdRemoveBtn).setOnClickListener(this);\r
//mView.findViewById(R.id.fdShareBtn).setOnClickListener(this);\r
- mPreview = (ImageView)mView.findViewById(R.id.fdPreview);\r
+ ProgressBar progressBar = (ProgressBar)mView.findViewById(R.id.fdProgressBar);\r
+ mProgressListener = new ProgressListener(progressBar);\r
}\r
\r
- updateFileDetails();\r
+ updateFileDetails(false, false);\r
return view;\r
}\r
\r
super.onAttach(activity);\r
try {\r
mContainerActivity = (ContainerActivity) activity;\r
+ \r
} catch (ClassCastException e) {\r
throw new ClassCastException(activity.toString() + " must implement " + FileDetailFragment.ContainerActivity.class.getSimpleName());\r
}\r
}\r
+ \r
+ \r
+ /**\r
+ * {@inheritDoc}\r
+ */\r
+ @Override\r
+ public void onActivityCreated(Bundle savedInstanceState) {\r
+ super.onActivityCreated(savedInstanceState);\r
+ if (mAccount != null) {\r
+ mStorageManager = new FileDataStorageManager(mAccount, getActivity().getApplicationContext().getContentResolver());\r
+ }\r
+ }\r
\r
\r
@Override\r
public void onSaveInstanceState(Bundle outState) {\r
- Log.i(getClass().toString(), "onSaveInstanceState() start");\r
super.onSaveInstanceState(outState);\r
outState.putParcelable(FileDetailFragment.EXTRA_FILE, mFile);\r
outState.putParcelable(FileDetailFragment.EXTRA_ACCOUNT, mAccount);\r
- Log.i(getClass().toString(), "onSaveInstanceState() end");\r
}\r
\r
+ @Override\r
+ public void onStart() {\r
+ super.onStart();\r
+ if (mFile != null && mFile.isAudio()) {\r
+ bindMediaService();\r
+ }\r
+ listenForTransferProgress();\r
+ }\r
\r
@Override\r
public void onResume() {\r
super.onResume();\r
\r
+ /*\r
mDownloadFinishReceiver = new DownloadFinishReceiver();\r
IntentFilter filter = new IntentFilter(\r
FileDownloader.DOWNLOAD_FINISH_MESSAGE);\r
getActivity().registerReceiver(mDownloadFinishReceiver, filter);\r
+ */\r
\r
mUploadFinishReceiver = new UploadFinishReceiver();\r
- filter = new IntentFilter(FileUploader.UPLOAD_FINISH_MESSAGE);\r
+ IntentFilter filter = new IntentFilter(FileUploader.UPLOAD_FINISH_MESSAGE);\r
getActivity().registerReceiver(mUploadFinishReceiver, filter);\r
- \r
- mPreview = (ImageView)mView.findViewById(R.id.fdPreview);\r
+\r
}\r
\r
+\r
@Override\r
public void onPause() {\r
super.onPause();\r
\r
- getActivity().unregisterReceiver(mDownloadFinishReceiver);\r
- mDownloadFinishReceiver = null;\r
- \r
- getActivity().unregisterReceiver(mUploadFinishReceiver);\r
- mUploadFinishReceiver = null;\r
+ /*\r
+ if (mDownloadFinishReceiver != null) {\r
+ getActivity().unregisterReceiver(mDownloadFinishReceiver);\r
+ mDownloadFinishReceiver = null;\r
+ }\r
+ */\r
\r
- if (mPreview != null) {\r
- mPreview = null;\r
+ if (mUploadFinishReceiver != null) {\r
+ getActivity().unregisterReceiver(mUploadFinishReceiver);\r
+ mUploadFinishReceiver = null;\r
}\r
}\r
\r
+ \r
+ @Override\r
+ public void onStop() {\r
+ super.onStop();\r
+ if (mMediaServiceConnection != null) {\r
+ Log.d(TAG, "Unbinding from MediaService ...");\r
+ if (mMediaServiceBinder != null && mMediaController != null) {\r
+ mMediaServiceBinder.unregisterMediaController(mMediaController);\r
+ }\r
+ getActivity().unbindService(mMediaServiceConnection);\r
+ mMediaServiceBinder = null;\r
+ if (mMediaController != null) {\r
+ mMediaController.hide();\r
+ mMediaController = null;\r
+ }\r
+ }\r
+ leaveTransferProgress();\r
+ }\r
+\r
+ \r
@Override\r
public View getView() {\r
return super.getView() == null ? mView : super.getView();\r
}\r
\r
\r
- \r
@Override\r
public void onClick(View v) {\r
- FileDataStorageManager fdsm = new FileDataStorageManager(mAccount, getActivity().getApplicationContext().getContentResolver());\r
switch (v.getId()) {\r
case R.id.fdDownloadBtn: {\r
- //if (FileDownloader.isDownloading(mAccount, mFile.getRemotePath())) {\r
FileDownloaderBinder downloaderBinder = mContainerActivity.getFileDownloaderBinder();\r
FileUploaderBinder uploaderBinder = mContainerActivity.getFileUploaderBinder();\r
if (downloaderBinder != null && downloaderBinder.isDownloading(mAccount, mFile)) {\r
}\r
\r
} else {\r
- mLastRemoteOperation = new SynchronizeFileOperation(mFile.getRemotePath(), fdsm, mAccount, true, false, getActivity());\r
+ mLastRemoteOperation = new SynchronizeFileOperation(mFile, null, mStorageManager, mAccount, true, false, getActivity());\r
WebdavClient wc = OwnCloudClientUtils.createOwnCloudClient(mAccount, getSherlockActivity().getApplicationContext());\r
mLastRemoteOperation.execute(wc, this, mHandler);\r
\r
// update ui \r
boolean inDisplayActivity = getActivity() instanceof FileDisplayActivity;\r
getActivity().showDialog((inDisplayActivity)? FileDisplayActivity.DIALOG_SHORT_WAIT : FileDetailActivity.DIALOG_SHORT_WAIT);\r
- setButtonsForTransferring(); // disable button immediately, although the synchronization does not result in a file transference\r
\r
}\r
break;\r
case R.id.fdKeepInSync: {\r
CheckBox cb = (CheckBox) getView().findViewById(R.id.fdKeepInSync);\r
mFile.setKeepInSync(cb.isChecked());\r
- fdsm.saveFile(mFile);\r
- \r
- /* NOT HERE\r
- * now that FileObserverService is involved, the easiest way to coordinate it with the download service\r
- * in every possible case is let the FileObserverService decide if the download should be started at\r
- * this moment or not\r
- * \r
- * see changes at FileObserverService#addObservedFile\r
- \r
- if (mFile.keepInSync()) {\r
- onClick(getView().findViewById(R.id.fdDownloadBtn));\r
- } else {\r
- mContainerActivity.onFileStateChanged(); // put inside 'else' to not call it twice (here, and in the virtual click on fdDownloadBtn)\r
- }*/\r
+ mStorageManager.saveFile(mFile);\r
\r
/// register the OCFile instance in the observer service to monitor local updates;\r
/// if necessary, the file is download \r
FileObserverService.CMD_DEL_OBSERVED_FILE));\r
intent.putExtra(FileObserverService.KEY_CMD_ARG_FILE, mFile);\r
intent.putExtra(FileObserverService.KEY_CMD_ARG_ACCOUNT, mAccount);\r
- Log.e(TAG, "starting observer service");\r
getActivity().startService(intent);\r
\r
- mContainerActivity.onFileStateChanged(); \r
+ if (mFile.keepInSync()) {\r
+ onClick(getView().findViewById(R.id.fdDownloadBtn)); // force an immediate synchronization\r
+ }\r
break;\r
}\r
case R.id.fdRenameBtn: {\r
- EditNameDialog dialog = EditNameDialog.newInstance(mFile.getFileName());\r
- dialog.setOnDismissListener(this);\r
+ EditNameDialog dialog = EditNameDialog.newInstance(getString(R.string.rename_dialog_title), mFile.getFileName(), this);\r
dialog.show(getFragmentManager(), "nameeditdialog");\r
break;\r
} \r
break;\r
}\r
case R.id.fdOpenBtn: {\r
- String storagePath = mFile.getStoragePath();\r
- String encodedStoragePath = WebdavUtils.encodePath(storagePath);\r
- try {\r
- Intent i = new Intent(Intent.ACTION_VIEW);\r
- i.setDataAndType(Uri.parse("file://"+ encodedStoragePath), mFile.getMimetype());\r
- i.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);\r
- startActivity(i);\r
- \r
- } catch (Throwable t) {\r
- Log.e(TAG, "Fail when trying to open with the mimeType provided from the ownCloud server: " + mFile.getMimetype());\r
- boolean toastIt = true; \r
- String mimeType = "";\r
- try {\r
- Intent i = new Intent(Intent.ACTION_VIEW);\r
- mimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension(storagePath.substring(storagePath.lastIndexOf('.') + 1));\r
- if (mimeType != null && !mimeType.equals(mFile.getMimetype())) {\r
- i.setDataAndType(Uri.parse("file://"+ encodedStoragePath), mimeType);\r
- i.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);\r
- startActivity(i);\r
- toastIt = false;\r
- }\r
- \r
- } catch (IndexOutOfBoundsException e) {\r
- Log.e(TAG, "Trying to find out MIME type of a file without extension: " + storagePath);\r
- \r
- } catch (ActivityNotFoundException e) {\r
- Log.e(TAG, "No activity found to handle: " + storagePath + " with MIME type " + mimeType + " obtained from extension");\r
- \r
- } catch (Throwable th) {\r
- Log.e(TAG, "Unexpected problem when opening: " + storagePath, th);\r
- \r
- } finally {\r
- if (toastIt) {\r
- Toast.makeText(getActivity(), "There is no application to handle file " + mFile.getFileName(), Toast.LENGTH_SHORT).show();\r
- }\r
- }\r
- \r
- }\r
+ openFile();\r
break;\r
}\r
default:\r
}\r
\r
\r
+ private void startVideoActivity() {\r
+ Intent i = new Intent(getActivity(), PreviewVideoActivity.class);\r
+ i.putExtra(PreviewVideoActivity.EXTRA_FILE, mFile);\r
+ i.putExtra(PreviewVideoActivity.EXTRA_ACCOUNT, mAccount);\r
+ startActivity(i);\r
+ }\r
+\r
+\r
+ private void bindMediaService() {\r
+ Log.d(TAG, "Binding to MediaService...");\r
+ if (mMediaServiceConnection == null) {\r
+ mMediaServiceConnection = new MediaServiceConnection();\r
+ }\r
+ getActivity().bindService( new Intent(getActivity(), \r
+ MediaService.class),\r
+ mMediaServiceConnection, \r
+ Context.BIND_AUTO_CREATE);\r
+ // follow the flow in MediaServiceConnection#onServiceConnected(...)\r
+ }\r
+ \r
+ /** Defines callbacks for service binding, passed to bindService() */\r
+ private class MediaServiceConnection implements ServiceConnection {\r
+\r
+ @Override\r
+ public void onServiceConnected(ComponentName component, IBinder service) {\r
+ if (component.equals(new ComponentName(getActivity(), MediaService.class))) {\r
+ Log.d(TAG, "Media service connected");\r
+ mMediaServiceBinder = (MediaServiceBinder) service;\r
+ if (mMediaServiceBinder != null) {\r
+ if (mMediaController == null) {\r
+ mMediaController = new MediaController(getSherlockActivity());\r
+ }\r
+ prepareMediaController();\r
+ \r
+ Log.d(TAG, "Successfully bound to MediaService, MediaController ready");\r
+ \r
+ } else {\r
+ Log.e(TAG, "Unexpected response from MediaService while binding");\r
+ }\r
+ }\r
+ }\r
+ \r
+ private void prepareMediaController() {\r
+ mMediaServiceBinder.registerMediaController(mMediaController);\r
+ mMediaController.setMediaPlayer(mMediaServiceBinder);\r
+ mMediaController.setAnchorView(getView());\r
+ mMediaController.setEnabled(mMediaServiceBinder.isInPlaybackState());\r
+ }\r
+\r
+ @Override\r
+ public void onServiceDisconnected(ComponentName component) {\r
+ if (component.equals(new ComponentName(getActivity(), MediaService.class))) {\r
+ Log.e(TAG, "Media service suddenly disconnected");\r
+ if (mMediaController != null) {\r
+ mMediaController.hide();\r
+ mMediaController.setMediaPlayer(null);\r
+ mMediaController = null;\r
+ }\r
+ mMediaServiceBinder = null;\r
+ mMediaServiceConnection = null;\r
+ }\r
+ }\r
+ } \r
+\r
+\r
+ /**\r
+ * Opens mFile.\r
+ */\r
+ private void openFile() {\r
+ \r
+ String storagePath = mFile.getStoragePath();\r
+ String encodedStoragePath = WebdavUtils.encodePath(storagePath);\r
+ try {\r
+ Intent i = new Intent(Intent.ACTION_VIEW);\r
+ i.setDataAndType(Uri.parse("file://"+ encodedStoragePath), mFile.getMimetype());\r
+ i.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);\r
+ startActivity(i);\r
+ \r
+ } catch (Throwable t) {\r
+ Log.e(TAG, "Fail when trying to open with the mimeType provided from the ownCloud server: " + mFile.getMimetype());\r
+ boolean toastIt = true; \r
+ String mimeType = "";\r
+ try {\r
+ Intent i = new Intent(Intent.ACTION_VIEW);\r
+ mimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension(storagePath.substring(storagePath.lastIndexOf('.') + 1));\r
+ if (mimeType == null || !mimeType.equals(mFile.getMimetype())) {\r
+ if (mimeType != null) {\r
+ i.setDataAndType(Uri.parse("file://"+ encodedStoragePath), mimeType);\r
+ } else {\r
+ // desperate try\r
+ i.setDataAndType(Uri.parse("file://"+ encodedStoragePath), "*/*");\r
+ }\r
+ i.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);\r
+ startActivity(i);\r
+ toastIt = false;\r
+ }\r
+ \r
+ } catch (IndexOutOfBoundsException e) {\r
+ Log.e(TAG, "Trying to find out MIME type of a file without extension: " + storagePath);\r
+ \r
+ } catch (ActivityNotFoundException e) {\r
+ Log.e(TAG, "No activity found to handle: " + storagePath + " with MIME type " + mimeType + " obtained from extension");\r
+ \r
+ } catch (Throwable th) {\r
+ Log.e(TAG, "Unexpected problem when opening: " + storagePath, th);\r
+ \r
+ } finally {\r
+ if (toastIt) {\r
+ Toast.makeText(getActivity(), "There is no application to handle file " + mFile.getFileName(), Toast.LENGTH_SHORT).show();\r
+ }\r
+ }\r
+ \r
+ }\r
+ }\r
+\r
+\r
@Override\r
public void onConfirmation(String callerTag) {\r
if (callerTag.equals(FTAG_CONFIRMATION)) {\r
- FileDataStorageManager fdsm = new FileDataStorageManager(mAccount, getActivity().getContentResolver());\r
- if (fdsm.getFileById(mFile.getFileId()) != null) {\r
+ if (mStorageManager.getFileById(mFile.getFileId()) != null) {\r
mLastRemoteOperation = new RemoveFileOperation( mFile, \r
true, \r
- new FileDataStorageManager(mAccount, getActivity().getContentResolver()));\r
+ mStorageManager);\r
WebdavClient wc = OwnCloudClientUtils.createOwnCloudClient(mAccount, getSherlockActivity().getApplicationContext());\r
mLastRemoteOperation.execute(wc, this, mHandler);\r
\r
\r
@Override\r
public void onNeutral(String callerTag) {\r
- FileDataStorageManager fdsm = new FileDataStorageManager(mAccount, getActivity().getContentResolver());\r
File f = null;\r
if (mFile.isDown() && (f = new File(mFile.getStoragePath())).exists()) {\r
f.delete();\r
mFile.setStoragePath(null);\r
- fdsm.saveFile(mFile);\r
+ mStorageManager.saveFile(mFile);\r
updateFileDetails(mFile, mAccount);\r
}\r
}\r
* @return True when the fragment was created with the empty layout.\r
*/\r
public boolean isEmpty() {\r
- return mLayout == R.layout.file_details_empty;\r
+ return (mLayout == R.layout.file_details_empty || mFile == null || mAccount == null);\r
}\r
\r
\r
/**\r
- * Can be used to get the file that is currently being displayed.\r
- * @return The file on the screen.\r
+ * {@inheritDoc}\r
*/\r
- public OCFile getDisplayedFile(){\r
+ public OCFile getFile(){\r
return mFile;\r
}\r
\r
*/\r
public void updateFileDetails(OCFile file, Account ocAccount) {\r
mFile = file;\r
+ if (ocAccount != null && ( \r
+ mStorageManager == null || \r
+ (mAccount != null && !mAccount.equals(ocAccount))\r
+ )) {\r
+ mStorageManager = new FileDataStorageManager(ocAccount, getActivity().getApplicationContext().getContentResolver());\r
+ }\r
mAccount = ocAccount;\r
- updateFileDetails();\r
+ updateFileDetails(false, false);\r
}\r
\r
\r
/**\r
* Updates the view with all relevant details about that file.\r
+ *\r
+ * TODO Remove parameter when the transferring state of files is kept in database. \r
+ * \r
+ * TODO REFACTORING! this method called 5 times before every time the fragment is shown! \r
+ * \r
+ * @param transferring Flag signaling if the file should be considered as downloading or uploading, \r
+ * although {@link FileDownloaderBinder#isDownloading(Account, OCFile)} and \r
+ * {@link FileUploaderBinder#isUploading(Account, OCFile)} return false.\r
+ * \r
+ * @param refresh If 'true', try to refresh the hold file from the database\r
*/\r
- public void updateFileDetails() {\r
+ public void updateFileDetails(boolean transferring, boolean refresh) {\r
\r
- if (mFile != null && mAccount != null && mLayout == R.layout.file_details_fragment) {\r
+ if (readyToShow()) {\r
+ \r
+ if (refresh && mStorageManager != null) {\r
+ mFile = mStorageManager.getFileByPath(mFile.getRemotePath());\r
+ }\r
\r
// set file details\r
setFilename(mFile.getFileName());\r
- setFiletype(DisplayUtils.convertMIMEtoPrettyPrint(mFile\r
- .getMimetype()));\r
+ setFiletype(mFile.getMimetype());\r
setFilesize(mFile.getFileLength());\r
if(ocVersionSupportsTimeCreated()){\r
setTimeCreated(mFile.getCreationTimestamp());\r
//if (FileDownloader.isDownloading(mAccount, mFile.getRemotePath()) || FileUploader.isUploading(mAccount, mFile.getRemotePath())) {\r
FileDownloaderBinder downloaderBinder = mContainerActivity.getFileDownloaderBinder();\r
FileUploaderBinder uploaderBinder = mContainerActivity.getFileUploaderBinder();\r
- if ((downloaderBinder != null && downloaderBinder.isDownloading(mAccount, mFile)) || (uploaderBinder != null && uploaderBinder.isUploading(mAccount, mFile))) {\r
+ if (transferring || (downloaderBinder != null && downloaderBinder.isDownloading(mAccount, mFile)) || (uploaderBinder != null && uploaderBinder.isUploading(mAccount, mFile))) {\r
setButtonsForTransferring();\r
\r
} else if (mFile.isDown()) {\r
- // Update preview\r
- if (mFile.getMimetype().startsWith("image/")) {\r
- BitmapLoader bl = new BitmapLoader();\r
- bl.execute(new String[]{mFile.getStoragePath()});\r
- }\r
\r
setButtonsForDown();\r
\r
} else {\r
+ // TODO load default preview image; when the local file is removed, the preview remains there\r
setButtonsForRemote();\r
}\r
}\r
+ getView().invalidate();\r
}\r
\r
\r
/**\r
+ * Checks if the fragment is ready to show details of a OCFile\r
+ * \r
+ * @return 'True' when the fragment is ready to show details of a file\r
+ */\r
+ private boolean readyToShow() {\r
+ return (mFile != null && mAccount != null && mLayout == R.layout.file_details_fragment); \r
+ }\r
+\r
+\r
+\r
+ /**\r
* Updates the filename in view\r
* @param filename to set\r
*/\r
*/\r
private void setFiletype(String mimetype) {\r
TextView tv = (TextView) getView().findViewById(R.id.fdType);\r
- if (tv != null)\r
- tv.setText(mimetype);\r
+ if (tv != null) {\r
+ String printableMimetype = DisplayUtils.convertMIMEtoPrettyPrint(mimetype);; \r
+ tv.setText(printableMimetype);\r
+ }\r
+ ImageView iv = (ImageView) getView().findViewById(R.id.fdIcon);\r
+ if (iv != null) {\r
+ iv.setImageResource(DisplayUtils.getResourceId(mimetype));\r
+ }\r
}\r
\r
/**\r
((Button) getView().findViewById(R.id.fdRenameBtn)).setEnabled(false);\r
((Button) getView().findViewById(R.id.fdRemoveBtn)).setEnabled(false);\r
getView().findViewById(R.id.fdKeepInSync).setEnabled(false);\r
+ \r
+ // show the progress bar for the transfer\r
+ ProgressBar progressBar = (ProgressBar)getView().findViewById(R.id.fdProgressBar);\r
+ progressBar.setVisibility(View.VISIBLE);\r
+ TextView progressText = (TextView)getView().findViewById(R.id.fdProgressText);\r
+ progressText.setVisibility(View.VISIBLE);\r
+ FileDownloaderBinder downloaderBinder = mContainerActivity.getFileDownloaderBinder();\r
+ FileUploaderBinder uploaderBinder = mContainerActivity.getFileUploaderBinder();\r
+ if (downloaderBinder != null && downloaderBinder.isDownloading(mAccount, mFile)) {\r
+ progressText.setText(R.string.downloader_download_in_progress_ticker);\r
+ } else if (uploaderBinder != null && uploaderBinder.isUploading(mAccount, mFile)) {\r
+ progressText.setText(R.string.uploader_upload_in_progress_ticker);\r
+ }\r
}\r
}\r
\r
+\r
/**\r
* Enables or disables buttons for a file locally available \r
*/\r
private void setButtonsForDown() {\r
if (!isEmpty()) {\r
Button downloadButton = (Button) getView().findViewById(R.id.fdDownloadBtn);\r
- downloadButton.setText(R.string.filedetails_redownload);\r
- //downloadButton.setEnabled(true);\r
+ downloadButton.setText(R.string.filedetails_sync_file);\r
\r
((Button) getView().findViewById(R.id.fdOpenBtn)).setEnabled(true);\r
((Button) getView().findViewById(R.id.fdRenameBtn)).setEnabled(true);\r
((Button) getView().findViewById(R.id.fdRemoveBtn)).setEnabled(true);\r
getView().findViewById(R.id.fdKeepInSync).setEnabled(true);\r
+ \r
+ // hides the progress bar\r
+ ProgressBar progressBar = (ProgressBar)getView().findViewById(R.id.fdProgressBar);\r
+ progressBar.setVisibility(View.GONE);\r
+ TextView progressText = (TextView)getView().findViewById(R.id.fdProgressText);\r
+ progressText.setVisibility(View.GONE);\r
}\r
}\r
\r
((Button) getView().findViewById(R.id.fdRenameBtn)).setEnabled(true);\r
((Button) getView().findViewById(R.id.fdRemoveBtn)).setEnabled(true);\r
getView().findViewById(R.id.fdKeepInSync).setEnabled(true);\r
+ \r
+ // hides the progress bar\r
+ ProgressBar progressBar = (ProgressBar)getView().findViewById(R.id.fdProgressBar);\r
+ progressBar.setVisibility(View.GONE);\r
+ TextView progressText = (TextView)getView().findViewById(R.id.fdProgressText);\r
+ progressText.setVisibility(View.GONE);\r
}\r
}\r
\r
\r
\r
/**\r
- * Interface to implement by any Activity that includes some instance of FileDetailFragment\r
- * \r
- * @author David A. Velasco\r
- */\r
- public interface ContainerActivity extends TransferServiceGetter {\r
-\r
- /**\r
- * Callback method invoked when the detail fragment wants to notice its container \r
- * activity about a relevant state the file shown by the fragment.\r
- * \r
- * Added to notify to FileDisplayActivity about the need of refresh the files list. \r
- * \r
- * Currently called when:\r
- * - a download is started;\r
- * - a rename is completed;\r
- * - a deletion is completed;\r
- * - the 'inSync' flag is changed;\r
- */\r
- public void onFileStateChanged();\r
- \r
- }\r
- \r
-\r
- /**\r
- * Once the file download has finished -> update view\r
- * @author Bartek Przybylski\r
- */\r
- private class DownloadFinishReceiver extends BroadcastReceiver {\r
- @Override\r
- public void onReceive(Context context, Intent intent) {\r
- String accountName = intent.getStringExtra(FileDownloader.ACCOUNT_NAME);\r
-\r
- if (!isEmpty() && accountName.equals(mAccount.name)) {\r
- boolean downloadWasFine = intent.getBooleanExtra(FileDownloader.EXTRA_DOWNLOAD_RESULT, false);\r
- String downloadedRemotePath = intent.getStringExtra(FileDownloader.EXTRA_REMOTE_PATH);\r
- if (mFile.getRemotePath().equals(downloadedRemotePath)) {\r
- if (downloadWasFine) {\r
- mFile.setStoragePath(intent.getStringExtra(FileDownloader.EXTRA_FILE_PATH)); // updates the local object without accessing the database again\r
- }\r
- updateFileDetails(); // it updates the buttons; must be called although !downloadWasFine\r
- }\r
- }\r
- }\r
- }\r
- \r
- \r
- /**\r
* Once the file upload has finished -> update view\r
* \r
* Being notified about the finish of an upload is necessary for the next sequence:\r
if (!isEmpty() && accountName.equals(mAccount.name)) {\r
boolean uploadWasFine = intent.getBooleanExtra(FileUploader.EXTRA_UPLOAD_RESULT, false);\r
String uploadRemotePath = intent.getStringExtra(FileUploader.EXTRA_REMOTE_PATH);\r
- if (mFile.getRemotePath().equals(uploadRemotePath)) {\r
+ boolean renamedInUpload = mFile.getRemotePath().equals(intent.getStringExtra(FileUploader.EXTRA_OLD_REMOTE_PATH));\r
+ if (mFile.getRemotePath().equals(uploadRemotePath) ||\r
+ renamedInUpload) {\r
if (uploadWasFine) {\r
- FileDataStorageManager fdsm = new FileDataStorageManager(mAccount, getActivity().getApplicationContext().getContentResolver());\r
- mFile = fdsm.getFileByPath(mFile.getRemotePath());\r
+ mFile = mStorageManager.getFileByPath(uploadRemotePath);\r
+ }\r
+ if (renamedInUpload) {\r
+ String newName = (new File(uploadRemotePath)).getName();\r
+ Toast msg = Toast.makeText(getActivity().getApplicationContext(), String.format(getString(R.string.filedetails_renamed_in_upload_msg), newName), Toast.LENGTH_LONG);\r
+ msg.show();\r
}\r
- updateFileDetails(); // it updates the buttons; must be called although !uploadWasFine; interrupted uploads still leave an incomplete file in the server\r
+ getSherlockActivity().removeStickyBroadcast(intent); // not the best place to do this; a small refactorization of BroadcastReceivers should be done\r
+ updateFileDetails(false, false); // it updates the buttons; must be called although !uploadWasFine; interrupted uploads still leave an incomplete file in the server\r
}\r
}\r
}\r
String newFilename = dialog.getNewFilename();\r
Log.d(TAG, "name edit dialog dismissed with new name " + newFilename);\r
mLastRemoteOperation = new RenameFileOperation( mFile, \r
+ mAccount, \r
newFilename, \r
new FileDataStorageManager(mAccount, getActivity().getContentResolver()));\r
WebdavClient wc = OwnCloudClientUtils.createOwnCloudClient(mAccount, getSherlockActivity().getApplicationContext());\r
}\r
\r
\r
- class BitmapLoader extends AsyncTask<String, Void, Bitmap> {\r
- @SuppressLint({ "NewApi", "NewApi", "NewApi" }) // to avoid Lint errors since Android SDK r20\r
- @Override\r
- protected Bitmap doInBackground(String... params) {\r
- Bitmap result = null;\r
- if (params.length != 1) return result;\r
- String storagePath = params[0];\r
- try {\r
-\r
- BitmapFactory.Options options = new Options();\r
- options.inScaled = true;\r
- options.inPurgeable = true;\r
- options.inJustDecodeBounds = true;\r
- if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.GINGERBREAD_MR1) {\r
- options.inPreferQualityOverSpeed = false;\r
- }\r
- if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.HONEYCOMB) {\r
- options.inMutable = false;\r
- }\r
-\r
- result = BitmapFactory.decodeFile(storagePath, options);\r
- options.inJustDecodeBounds = false;\r
-\r
- int width = options.outWidth;\r
- int height = options.outHeight;\r
- int scale = 1;\r
- if (width >= 2048 || height >= 2048) {\r
- scale = (int) Math.ceil((Math.ceil(Math.max(height, width) / 2048.)));\r
- options.inSampleSize = scale;\r
- }\r
- Display display = getActivity().getWindowManager().getDefaultDisplay();\r
- Point size = new Point();\r
- int screenwidth;\r
- if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.HONEYCOMB_MR2) {\r
- display.getSize(size);\r
- screenwidth = size.x;\r
- } else {\r
- screenwidth = display.getWidth();\r
- }\r
-\r
- Log.e("ASD", "W " + width + " SW " + screenwidth);\r
-\r
- if (width > screenwidth) {\r
- scale = (int) Math.ceil((float)width / screenwidth);\r
- options.inSampleSize = scale;\r
- }\r
-\r
- result = BitmapFactory.decodeFile(storagePath, options);\r
-\r
- Log.e("ASD", "W " + options.outWidth + " SW " + options.outHeight);\r
-\r
- } catch (OutOfMemoryError e) {\r
- result = null;\r
- Log.e(TAG, "Out of memory occured for file with size " + storagePath);\r
- \r
- } catch (NoSuchFieldError e) {\r
- result = null;\r
- Log.e(TAG, "Error from access to unexisting field despite protection " + storagePath);\r
- \r
- } catch (Throwable t) {\r
- result = null;\r
- Log.e(TAG, "Unexpected error while creating image preview " + storagePath, t);\r
- }\r
- return result;\r
- }\r
- @Override\r
- protected void onPostExecute(Bitmap result) {\r
- if (result != null && mPreview != null) {\r
- mPreview.setImageBitmap(result);\r
- }\r
- }\r
- \r
- }\r
-\r
/**\r
* {@inheritDoc}\r
*/\r
if (!result.isSuccess()) {\r
if (result.getCode() == ResultCode.SYNC_CONFLICT) {\r
Intent i = new Intent(getActivity(), ConflictsResolveActivity.class);\r
- //i.setFlags(i.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK);\r
- i.putExtra("remotepath", mFile.getRemotePath());\r
- i.putExtra("localpath", mFile.getStoragePath());\r
- i.putExtra("account", mAccount);\r
+ i.putExtra(ConflictsResolveActivity.EXTRA_FILE, mFile);\r
+ i.putExtra(ConflictsResolveActivity.EXTRA_ACCOUNT, mAccount);\r
startActivity(i);\r
\r
} else {\r
msg.show();\r
}\r
\r
+ if (mFile.isDown()) {\r
+ setButtonsForDown();\r
+ \r
+ } else {\r
+ setButtonsForRemote();\r
+ }\r
+ \r
} else {\r
if (operation.transferWasRequested()) {\r
+ setButtonsForTransferring();\r
mContainerActivity.onFileStateChanged(); // this is not working; FileDownloader won't do NOTHING at all until this method finishes, so \r
// checking the service to see if the file is downloading results in FALSE\r
} else {\r
}\r
}\r
}\r
+ \r
+ \r
+ public void listenForTransferProgress() {\r
+ if (mProgressListener != null) {\r
+ if (mContainerActivity.getFileDownloaderBinder() != null) {\r
+ mContainerActivity.getFileDownloaderBinder().addDatatransferProgressListener(mProgressListener, mAccount, mFile);\r
+ }\r
+ if (mContainerActivity.getFileUploaderBinder() != null) {\r
+ mContainerActivity.getFileUploaderBinder().addDatatransferProgressListener(mProgressListener, mAccount, mFile);\r
+ }\r
+ }\r
+ }\r
+ \r
+ \r
+ public void leaveTransferProgress() {\r
+ if (mProgressListener != null) {\r
+ if (mContainerActivity.getFileDownloaderBinder() != null) {\r
+ mContainerActivity.getFileDownloaderBinder().removeDatatransferProgressListener(mProgressListener, mAccount, mFile);\r
+ }\r
+ if (mContainerActivity.getFileUploaderBinder() != null) {\r
+ mContainerActivity.getFileUploaderBinder().removeDatatransferProgressListener(mProgressListener, mAccount, mFile);\r
+ }\r
+ }\r
+ }\r
+\r
+\r
+ \r
+ /**\r
+ * Helper class responsible for updating the progress bar shown for file uploading or downloading \r
+ * \r
+ * @author David A. Velasco\r
+ */\r
+ private class ProgressListener implements OnDatatransferProgressListener {\r
+ int mLastPercent = 0;\r
+ WeakReference<ProgressBar> mProgressBar = null;\r
+ \r
+ ProgressListener(ProgressBar progressBar) {\r
+ mProgressBar = new WeakReference<ProgressBar>(progressBar);\r
+ }\r
+ \r
+ @Override\r
+ public void onTransferProgress(long progressRate) {\r
+ // old method, nothing here\r
+ };\r
+\r
+ @Override\r
+ public void onTransferProgress(long progressRate, long totalTransferredSoFar, long totalToTransfer, String filename) {\r
+ int percent = (int)(100.0*((double)totalTransferredSoFar)/((double)totalToTransfer));\r
+ if (percent != mLastPercent) {\r
+ ProgressBar pb = mProgressBar.get();\r
+ if (pb != null) {\r
+ pb.setProgress(percent);\r
+ pb.postInvalidate();\r
+ }\r
+ }\r
+ mLastPercent = percent;\r
+ }\r
+\r
+ };\r
+ \r
+\r
\r
}\r