Merge branch 'thumbnails_from_server' of https://github.com/tobiasKaminsky/android...
authorjabarros <jabarros@solidgear.es>
Fri, 24 Oct 2014 11:38:03 +0000 (13:38 +0200)
committerjabarros <jabarros@solidgear.es>
Fri, 24 Oct 2014 11:38:03 +0000 (13:38 +0200)
Conflicts:
src/com/owncloud/android/ui/adapter/FileListListAdapter.java

1  2 
src/com/owncloud/android/MainApp.java
src/com/owncloud/android/datamodel/ThumbnailsCacheManager.java
src/com/owncloud/android/ui/adapter/FileListListAdapter.java

   */
  package com.owncloud.android;
  
 -import com.owncloud.android.lib.common.OwnCloudClientManagerFactory;
 -import com.owncloud.android.lib.common.OwnCloudClientManagerFactory.Policy;
 -
  import android.app.Application;
  import android.content.Context;
 +
++import com.owncloud.android.authentication.AccountUtils;
 +import com.owncloud.android.datamodel.ThumbnailsCacheManager;
 +import com.owncloud.android.lib.common.OwnCloudClientManagerFactory;
 +import com.owncloud.android.lib.common.OwnCloudClientManagerFactory.Policy;
 +import com.owncloud.android.lib.common.utils.Log_OC;
  /**
   * Main Application of the project
   * 
@@@ -55,20 -53,7 +56,21 @@@ public class MainApp extends Applicatio
          } else {
              OwnCloudClientManagerFactory.setDefaultPolicy(Policy.ALWAYS_NEW_CLIENT);
          }
-         
++
 +        // initialise thumbnails cache on background thread
-         new ThumbnailsCacheManager.InitDiskCacheTask().execute();
++        new ThumbnailsCacheManager.InitDiskCacheTask(AccountUtils.getCurrentOwnCloudAccount(mContext),
++                mContext).execute();
          
 +        if (BuildConfig.DEBUG) {
 +
 +            String dataFolder = getDataFolder();
 +
 +            // Set folder for store logs
 +            Log_OC.setLogDataFolder(dataFolder);
 +
 +            Log_OC.startLogging();
 +            Log_OC.d("Debug", "start logging");
 +        }
      }
  
      public static Context getAppContext() {
@@@ -81,7 -66,7 +83,7 @@@
      public static String getAccountType() {
          return getAppContext().getResources().getString(R.string.account_type);
      }
 -    
 +
      //  From AccountAuthenticator 
      //  public static final String AUTHORITY = "org.owncloud";
      public static String getAuthority() {
index e75404e,0000000..2cedcb4
mode 100644,000000..100644
--- /dev/null
@@@ -1,265 -1,0 +1,329 @@@
- import android.graphics.BitmapFactory;
 +/* ownCloud Android client application
 + *   Copyright (C) 2012-2014 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,
 + *   as published by the Free Software Foundation.
 + *
 + *   This program is distributed in the hope that it will be useful,
 + *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 + *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 + *   GNU General Public License for more details.
 + *
 + *   You should have received a copy of the GNU General Public License
 + *   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 + *
 + */
 +
 +package com.owncloud.android.datamodel;
 +
 +import java.io.File;
++import java.io.IOException;
 +import java.lang.ref.WeakReference;
 +
++import org.apache.commons.httpclient.HttpStatus;
++import org.apache.commons.httpclient.methods.GetMethod;
++
++import android.accounts.Account;
++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.drawable.BitmapDrawable;
 +import android.graphics.drawable.Drawable;
 +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;
