Move isImage method to BitmapUtils class
[pub/Android/ownCloud.git] / src / com / owncloud / android / datamodel / ThumbnailsCacheManager.java
index 5540aa5..bf62a23 100644 (file)
@@ -18,7 +18,6 @@
 package com.owncloud.android.datamodel;
 
 import java.io.File;
-import java.io.IOException;
 import java.lang.ref.WeakReference;
 
 import org.apache.commons.httpclient.HttpStatus;
@@ -26,19 +25,17 @@ import org.apache.commons.httpclient.methods.GetMethod;
 
 import android.accounts.Account;
 import android.accounts.AccountManager;
-import android.accounts.AuthenticatorException;
-import android.accounts.OperationCanceledException;
-import android.content.Context;
 import android.content.res.Resources;
 import android.graphics.Bitmap;
 import android.graphics.Bitmap.CompressFormat;
 import android.graphics.BitmapFactory;
+import android.graphics.Matrix;
 import android.graphics.drawable.BitmapDrawable;
 import android.graphics.drawable.Drawable;
+import android.media.ExifInterface;
 import android.media.ThumbnailUtils;
 import android.net.Uri;
 import android.os.AsyncTask;
-import android.util.TypedValue;
 import android.widget.ImageView;
 
 import com.owncloud.android.MainApp;
@@ -46,7 +43,6 @@ import com.owncloud.android.R;
 import com.owncloud.android.lib.common.OwnCloudAccount;
 import com.owncloud.android.lib.common.OwnCloudClient;
 import com.owncloud.android.lib.common.OwnCloudClientManagerFactory;
-import com.owncloud.android.lib.common.accounts.AccountUtils.AccountNotFoundException;
 import com.owncloud.android.lib.common.accounts.AccountUtils.Constants;
 import com.owncloud.android.lib.common.utils.Log_OC;
 import com.owncloud.android.lib.resources.status.OwnCloudVersion;
