--- /dev/null
- 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
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