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() {
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
 +        }
 +    }
 +
 +}
@@@ -53,31 -72,188 +53,32 @@@ import com.owncloud.android.utils.Displ
   */\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