++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.utils.Log_OC;
 +import com.owncloud.android.ui.adapter.DiskLruImageCache;
 +import com.owncloud.android.utils.BitmapUtils;
 +import com.owncloud.android.utils.DisplayUtils;
 +
 +/**
 + * Manager for concurrent access to thumbnails cache. 
 + *  
 + * @author Tobias Kaminsky
 + * @author David A. Velasco
 + */
 +public class ThumbnailsCacheManager {
 +    
 +    private static final String TAG = ThumbnailsCacheManager.class.getSimpleName();
 +    
 +    private static final String CACHE_FOLDER = "thumbnailCache"; 
 +    
 +    private static final Object mThumbnailsDiskCacheLock = new Object();
 +    private static DiskLruImageCache mThumbnailCache = null;
 +    private static boolean mThumbnailCacheStarting = true;
 +    
 +    private static final int DISK_CACHE_SIZE = 1024 * 1024 * 10; // 10MB
 +    private static final CompressFormat mCompressFormat = CompressFormat.JPEG;
 +    private static final int mCompressQuality = 70;
++    private static OwnCloudClient mClient;
++
 +    public static Bitmap mDefaultImg = 
 +            BitmapFactory.decodeResource(
 +                    MainApp.getAppContext().getResources(), 
 +                    DisplayUtils.getResourceId("image/png", "default.png")
 +            );
 +
 +    
 +    public static class InitDiskCacheTask extends AsyncTask<File, Void, Void> {
++        private static Account mAccount;
++        private static Context mContext;
++
++        public InitDiskCacheTask(Account account, Context context) {
++            mAccount = account;
++            mContext = context;
++           }
++
 +        @Override
 +        protected Void doInBackground(File... params) {
 +            synchronized (mThumbnailsDiskCacheLock) {
 +                mThumbnailCacheStarting = true;
++
 +                if (mThumbnailCache == null) {
 +                    try {
++                        OwnCloudAccount ocAccount;
++                        try {
++                            ocAccount = new OwnCloudAccount(mAccount, mContext);
++                            mClient = OwnCloudClientManagerFactory.getDefaultSingleton().getClientFor(ocAccount, mContext);
++                        } catch (AccountNotFoundException e) {
++                            // TODO Auto-generated catch block
++                            e.printStackTrace();
++                        } catch (AuthenticatorException e) {
++                            // TODO Auto-generated catch block
++                            e.printStackTrace();
++                        } catch (OperationCanceledException e) {
++                            // TODO Auto-generated catch block
++                            e.printStackTrace();
++                        } catch (IOException e) {
++                            // TODO Auto-generated catch block
++                            e.printStackTrace();
++                        }
++
 +                        // Check if media is mounted or storage is built-in, if so, 
 +                        // try and use external cache dir; otherwise use internal cache dir
 +                        final String cachePath = 
 +                                MainApp.getAppContext().getExternalCacheDir().getPath() + 
 +                                File.separator + CACHE_FOLDER;
 +                        Log_OC.d(TAG, "create dir: " + cachePath);
 +                        final File diskCacheDir = new File(cachePath);
 +                        mThumbnailCache = new DiskLruImageCache(
 +                                diskCacheDir, 
 +                                DISK_CACHE_SIZE, 
 +                                mCompressFormat, 
 +                                mCompressQuality
 +                        );
 +                    } catch (Exception e) {
 +                        Log_OC.d(TAG, "Thumbnail cache could not be opened ", e);
 +                        mThumbnailCache = null;
 +                    }
 +                }
 +                mThumbnailCacheStarting = false; // Finished initialization
 +                mThumbnailsDiskCacheLock.notifyAll(); // Wake any waiting threads
 +            }
 +            return null;
 +        }
 +    }
 +    
 +    
 +    public static void addBitmapToCache(String key, Bitmap bitmap) {
 +        synchronized (mThumbnailsDiskCacheLock) {
 +            if (mThumbnailCache != null) {
 +                mThumbnailCache.put(key, bitmap);
 +            }
 +        }
 +    }
 +
 +
 +    public static Bitmap getBitmapFromDiskCache(String key) {
 +        synchronized (mThumbnailsDiskCacheLock) {
 +            // Wait while disk cache is started from background thread
 +            while (mThumbnailCacheStarting) {
 +                try {
 +                    mThumbnailsDiskCacheLock.wait();
 +                } catch (InterruptedException e) {}
 +            }
 +            if (mThumbnailCache != null) {
 +                return (Bitmap) mThumbnailCache.getBitmap(key);
 +            }
 +        }
 +        return null;
 +    }
 +
 +    
 +    public static boolean cancelPotentialWork(OCFile file, ImageView imageView) {
 +        final ThumbnailGenerationTask bitmapWorkerTask = getBitmapWorkerTask(imageView);
 +
 +        if (bitmapWorkerTask != null) {
 +            final OCFile 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();
 +            if (drawable instanceof AsyncDrawable) {
 +                final AsyncDrawable asyncDrawable = (AsyncDrawable) drawable;
 +                return asyncDrawable.getBitmapWorkerTask();
 +            }
 +         }
 +         return null;
 +     }
 +
 +    public static class ThumbnailGenerationTask extends AsyncTask<OCFile, Void, Bitmap> {
 +        private final WeakReference<ImageView> mImageViewReference;
 +        private OCFile mFile;
 +        private FileDataStorageManager mStorageManager;
 +        
 +        public ThumbnailGenerationTask(ImageView imageView, FileDataStorageManager storageManager) {
 +         // Use a WeakReference to ensure the ImageView can be garbage collected
 +            mImageViewReference = new WeakReference<ImageView>(imageView);
 +            if (storageManager == null)
 +                throw new IllegalArgumentException("storageManager must not be NULL");
 +            mStorageManager = storageManager;
 +        }
 +
 +        // Decode image in background.
 +        @Override
 +        protected Bitmap doInBackground(OCFile... params) {
 +            Bitmap thumbnail = null;
 +            
 +            try {
 +                mFile = params[0];
 +                final String imageKey = String.valueOf(mFile.getRemoteId());
 +    
 +                // Check disk cache in background thread
 +                thumbnail = getBitmapFromDiskCache(imageKey);
 +    
 +                // Not found in disk cache
 +                if (thumbnail == null || mFile.needsUpdateThumbnail()) { 
 +                    // Converts dp to pixel
 +                    Resources r = MainApp.getAppContext().getResources();
 +                    int px = (int) Math.round(TypedValue.applyDimension(
 +                            TypedValue.COMPLEX_UNIT_DIP, 150, r.getDisplayMetrics()
 +                    ));
 +                    
 +                    if (mFile.isDown()){
 +                        Bitmap bitmap = BitmapUtils.decodeSampledBitmapFromFile(
 +                                mFile.getStoragePath(), px, px);
 +                        
 +                        if (bitmap != null) {
 +                            thumbnail = ThumbnailUtils.extractThumbnail(bitmap, px, px);
 +    
 +                            // Add thumbnail to cache
 +                            addBitmapToCache(imageKey, thumbnail);
 +
 +                            mFile.setNeedsUpdateThumbnail(false);
 +                            mStorageManager.saveFile(mFile);
 +                        }
 +    
++                    } else {
++                        // Download thumbnail from server
++                        try {
++                            int status = -1;
++
++                            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);
++                            if (status == HttpStatus.SC_OK) {
++                                byte[] bytes = get.getResponseBody();
++                                Bitmap bitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
++                                thumbnail = ThumbnailUtils.extractThumbnail(bitmap, px, px);
++
++                                // Add thumbnail to cache
++                                if (thumbnail != null) {
++                                    addBitmapToCache(imageKey, thumbnail);
++                                }
++                            }
++                        } catch (Exception e) {
++                            e.printStackTrace();
++                        }
 +                    }
 +                }
 +                
 +            } 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 (mImageViewReference != null && bitmap != null) {
 +                final ImageView imageView = mImageViewReference.get();
 +                final ThumbnailGenerationTask bitmapWorkerTask =
 +                        getBitmapWorkerTask(imageView);
 +                if (this == bitmapWorkerTask && imageView != null) {
 +                    if (imageView.getTag().equals(mFile.getFileId())) {
 +                        imageView.setImageBitmap(bitmap);
 +                    }
 +                }
 +            }
 +        }
 +    }
 +  
 +    
 +    public static class AsyncDrawable extends BitmapDrawable {
 +        private final WeakReference<ThumbnailGenerationTask> bitmapWorkerTaskReference;
 +
 +        public AsyncDrawable(
 +                Resources res, Bitmap bitmap, ThumbnailGenerationTask bitmapWorkerTask
 +            ) {
 +            
 +            super(res, bitmap);
 +            bitmapWorkerTaskReference =
 +                new WeakReference<ThumbnailGenerationTask>(bitmapWorkerTask);
 +        }
 +
 +        public ThumbnailGenerationTask getBitmapWorkerTask() {
 +            return bitmapWorkerTaskReference.get();
 +        }
 +    }
 +
 +    
 +    /**
 +     * Remove from cache the remoteId passed
 +     * @param fileRemoteId: remote id of mFile passed
 +     */
 +    public static void removeFileFromCache(String fileRemoteId){
 +        synchronized (mThumbnailsDiskCacheLock) {
 +            if (mThumbnailCache != null) {
 +                mThumbnailCache.removeKey(fileRemoteId);
 +            }
 +            mThumbnailsDiskCacheLock.notifyAll(); // Wake any waiting threads
 +        }
 +    }
 +
 +}
   */\r
  package com.owncloud.android.ui.adapter;\r
  \r
 -import java.io.File;\r
 -import java.io.IOException;\r
 -import java.lang.ref.WeakReference;\r
  import java.util.Vector;\r
  \r
 -import org.apache.commons.httpclient.methods.GetMethod;\r
 -import org.apache.http.HttpStatus;\r
 -\r
  import android.accounts.Account;\r
 -import android.accounts.AuthenticatorException;\r
 -import android.accounts.OperationCanceledException;\r
  import android.content.Context;\r
 -import android.content.res.Resources;\r
  import android.graphics.Bitmap;\r
 -import android.graphics.Bitmap.CompressFormat;\r
 -import android.graphics.BitmapFactory;\r
 -import android.graphics.drawable.BitmapDrawable;\r
 -import android.graphics.drawable.Drawable;\r
 -import android.media.ThumbnailUtils;\r
 -import android.net.Uri;\r
 -import android.os.AsyncTask;\r
 -import android.util.TypedValue;\r
  import android.view.LayoutInflater;\r
  import android.view.View;\r
  import android.view.ViewGroup;\r
