X-Git-Url: http://git.linex4red.de/pub/Android/ownCloud.git/blobdiff_plain/fd7a940deefe91a8e547d99a2054370510b68090..25718e7992ac273156f58d679ffc2cf3dad0c3c3:/src/com/owncloud/android/ui/preview/PreviewImageFragment.java diff --git a/src/com/owncloud/android/ui/preview/PreviewImageFragment.java b/src/com/owncloud/android/ui/preview/PreviewImageFragment.java index 4dd5c436..f8f6e10b 100644 --- a/src/com/owncloud/android/ui/preview/PreviewImageFragment.java +++ b/src/com/owncloud/android/ui/preview/PreviewImageFragment.java @@ -1,5 +1,8 @@ -/* ownCloud Android client application - * Copyright (C) 2012-2014 ownCloud Inc. +/** + * ownCloud Android client application + * + * @author David A. Velasco + * Copyright (C) 2015 ownCloud Inc. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2, @@ -36,6 +39,9 @@ import android.os.Bundle; import android.support.v4.app.FragmentStatePagerAdapter; import android.view.Display; import android.view.LayoutInflater; +import android.view.Menu; +import android.view.MenuInflater; +import android.view.MenuItem; import android.view.View; import android.view.View.OnClickListener; import android.view.ViewGroup; @@ -43,9 +49,6 @@ import android.widget.ImageView; import android.widget.ProgressBar; import android.widget.TextView; -import com.actionbarsherlock.view.Menu; -import com.actionbarsherlock.view.MenuInflater; -import com.actionbarsherlock.view.MenuItem; import com.owncloud.android.R; import com.owncloud.android.datamodel.OCFile; import com.owncloud.android.files.FileMenuFilter; @@ -53,18 +56,19 @@ import com.owncloud.android.lib.common.utils.Log_OC; import com.owncloud.android.ui.dialog.ConfirmationDialogFragment; import com.owncloud.android.ui.dialog.RemoveFileDialogFragment; import com.owncloud.android.ui.fragment.FileFragment; -import com.owncloud.android.utils.TouchImageViewCustom; +import com.owncloud.android.utils.BitmapUtils; +import third_parties.michaelOrtiz.TouchImageViewCustom; /** * This fragment shows a preview of a downloaded image. * - * Trying to get an instance with NULL {@link OCFile} or ownCloud {@link Account} values will produce an {@link IllegalStateException}. - * - * If the {@link OCFile} passed is not downloaded, an {@link IllegalStateException} is generated on instantiation too. + * Trying to get an instance with NULL {@link OCFile} or ownCloud {@link Account} values will + * produce an {@link IllegalStateException}. * - * @author David A. Velasco + * If the {@link OCFile} passed is not downloaded, an {@link IllegalStateException} is generated on + * instantiation too. */ public class PreviewImageFragment extends FileFragment { @@ -82,6 +86,8 @@ public class PreviewImageFragment extends FileFragment { private static final String TAG = PreviewImageFragment.class.getSimpleName(); private boolean mIgnoreFirstSavedState; + + private LoadBitmapTask mLoadBitmapTask = null; /** @@ -89,11 +95,13 @@ public class PreviewImageFragment extends FileFragment { * * When 'imageFile' or 'ocAccount' are null * - * @param imageFile An {@link OCFile} to preview as an image in the fragment + * @param fileToDetail An {@link OCFile} to preview as an image in the fragment * @param ocAccount An ownCloud account; needed to start downloads - * @param ignoreFirstSavedState Flag to work around an unexpected behaviour of {@link FragmentStatePagerAdapter}; TODO better solution + * @param ignoreFirstSavedState Flag to work around an unexpected behaviour of + * {@link FragmentStatePagerAdapter}; TODO better solution */ - public PreviewImageFragment(OCFile fileToDetail, Account ocAccount, boolean ignoreFirstSavedState) { + public PreviewImageFragment(OCFile fileToDetail, Account ocAccount, + boolean ignoreFirstSavedState) { super(fileToDetail); mAccount = ocAccount; mIgnoreFirstSavedState = ignoreFirstSavedState; @@ -103,9 +111,11 @@ public class PreviewImageFragment extends FileFragment { /** * Creates an empty fragment for image previews. * - * MUST BE KEPT: the system uses it when tries to reinstantiate a fragment automatically (for instance, when the device is turned a aside). + * MUST BE KEPT: the system uses it when tries to reinstantiate a fragment automatically + * (for instance, when the device is turned a aside). * - * DO NOT CALL IT: an {@link OCFile} and {@link Account} must be provided for a successful construction + * DO NOT CALL IT: an {@link OCFile} and {@link Account} must be provided for a successful + * construction */ public PreviewImageFragment() { super(); @@ -156,7 +166,8 @@ public class PreviewImageFragment extends FileFragment { super.onActivityCreated(savedInstanceState); if (savedInstanceState != null) { if (!mIgnoreFirstSavedState) { - OCFile file = (OCFile)savedInstanceState.getParcelable(PreviewImageFragment.EXTRA_FILE); + OCFile file = (OCFile)savedInstanceState.getParcelable( + PreviewImageFragment.EXTRA_FILE); setFile(file); mAccount = savedInstanceState.getParcelable(PreviewImageFragment.EXTRA_ACCOUNT); } else { @@ -190,12 +201,22 @@ public class PreviewImageFragment extends FileFragment { public void onStart() { super.onStart(); if (getFile() != null) { - BitmapLoader bl = new BitmapLoader(mImageView, mMessageView, mProgressWheel); - bl.execute(new String[]{getFile().getStoragePath()}); + mLoadBitmapTask = new LoadBitmapTask(mImageView, mMessageView, mProgressWheel); + mLoadBitmapTask.execute(new String[]{getFile().getStoragePath()}); } } + @Override + public void onStop() { + super.onStop(); + if (mLoadBitmapTask != null) { + mLoadBitmapTask.cancel(true); + mLoadBitmapTask = null; + } + + } + /** * {@inheritDoc} */ @@ -220,7 +241,7 @@ public class PreviewImageFragment extends FileFragment { getFile(), mContainerActivity.getStorageManager().getAccount(), mContainerActivity, - getSherlockActivity() + getActivity() ); mf.filter(menu); } @@ -329,27 +350,30 @@ public class PreviewImageFragment extends FileFragment { } - private class BitmapLoader extends AsyncTask { + private class LoadBitmapTask extends AsyncTask { /** * Weak reference to the target {@link ImageView} where the bitmap will be loaded into. * - * Using a weak reference will avoid memory leaks if the target ImageView is retired from memory before the load finishes. + * Using a weak reference will avoid memory leaks if the target ImageView is retired from + * memory before the load finishes. */ private final WeakReference mImageViewRef; /** * Weak reference to the target {@link TextView} where error messages will be written. * - * Using a weak reference will avoid memory leaks if the target ImageView is retired from memory before the load finishes. + * Using a weak reference will avoid memory leaks if the target ImageView is retired from + * memory before the load finishes. */ private final WeakReference mMessageViewRef; /** - * Weak reference to the target {@link Progressbar} shown while the load is in progress. + * Weak reference to the target {@link ProgressBar} shown while the load is in progress. * - * Using a weak reference will avoid memory leaks if the target ImageView is retired from memory before the load finishes. + * Using a weak reference will avoid memory leaks if the target ImageView is retired from + * memory before the load finishes. */ private final WeakReference mProgressWheelRef; @@ -365,7 +389,8 @@ public class PreviewImageFragment extends FileFragment { * * @param imageView Target {@link ImageView} where the bitmap will be loaded into. */ - public BitmapLoader(ImageViewCustom imageView, TextView messageView, ProgressBar progressWheel) { + public LoadBitmapTask(ImageViewCustom imageView, TextView messageView, + ProgressBar progressWheel) { mImageViewRef = new WeakReference(imageView); mMessageViewRef = new WeakReference(messageView); mProgressWheelRef = new WeakReference(progressWheel); @@ -379,43 +404,65 @@ public class PreviewImageFragment extends FileFragment { String storagePath = params[0]; try { + if (isCancelled()) return result; + File picture = new File(storagePath); if (picture != null) { - //Decode file into a bitmap in real size for being able to make zoom on the image + // Decode file into a bitmap in real size for being able to make zoom on + // the image result = BitmapFactory.decodeStream(new FlushedInputStream (new BufferedInputStream(new FileInputStream(picture)))); } + if (isCancelled()) return result; + if (result == null) { mErrorMessageId = R.string.preview_image_error_unknown_format; Log_OC.e(TAG, "File could not be loaded as a bitmap: " + storagePath); + } else { + // Rotate image, obeying exif tag. + result = BitmapUtils.rotateImage(result, storagePath); } } catch (OutOfMemoryError e) { Log_OC.e(TAG, "Out of memory occured for file " + storagePath, e); - // If out of memory error when loading image, try to load it scaled + if (isCancelled()) return result; + + // If out of memory error when loading or rotating image, try to load it scaled result = loadScaledImage(storagePath); if (result == null) { mErrorMessageId = R.string.preview_image_error_unknown_format; Log_OC.e(TAG, "File could not be loaded as a bitmap: " + storagePath); + } else { + // Rotate scaled image, obeying exif tag + result = BitmapUtils.rotateImage(result, storagePath); } } catch (NoSuchFieldError e) { mErrorMessageId = R.string.common_error_unknown; - Log_OC.e(TAG, "Error from access to unexisting field despite protection; file " + storagePath, e); + Log_OC.e(TAG, "Error from access to unexisting field despite protection; file " + + storagePath, e); } catch (Throwable t) { mErrorMessageId = R.string.common_error_unknown; Log_OC.e(TAG, "Unexpected error loading " + getFile().getStoragePath(), t); } + return result; } @Override + protected void onCancelled(Bitmap result) { + if (result != null) { + result.recycle(); + } + } + + @Override protected void onPostExecute(Bitmap result) { hideProgressWheel(); if (result != null) { @@ -424,7 +471,7 @@ public class PreviewImageFragment extends FileFragment { showErrorMessage(); } } - + @SuppressLint("InlinedApi") private void showLoadedImage(Bitmap result) { if (mImageViewRef != null) { @@ -473,7 +520,8 @@ public class PreviewImageFragment extends FileFragment { } /** - * Helper method to test if an {@link OCFile} can be passed to a {@link PreviewImageFragment} to be previewed. + * Helper method to test if an {@link OCFile} can be passed to a {@link PreviewImageFragment} + * to be previewed. * * @param file File to test if can be previewed. * @return 'True' if the file can be handled by the fragment. @@ -539,7 +587,8 @@ public class PreviewImageFragment extends FileFragment { if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.HONEYCOMB) { options.inMutable = false; } - // make a false load of the bitmap - just to be able to read outWidth, outHeight and outMimeType + // make a false load of the bitmap - just to be able to read outWidth, outHeight and + // outMimeType options.inJustDecodeBounds = true; BitmapFactory.decodeFile(storagePath, options);