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
import android.view.View.OnTouchListener;\r
import android.view.ViewGroup;\r
import android.webkit.MimeTypeMap;\r
+import android.webkit.WebView.FindListener;\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
+import android.widget.VideoView;\r
\r
import com.actionbarsherlock.app.SherlockFragment;\r
import com.owncloud.android.AccountUtils;\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.OnSwipeTouchListener;\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, OnTouchListener, \r
- 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 FileDataStorageManager mStorageManager;\r
- private ImageView mPreview;\r
\r
private DownloadFinishReceiver mDownloadFinishReceiver;\r
private UploadFinishReceiver mUploadFinishReceiver;\r
+ public ProgressListener mProgressListener;\r
\r
private Handler mHandler;\r
private RemoteOperation mLastRemoteOperation;\r
- private DialogFragment mCurrentDialog;\r
+ \r
private MediaServiceBinder mMediaServiceBinder = null;\r
private MediaController mMediaController = null;\r
private MediaServiceConnection mMediaServiceConnection = null;\r
mAccount = null;\r
mStorageManager = null;\r
mLayout = R.layout.file_details_empty;\r
+ mProgressListener = null;\r
}\r
\r
\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
+ mProgressListener = null;\r
}\r
\r
\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
- mPreview.setOnTouchListener(this);\r
+ ProgressBar progressBar = (ProgressBar)mView.findViewById(R.id.fdProgressBar);\r
+ mProgressListener = new ProgressListener(progressBar);\r
}\r
\r
updateFileDetails(false);\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
super.onActivityCreated(savedInstanceState);\r
if (mAccount != null) {\r
mStorageManager = new FileDataStorageManager(mAccount, getActivity().getApplicationContext().getContentResolver());;\r
+ mView.setOnTouchListener(new OnSwipeTouchListener(getActivity())); \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
if (mFile != null && mFile.isAudio()) {\r
bindMediaService();\r
}\r
+ listenForTransferProgress();\r
}\r
\r
@Override\r
filter = new IntentFilter(FileUploader.UPLOAD_FINISH_MESSAGE);\r
getActivity().registerReceiver(mUploadFinishReceiver, filter);\r
\r
- mPreview = (ImageView)mView.findViewById(R.id.fdPreview); // this is here just because it is nullified in onPause()\r
- \r
- if (mMediaController != null) {\r
- mMediaController.show();\r
- }\r
}\r
\r
\r
\r
getActivity().unregisterReceiver(mUploadFinishReceiver);\r
mUploadFinishReceiver = null;\r
- \r
- if (mPreview != null) { // why?\r
- mPreview = null;\r
- }\r
- \r
- if (mMediaController != null) {\r
- mMediaController.hide();\r
- }\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
- mMediaController = null;\r
+ if (mMediaController != null) {\r
+ mMediaController.hide();\r
+ mMediaController = null;\r
+ }\r
}\r
+ leaveTransferProgress();\r
}\r
\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
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
if (mFile.keepInSync()) {\r
mFile.isDown() ? R.string.confirmation_remove_local : -1,\r
R.string.common_cancel);\r
confDialog.setOnConfirmationListener(this);\r
- mCurrentDialog = confDialog;\r
- mCurrentDialog.show(getFragmentManager(), FTAG_CONFIRMATION);\r
+ confDialog.show(getFragmentManager(), FTAG_CONFIRMATION);\r
break;\r
}\r
case R.id.fdOpenBtn: {\r
}\r
\r
\r
- @Override\r
- public boolean onTouch(View v, MotionEvent event) {\r
- if (v == mPreview && event.getAction() == MotionEvent.ACTION_DOWN && mFile != null && mFile.isDown() && mFile.isAudio()) {\r
- if (!mMediaServiceBinder.isPlaying(mFile)) {\r
- Log.d(TAG, "starting playback of " + mFile.getStoragePath());\r
- mMediaServiceBinder.start(mAccount, mFile);\r
- // this is a patch; need to synchronize this with the onPrepared() coming from MediaPlayer in the MediaService\r
- mMediaController.postDelayed(new Runnable() {\r
- @Override\r
- public void run() {\r
- mMediaController.show(0);\r
- }\r
- } , 300);\r
- } else {\r
- mMediaController.show(0);\r
- }\r
- }\r
- return false;\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
+\r
private void bindMediaService() {\r
Log.d(TAG, "Binding to MediaService...");\r
if (mMediaServiceConnection == null) {\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
if (mMediaController == null) {\r
mMediaController = new MediaController(getSherlockActivity());\r
}\r
- mMediaController.setMediaPlayer(mMediaServiceBinder);\r
- mMediaController.setAnchorView(mPreview);\r
- mMediaController.setEnabled(true);\r
+ prepareMediaController();\r
\r
Log.d(TAG, "Successfully bound to MediaService, MediaController ready");\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.d(TAG, "Media service suddenly disconnected");\r
+ Log.e(TAG, "Media service suddenly disconnected");\r
if (mMediaController != null) {\r
mMediaController.hide();\r
- mMediaController.setMediaPlayer(null); // TODO check this is not an error\r
+ mMediaController.setMediaPlayer(null);\r
mMediaController = null;\r
}\r
mMediaServiceBinder = null;\r
getActivity().showDialog((inDisplayActivity)? FileDisplayActivity.DIALOG_SHORT_WAIT : FileDetailActivity.DIALOG_SHORT_WAIT);\r
}\r
}\r
- mCurrentDialog.dismiss();\r
- mCurrentDialog = null;\r
}\r
\r
@Override\r
mStorageManager.saveFile(mFile);\r
updateFileDetails(mFile, mAccount);\r
}\r
- mCurrentDialog.dismiss();\r
- mCurrentDialog = null;\r
}\r
\r
@Override\r
public void onCancel(String callerTag) {\r
Log.d(TAG, "REMOVAL CANCELED");\r
- mCurrentDialog.dismiss();\r
- mCurrentDialog = null;\r
}\r
\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
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
((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
((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
if (downloadWasFine) {\r
mFile = mStorageManager.getFileByPath(downloadedRemotePath);\r
}\r
+ mContainerActivity.notifySuccessfulDownload(mFile, intent, downloadWasFine);\r
+ getActivity().removeStickyBroadcast(intent);\r
updateFileDetails(false); // it updates the buttons; must be called although !downloadWasFine\r
}\r
}\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
\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