@@@ -35,49 -52,208 +35,50 @@@ import com.owncloud.android.R
  import com.owncloud.android.authentication.AccountUtils;\r
  import com.owncloud.android.datamodel.FileDataStorageManager;\r
  import com.owncloud.android.datamodel.OCFile;\r
 +import com.owncloud.android.datamodel.ThumbnailsCacheManager;\r
 +import com.owncloud.android.datamodel.ThumbnailsCacheManager.AsyncDrawable;\r
  import com.owncloud.android.files.services.FileDownloader.FileDownloaderBinder;\r
  import com.owncloud.android.files.services.FileUploader.FileUploaderBinder;\r
 -import com.owncloud.android.lib.common.OwnCloudAccount;\r
 -import com.owncloud.android.lib.common.OwnCloudClient;\r
 -import com.owncloud.android.lib.common.OwnCloudClientManagerFactory;\r
 -import com.owncloud.android.lib.common.accounts.AccountUtils.AccountNotFoundException;\r
  import com.owncloud.android.ui.activity.ComponentsGetter;\r
  import com.owncloud.android.utils.DisplayUtils;\r
 -import com.owncloud.android.utils.Log_OC;\r
 +\r
  \r
  /**\r
   * This Adapter populates a ListView with all files and folders in an ownCloud\r
   * instance.\r
   * \r
   * @author Bartek Przybylski\r
 - * @Author Tobias Kaminsky\r
 - * \r
 + * @author Tobias Kaminsky\r
 + * @author David A. Velasco\r
   */\r
  public class FileListListAdapter extends BaseAdapter implements ListAdapter {\r
      private final static String PERMISSION_SHARED_WITH_ME = "S";\r
 -\r
 -    private final Context mContext;\r
 +    \r
 +    private Context mContext;\r
      private OCFile mFile = null;\r
      private Vector<OCFile> mFiles = null;\r
 -    private final boolean mJustFolders;\r
 -\r
 -    private FileDataStorageManager mStorageManager;\r
 -    private Account mAccount;\r
 -    private final ComponentsGetter mTransferServiceGetter;\r
 -\r
 -    private final Object thumbnailDiskCacheLock = new Object();\r
 -    private DiskLruImageCache mThumbnailCache;\r
 -    private boolean mThumbnailCacheStarting = true;\r
 -    private static final int DISK_CACHE_SIZE = 1024 * 1024 * 10; // 10MB\r
 -    private static final CompressFormat mCompressFormat = CompressFormat.JPEG;\r
 -    private static final int mCompressQuality = 70;\r
 -    private final Bitmap defaultImg;\r
 -    private OwnCloudClient client;\r
 -\r
 -    public FileListListAdapter(boolean justFolders, Context context, ComponentsGetter transferServiceGetter) {\r
 +    private boolean mJustFolders;\r
 +\r
 +    private FileDataStorageManager mStorageManager;
 +    private Account mAccount;
 +    private ComponentsGetter mTransferServiceGetter;\r
 +    \r
 +    public FileListListAdapter(\r
 +            boolean justFolders, \r
 +            Context context, \r
 +            ComponentsGetter transferServiceGetter\r
 +            ) {\r
-         \r
\r
          mJustFolders = justFolders;\r
          mContext = context;\r
          mAccount = AccountUtils.getCurrentOwnCloudAccount(mContext);\r
          mTransferServiceGetter = transferServiceGetter;\r
-         \r
 -        defaultImg = BitmapFactory.decodeResource(mContext.getResources(),\r
 -                DisplayUtils.getResourceId("image/png", "default.png"));\r
 -\r
 -        // Initialise disk cache on background thread\r
 -        new InitDiskCacheTask().execute();\r
 -\r
 -    }\r
 -\r
 -    class InitDiskCacheTask extends AsyncTask<File, Void, Void> {\r
 -        @Override\r
 -        protected Void doInBackground(File... params) {\r
 -            synchronized (thumbnailDiskCacheLock) {\r
 -                OwnCloudAccount ocAccount;\r
 -                try {\r
 -                    ocAccount = new OwnCloudAccount(mAccount, mContext);\r
 -                    client = OwnCloudClientManagerFactory.getDefaultSingleton().getClientFor(ocAccount, mContext);\r
 -                } catch (AccountNotFoundException e) {\r
 -                    // TODO Auto-generated catch block\r
 -                    e.printStackTrace();\r
 -                } catch (AuthenticatorException e) {\r
 -                    // TODO Auto-generated catch block\r
 -                    e.printStackTrace();\r
 -                } catch (OperationCanceledException e) {\r
 -                    // TODO Auto-generated catch block\r
 -                    e.printStackTrace();\r
 -                } catch (IOException e) {\r
 -                    // TODO Auto-generated catch block\r
 -                    e.printStackTrace();\r
 -                }\r
 -\r
 -                mThumbnailCache = new DiskLruImageCache(mContext, "thumbnailCache", DISK_CACHE_SIZE, mCompressFormat,\r
 -                        mCompressQuality);\r
 -\r
 -                mThumbnailCacheStarting = false; // Finished initialization\r
 -                thumbnailDiskCacheLock.notifyAll(); // Wake any waiting threads\r
 -            }\r
 -            return null;\r
 -        }\r
 -    }\r
 -\r
 -    static class AsyncDrawable extends BitmapDrawable {\r
 -        private final WeakReference<ThumbnailGenerationTask> bitmapWorkerTaskReference;\r
 -\r
 -        public AsyncDrawable(Resources res, Bitmap bitmap, ThumbnailGenerationTask bitmapWorkerTask) {\r
 -            super(res, bitmap);\r
 -            bitmapWorkerTaskReference = new WeakReference<ThumbnailGenerationTask>(bitmapWorkerTask);\r
 -        }\r
 -\r
 -        public ThumbnailGenerationTask getBitmapWorkerTask() {\r
 -            return bitmapWorkerTaskReference.get();\r
 -        }\r
 -    }\r
 -\r
 -    class ThumbnailGenerationTask extends AsyncTask<OCFile, Void, Bitmap> {\r
 -        private final WeakReference<ImageView> imageViewReference;\r
 -        private OCFile file;\r
 -\r
 -        public ThumbnailGenerationTask(ImageView imageView) {\r
 -            // Use a WeakReference to ensure the ImageView can be garbage\r
 -            // collected\r
 -            imageViewReference = new WeakReference<ImageView>(imageView);\r
 -        }\r
 -\r
 -        // Decode image in background.\r
 -        @Override\r
 -        protected Bitmap doInBackground(OCFile... params) {\r
 -            file = params[0];\r
 -            final String imageKey = String.valueOf(file.getRemoteId().hashCode());\r
 -            Log_OC.d("Thumbnail", imageKey);\r
 -\r
 -            // Check disk cache in background thread\r
 -            Bitmap thumbnail = getBitmapFromDiskCache(imageKey);\r
 -\r
 -            // Not found in disk cache\r
 -            if (thumbnail == null) {\r
 -                // Converts dp to pixel\r
 -                Resources r = mContext.getResources();\r
 -                int px = Math.round(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 32, r.getDisplayMetrics()));\r
 -\r
 -                if (file.isDown()) {\r
 -                    Bitmap bitmap = BitmapFactory.decodeFile(file.getStoragePath());\r
 -\r
 -                    if (bitmap != null) {\r
 -                        thumbnail = ThumbnailUtils.extractThumbnail(bitmap, px, px);\r
 -\r
 -                        // Add thumbnail to cache\r
 -                        addBitmapToCache(imageKey, thumbnail);\r
 -                    }\r
 -\r
 -                } else {\r
 -                    // Download thumbnail from server\r
 -                    try {\r
 -                        int status = -1;\r
 -\r
 -                        String uri = client.getBaseUri() + "/index.php/apps/files/api/v1/thumbnail/" + px + "/" + px\r
 -                                + "/" + Uri.encode(file.getRemotePath(), "/");\r
 -                        Log_OC.d("Thumbnail", "URI: " + uri);\r
 -                        GetMethod get = new GetMethod(uri);\r
 -                        status = client.executeMethod(get);\r
 -                        if (status == HttpStatus.SC_OK) {\r
 -                            byte[] bytes = get.getResponseBody();\r
 -                            Bitmap bitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.length);\r
 -                            thumbnail = ThumbnailUtils.extractThumbnail(bitmap, px, px);\r
 -\r
 -                            // Add thumbnail to cache\r
 -                            if (thumbnail != null) {\r
 -                                addBitmapToCache(imageKey, thumbnail);\r
 -                            }\r
 -                        }\r
 -                    } catch (Exception e) {\r
 -                        e.printStackTrace();\r
 -                    }\r
 -                }\r
 -            }\r
 -            return thumbnail;\r
 -        }\r
\r
 -        @Override\r
 -        protected void onPostExecute(Bitmap bitmap) {\r
 -            if (isCancelled()) {\r
 -                bitmap = null;\r
 -            }\r
 +        // initialise thumbnails cache on background thread\r
-         new ThumbnailsCacheManager.InitDiskCacheTask().execute();\r
++        new ThumbnailsCacheManager.InitDiskCacheTask(mAccount, mContext).execute();\r
\r
 -            if (imageViewReference != null && bitmap != null) {\r
 -                final ImageView imageView = imageViewReference.get();\r
 -                final ThumbnailGenerationTask bitmapWorkerTask = getBitmapWorkerTask(imageView);\r
 -                if (this == bitmapWorkerTask && imageView != null) {\r
 -                    imageView.setImageBitmap(bitmap);\r
 -                }\r
 -            }\r
 -        }\r
      }\r
 -\r
 -    public void addBitmapToCache(String key, Bitmap bitmap) {\r
 -        synchronized (thumbnailDiskCacheLock) {\r
 -            if (mThumbnailCache != null && mThumbnailCache.getBitmap(key) == null) {\r
 -                mThumbnailCache.put(key, bitmap);\r
 -            }\r
 -        }\r
 -    }\r
 -\r
 -    public Bitmap getBitmapFromDiskCache(String key) {\r
 -        synchronized (thumbnailDiskCacheLock) {\r
 -            // Wait while disk cache is started from background thread\r
 -            while (mThumbnailCacheStarting) {\r
 -                try {\r
 -                    thumbnailDiskCacheLock.wait();\r
 -                } catch (InterruptedException e) {\r
 -                }\r
 -            }\r
 -            if (mThumbnailCache != null) {\r
 -                return mThumbnailCache.getBitmap(key);\r
 -            }\r
 -        }\r
 -        return null;\r
 -    }\r
 -\r
 +    \r
      @Override\r
      public boolean areAllItemsEnabled() {\r
          return true;\r
      public View getView(int position, View convertView, ViewGroup parent) {\r
          View view = convertView;\r
          if (view == null) {\r
 -            LayoutInflater inflator = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);\r
 +            LayoutInflater inflator = (LayoutInflater) mContext\r
 +                    .getSystemService(Context.LAYOUT_INFLATER_SERVICE);\r
              view = inflator.inflate(R.layout.list_item, null);\r
          }\r
 -\r
 +         \r
          if (mFiles != null && mFiles.size() > position) {\r
              OCFile file = mFiles.get(position);\r
 -            TextView fileName = (TextView) view.findViewById(R.id.Filename);\r
 +            TextView fileName = (TextView) view.findViewById(R.id.Filename);           \r
              String name = file.getFileName();\r
  \r
              fileName.setText(name);\r
              ImageView fileIcon = (ImageView) view.findViewById(R.id.imageView1);\r
 +            fileIcon.setTag(file.getFileId());\r
              ImageView sharedIconV = (ImageView) view.findViewById(R.id.sharedIcon);\r
              ImageView sharedWithMeIconV = (ImageView) view.findViewById(R.id.sharedWithMeIcon);\r
              sharedWithMeIconV.setVisibility(View.GONE);\r
  \r
              ImageView localStateView = (ImageView) view.findViewById(R.id.imageView2);\r
              localStateView.bringToFront();\r
 -            FileDownloaderBinder downloaderBinder = mTransferServiceGetter.getFileDownloaderBinder();\r
 +            FileDownloaderBinder downloaderBinder = \r
 +                    mTransferServiceGetter.getFileDownloaderBinder();\r
              FileUploaderBinder uploaderBinder = mTransferServiceGetter.getFileUploaderBinder();\r
              if (downloaderBinder != null && downloaderBinder.isDownloading(mAccount, file)) {\r
                  localStateView.setImageResource(R.drawable.downloading_file_indicator);\r
              } else {\r
                  localStateView.setVisibility(View.INVISIBLE);\r
              }\r
 -\r
 +            \r
              TextView fileSizeV = (TextView) view.findViewById(R.id.file_size);\r
              TextView lastModV = (TextView) view.findViewById(R.id.last_mod);\r
              ImageView checkBoxV = (ImageView) view.findViewById(R.id.custom_checkbox);\r
 -\r
 +            \r
              if (!file.isFolder()) {\r
                  fileSizeV.setVisibility(View.VISIBLE);\r
                  fileSizeV.setText(DisplayUtils.bytesToHumanReadable(file.getFileLength()));\r
                  lastModV.setVisibility(View.VISIBLE);\r
 -                lastModV.setText(DisplayUtils.unixTimeToHumanReadable(file.getModificationTimestamp()));\r
 -                // this if-else is needed even thoe fav icon is visible by\r
 -                // default\r
 +                lastModV.setText(\r
 +                        DisplayUtils.unixTimeToHumanReadable(file.getModificationTimestamp())\r
 +                );\r
 +                // this if-else is needed even thoe fav icon is visible by default\r
                  // because android reuses views in listview\r
                  if (!file.keepInSync()) {\r
                      view.findViewById(R.id.imageView3).setVisibility(View.GONE);\r
                  } else {\r
                      view.findViewById(R.id.imageView3).setVisibility(View.VISIBLE);\r
                  }\r
 -\r
 -                ListView parentList = (ListView) parent;\r
 -                if (parentList.getChoiceMode() == ListView.CHOICE_MODE_NONE) {\r
 +                \r
 +                ListView parentList = (ListView)parent;\r
 +                if (parentList.getChoiceMode() == ListView.CHOICE_MODE_NONE) { \r
                      checkBoxV.setVisibility(View.GONE);\r
                  } else {\r
                      if (parentList.isItemChecked(position)) {\r
                          checkBoxV.setImageResource(android.R.drawable.checkbox_off_background);\r
                      }\r
                      checkBoxV.setVisibility(View.VISIBLE);\r
 -                }\r
 -\r
 +                }               \r
 +                \r
                  // get Thumbnail if file is image\r
 -                if (file.isImage()) {\r
 -                    // Thumbnail in Cache?\r
 -                    Bitmap thumbnail = getBitmapFromDiskCache(String.valueOf(file.getRemoteId().hashCode()));\r
 -                    if (thumbnail != null) {\r
 +                if (file.isImage() && file.getRemoteId() != null){\r
 +                     // Thumbnail in Cache?\r
 +                    Bitmap thumbnail = ThumbnailsCacheManager.getBitmapFromDiskCache(\r
 +                            String.valueOf(file.getRemoteId())\r
 +                    );\r
 +                    if (thumbnail != null && !file.needsUpdateThumbnail()){\r
                          fileIcon.setImageBitmap(thumbnail);\r
                      } else {\r
                          // generate new Thumbnail\r
 -                        if (cancelPotentialWork(file, fileIcon)) {\r
 -                            final ThumbnailGenerationTask task = new ThumbnailGenerationTask(fileIcon);\r
 -                            final AsyncDrawable asyncDrawable = new AsyncDrawable(mContext.getResources(), defaultImg,\r
 -                                    task);\r
 +                        if (ThumbnailsCacheManager.cancelPotentialWork(file, fileIcon)) {\r
 +                            final ThumbnailsCacheManager.ThumbnailGenerationTask task = \r
 +                                    new ThumbnailsCacheManager.ThumbnailGenerationTask(\r
 +                                            fileIcon, mStorageManager\r
 +                                    );\r
 +                            if (thumbnail == null) {\r
 +                                thumbnail = ThumbnailsCacheManager.mDefaultImg;\r
 +                            }\r
 +                            final AsyncDrawable asyncDrawable = new AsyncDrawable(\r
 +                                    mContext.getResources(), \r
 +                                    thumbnail, \r
 +                                    task\r
 +                            );\r
                              fileIcon.setImageDrawable(asyncDrawable);\r
                              task.execute(file);\r
                          }\r
                      }\r
                  } else {\r
 -                    fileIcon.setImageResource(DisplayUtils.getResourceId(file.getMimetype(), file.getFileName()));\r
 +                    fileIcon.setImageResource(\r
 +                            DisplayUtils.getResourceId(file.getMimetype(), file.getFileName())\r
 +                    );\r
                  }\r
 -\r
 +
                  if (checkIfFileIsSharedWithMe(file)) {\r
                      sharedWithMeIconV.setVisibility(View.VISIBLE);\r
                  }\r
 -            } else {\r
 +            } \r
 +            else {\r
                  fileSizeV.setVisibility(View.INVISIBLE);\r
 -                // fileSizeV.setText(DisplayUtils.bytesToHumanReadable(file.getFileLength()));\r
 +                //fileSizeV.setText(DisplayUtils.bytesToHumanReadable(file.getFileLength()));\r
                  lastModV.setVisibility(View.VISIBLE);\r
 -                lastModV.setText(DisplayUtils.unixTimeToHumanReadable(file.getModificationTimestamp()));\r
 +                lastModV.setText(\r
 +                        DisplayUtils.unixTimeToHumanReadable(file.getModificationTimestamp())\r
 +                );\r
                  checkBoxV.setVisibility(View.GONE);\r
                  view.findViewById(R.id.imageView3).setVisibility(View.GONE);\r
  \r
                      fileIcon.setImageResource(R.drawable.shared_with_me_folder);\r
                      sharedWithMeIconV.setVisibility(View.VISIBLE);\r
                  } else {\r
 -                    fileIcon.setImageResource(DisplayUtils.getResourceId(file.getMimetype(), file.getFileName()));\r
 +                    fileIcon.setImageResource(\r
 +                            DisplayUtils.getResourceId(file.getMimetype(), file.getFileName())\r
 +                    );\r
                  }\r
  \r
                  // If folder is sharedByLink, icon folder must be changed to\r
  \r
          return view;\r
      }\r
 -\r
 -    public static boolean cancelPotentialWork(OCFile file, ImageView imageView) {\r
 -        final ThumbnailGenerationTask bitmapWorkerTask = getBitmapWorkerTask(imageView);\r
 -\r
 -        if (bitmapWorkerTask != null) {\r
 -            final OCFile bitmapData = bitmapWorkerTask.file;\r
 -            // If bitmapData is not yet set or it differs from the new data\r
 -            if (bitmapData == null || bitmapData != file) {\r
 -                // Cancel previous task\r
 -                bitmapWorkerTask.cancel(true);\r
 -            } else {\r
 -                // The same work is already in progress\r
 -                return false;\r
 -            }\r
 -        }\r
 -        // No task associated with the ImageView, or an existing task was\r
 -        // cancelled\r
 -        return true;\r
 -    }\r
 -\r
 -    private static ThumbnailGenerationTask getBitmapWorkerTask(ImageView imageView) {\r
 -        if (imageView != null) {\r
 -            final Drawable drawable = imageView.getDrawable();\r
 -            if (drawable instanceof AsyncDrawable) {\r
 -                final AsyncDrawable asyncDrawable = (AsyncDrawable) drawable;\r
 -                return asyncDrawable.getBitmapWorkerTask();\r
 -            }\r
 -        }\r
 -        return null;\r
 -    }\r
 -\r
 +    \r
      @Override\r
      public int getViewTypeCount() {\r
          return 1;\r
  \r
      /**\r
       * Change the adapted directory for a new one\r
 -     * \r
 -     * @param directory New file to adapt. Can be NULL, meaning\r
 -     *            "no content to adapt".\r
 -     * @param updatedStorageManager Optional updated storage manager; used to\r
 -     *            replace mStorageManager if is different (and not NULL)\r
 +     * @param directory                 New file to adapt. Can be NULL, meaning \r
 +     *                                  "no content to adapt".\r
 +     * @param updatedStorageManager     Optional updated storage manager; used to replace \r
 +     *                                  mStorageManager if is different (and not NULL)\r
       */\r
      public void swapDirectory(OCFile directory, FileDataStorageManager updatedStorageManager) {\r
          mFile = directory;\r
          }\r
          notifyDataSetChanged();\r
      }\r
 -\r
 +    \r
 +    \r
      /**\r
       * Filter for getting only the folders\r
 -     * \r
       * @param files\r
       * @return Vector<OCFile>\r
       */\r
      public Vector<OCFile> getFolders(Vector<OCFile> files) {\r
 -        Vector<OCFile> ret = new Vector<OCFile>();\r
 -        OCFile current = null;\r
 -        for (int i = 0; i < files.size(); i++) {\r
 +        Vector<OCFile> ret = new Vector<OCFile>(); \r
 +        OCFile current = null; \r
 +        for (int i=0; i<files.size(); i++) {\r
              current = files.get(i);\r
              if (current.isFolder()) {\r
                  ret.add(current);\r
          }\r
          return ret;\r
      }\r
 -\r
 +    \r
 +    \r
      /**\r
       * Check if parent folder does not include 'S' permission and if file/folder\r
       * is shared with me\r
       * @return boolean: True if it is shared with me and false if it is not\r
       */\r
      private boolean checkIfFileIsSharedWithMe(OCFile file) {\r
 -        return (mFile.getPermissions() != null && !mFile.getPermissions().contains(PERMISSION_SHARED_WITH_ME)\r
 -                && file.getPermissions() != null && file.getPermissions().contains(PERMISSION_SHARED_WITH_ME));\r
 +        return (mFile.getPermissions() != null \r
 +                && !mFile.getPermissions().contains(PERMISSION_SHARED_WITH_ME)\r
 +                && file.getPermissions() != null \r
 +                && file.getPermissions().contains(PERMISSION_SHARED_WITH_ME));\r
      }\r
  }\r