@@ -85,11 +81,6 @@ public class ThumbnailsCacheManager {
 
     
     public static class InitDiskCacheTask extends AsyncTask<File, Void, Void> {
-        private static Context mContext;
-
-        public InitDiskCacheTask(Context context) {
-            mContext = context;
-           }
 
         @Override
         protected Void doInBackground(File... params) {
@@ -167,6 +158,24 @@ public class ThumbnailsCacheManager {
         return true;
     }
     
+    public static boolean cancelPotentialWork(File file, ImageView imageView) {
+        final ThumbnailLocalGenerationTask bitmapWorkerTask = getBitmapLocalWorkerTask(imageView);
+
+        if (bitmapWorkerTask != null) {
+            final File bitmapData = bitmapWorkerTask.mFile;
+            // If bitmapData is not yet set or it differs from the new data
+            if (bitmapData == null || bitmapData != file) {
+                // Cancel previous task
+                bitmapWorkerTask.cancel(true);
+            } else {
+                // The same work is already in progress
+                return false;
+            }
+        }
+        // No task associated with the ImageView, or an existing task was cancelled
+        return true;
+    }
+    
     public static ThumbnailGenerationTask getBitmapWorkerTask(ImageView imageView) {
         if (imageView != null) {
             final Drawable drawable = imageView.getDrawable();
@@ -177,6 +186,84 @@ public class ThumbnailsCacheManager {
          }
          return null;
      }
+    
+    public static ThumbnailLocalGenerationTask getBitmapLocalWorkerTask(ImageView imageView) {
+        if (imageView != null) {
+            final Drawable drawable = imageView.getDrawable();
+            if (drawable instanceof AsyncLocalDrawable) {
+                final AsyncLocalDrawable asyncDrawable = (AsyncLocalDrawable) drawable;
+                return asyncDrawable.getBitmapWorkerTask();
+            }
+         }
+         return null;
+     }
+    
+    public static class ThumbnailLocalGenerationTask extends AsyncTask<File, Void, Bitmap> {
+        private final WeakReference<ImageView> mImageViewLocalReference;
+        private File mFile;
+        
+        public ThumbnailLocalGenerationTask(ImageView imageView) {
+         // Use a WeakReference to ensure the ImageView can be garbage collected
+            mImageViewLocalReference = new WeakReference<ImageView>(imageView);
+        }
+
+        // Decode image in background.
+        @Override
+        protected Bitmap doInBackground(File... params) {
+            Bitmap thumbnail = null;
+            
+            try {
+                mFile = params[0];
+                final String imageKey = String.valueOf(mFile.hashCode());
+    
+                // Check disk cache in background thread
+                thumbnail = getBitmapFromDiskCache(imageKey);
+    
+                // Not found in disk cache
+                if (thumbnail == null) { 
+                    // Converts dp to pixel
+                    Resources r = MainApp.getAppContext().getResources();
+                    
+                    int px = (int) Math.round(r.getDimension(R.dimen.file_icon_size));
+                    
+                    Bitmap bitmap = BitmapUtils.decodeSampledBitmapFromFile(
+                            mFile.getAbsolutePath(), px, px);
+                    
+                    if (bitmap != null) {
+                        thumbnail = ThumbnailUtils.extractThumbnail(bitmap, px, px);
+
+                        // Add thumbnail to cache
+                        addBitmapToCache(imageKey, thumbnail);
+                    }
+                }
+                
+            } catch (Throwable t) {
+                // the app should never break due to a problem with thumbnails
+                Log_OC.e(TAG, "Generation of thumbnail for " + mFile + " failed", t);
+                if (t instanceof OutOfMemoryError) {
+                    System.gc();
+                }
+            }
+            
+            return thumbnail;
+        }
+        
+        protected void onPostExecute(Bitmap bitmap){
+            if (isCancelled()) {
+                bitmap = null;
+            }
+
+            if (mImageViewLocalReference != null && bitmap != null) {
+                final ImageView imageView = mImageViewLocalReference.get();
+                final ThumbnailLocalGenerationTask bitmapWorkerTask = getBitmapLocalWorkerTask(imageView);
+                if (this == bitmapWorkerTask && imageView != null) {
+                    if (imageView.getTag().equals(mFile.hashCode())) {
+                        imageView.setImageBitmap(bitmap);
+                    }
+                }
+            }
+        }
+    }
 
     public static class ThumbnailGenerationTask extends AsyncTask<OCFile, Void, Bitmap> {
         private final WeakReference<ImageView> mImageViewReference;
@@ -204,7 +291,8 @@ public class ThumbnailsCacheManager {
                     
                     mServerVersion = accountMgr.getUserData(mAccount, Constants.KEY_OC_VERSION);
                     OwnCloudAccount ocAccount = new OwnCloudAccount(mAccount, MainApp.getAppContext());
-                    mClient = OwnCloudClientManagerFactory.getDefaultSingleton().getClientFor(ocAccount, MainApp.getAppContext());
+                    mClient = OwnCloudClientManagerFactory.getDefaultSingleton().
+                            getClientFor(ocAccount, MainApp.getAppContext());
                 }
                 
                 mFile = params[0];
@@ -226,6 +314,9 @@ public class ThumbnailsCacheManager {
                         
                         if (bitmap != null) {
                             thumbnail = ThumbnailUtils.extractThumbnail(bitmap, px, px);
+                            
+                            // Rotate image, obeying exif tag
+                            thumbnail = BitmapUtils.rotateImage(thumbnail, mFile.getStoragePath());
     
                             // Add thumbnail to cache
                             addBitmapToCache(imageKey, thumbnail);
@@ -242,8 +333,8 @@ public class ThumbnailsCacheManager {
                                 try {
                                     int status = -1;
 
-                                    String uri = mClient.getBaseUri() + "/index.php/apps/files/api/v1/thumbnail/" + px + "/" + px
-                                            + Uri.encode(mFile.getRemotePath(), "/");
+                                    String uri = mClient.getBaseUri() + "/index.php/apps/files/api/v1/thumbnail/" + 
+                                            px + "/" + px + Uri.encode(mFile.getRemotePath(), "/");
                                     Log_OC.d("Thumbnail", "URI: " + uri);
                                     GetMethod get = new GetMethod(uri);
                                     status = mClient.executeMethod(get);
@@ -313,6 +404,20 @@ public class ThumbnailsCacheManager {
             return bitmapWorkerTaskReference.get();
         }
     }
+    
+    public static class AsyncLocalDrawable extends BitmapDrawable {
+        private final WeakReference<ThumbnailLocalGenerationTask> bitmapWorkerLocalTaskReference;
+
+        public AsyncLocalDrawable(Resources res, Bitmap bitmap, ThumbnailLocalGenerationTask bitmapWorkerTask) {
+            super(res, bitmap);
+            bitmapWorkerLocalTaskReference =
+                new WeakReference<ThumbnailLocalGenerationTask>(bitmapWorkerTask);
+        }
+
+        public ThumbnailLocalGenerationTask getBitmapWorkerTask() {
+            return bitmapWorkerLocalTaskReference.get();
+        }
+    }
 
     
     /**
@@ -327,5 +432,5 @@ public class ThumbnailsCacheManager {
             mThumbnailsDiskCacheLock.notifyAll(); // Wake any waiting threads
         }
     }
-
+    
 }