From: jabarros Date: Fri, 24 Oct 2014 11:38:03 +0000 (+0200) Subject: Merge branch 'thumbnails_from_server' of https://github.com/tobiasKaminsky/android... X-Git-Tag: oc-android-1.7.0_signed~121^2~7 X-Git-Url: http://git.linex4red.de/pub/Android/ownCloud.git/commitdiff_plain/2e47071c9c44d687b0c69a393807ea32fde08184?ds=inline;hp=--cc Merge branch 'thumbnails_from_server' of https://github.com/tobiasKaminsky/android into thumbnails_from_server Conflicts: src/com/owncloud/android/ui/adapter/FileListListAdapter.java --- 2e47071c9c44d687b0c69a393807ea32fde08184 diff --cc src/com/owncloud/android/MainApp.java index e04239df,08efe342..37a3e6ff --- a/src/com/owncloud/android/MainApp.java +++ b/src/com/owncloud/android/MainApp.java @@@ -16,13 -16,11 +16,14 @@@ */ 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() { diff --cc src/com/owncloud/android/datamodel/ThumbnailsCacheManager.java index e75404ef,00000000..2cedcb41 mode 100644,000000..100644 --- a/src/com/owncloud/android/datamodel/ThumbnailsCacheManager.java +++ b/src/com/owncloud/android/datamodel/ThumbnailsCacheManager.java @@@ -1,265 -1,0 +1,329 @@@ +/* 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 . + * + */ + +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.BitmapFactory; +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 { ++ 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 { + private final WeakReference 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); + 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 bitmapWorkerTaskReference; + + public AsyncDrawable( + Resources res, Bitmap bitmap, ThumbnailGenerationTask bitmapWorkerTask + ) { + + super(res, bitmap); + bitmapWorkerTaskReference = + new WeakReference(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 + } + } + +} diff --cc src/com/owncloud/android/ui/adapter/FileListListAdapter.java index 0d10e7fa,64a2b579..d74bbc5b --- a/src/com/owncloud/android/ui/adapter/FileListListAdapter.java +++ b/src/com/owncloud/android/ui/adapter/FileListListAdapter.java @@@ -53,31 -72,188 +53,32 @@@ import com.owncloud.android.utils.Displ */ public class FileListListAdapter extends BaseAdapter implements ListAdapter { private final static String PERMISSION_SHARED_WITH_ME = "S"; - - private final Context mContext; + + private Context mContext; private OCFile mFile = null; private Vector mFiles = null; - private final boolean mJustFolders; - - private FileDataStorageManager mStorageManager; - private Account mAccount; - private final ComponentsGetter mTransferServiceGetter; - - private final Object thumbnailDiskCacheLock = new Object(); - private DiskLruImageCache mThumbnailCache; - private 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 final Bitmap defaultImg; - private OwnCloudClient client; - - public FileListListAdapter(boolean justFolders, Context context, ComponentsGetter transferServiceGetter) { + private boolean mJustFolders; + + private FileDataStorageManager mStorageManager; + private Account mAccount; + private ComponentsGetter mTransferServiceGetter; + + public FileListListAdapter( + boolean justFolders, + Context context, + ComponentsGetter transferServiceGetter + ) { - + mJustFolders = justFolders; mContext = context; mAccount = AccountUtils.getCurrentOwnCloudAccount(mContext); mTransferServiceGetter = transferServiceGetter; - - defaultImg = BitmapFactory.decodeResource(mContext.getResources(), - DisplayUtils.getResourceId("image/png", "default.png")); - - // Initialise disk cache on background thread - new InitDiskCacheTask().execute(); - - } - - class InitDiskCacheTask extends AsyncTask { - @Override - protected Void doInBackground(File... params) { - synchronized (thumbnailDiskCacheLock) { - OwnCloudAccount ocAccount; - try { - ocAccount = new OwnCloudAccount(mAccount, mContext); - client = 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(); - } - - mThumbnailCache = new DiskLruImageCache(mContext, "thumbnailCache", DISK_CACHE_SIZE, mCompressFormat, - mCompressQuality); - - mThumbnailCacheStarting = false; // Finished initialization - thumbnailDiskCacheLock.notifyAll(); // Wake any waiting threads - } - return null; - } - } - - static class AsyncDrawable extends BitmapDrawable { - private final WeakReference bitmapWorkerTaskReference; - - public AsyncDrawable(Resources res, Bitmap bitmap, ThumbnailGenerationTask bitmapWorkerTask) { - super(res, bitmap); - bitmapWorkerTaskReference = new WeakReference(bitmapWorkerTask); - } - - public ThumbnailGenerationTask getBitmapWorkerTask() { - return bitmapWorkerTaskReference.get(); - } - } - - class ThumbnailGenerationTask extends AsyncTask { - private final WeakReference imageViewReference; - private OCFile file; - - public ThumbnailGenerationTask(ImageView imageView) { - // Use a WeakReference to ensure the ImageView can be garbage - // collected - imageViewReference = new WeakReference(imageView); - } - - // Decode image in background. - @Override - protected Bitmap doInBackground(OCFile... params) { - file = params[0]; - final String imageKey = String.valueOf(file.getRemoteId().hashCode()); - Log_OC.d("Thumbnail", imageKey); - - // Check disk cache in background thread - Bitmap thumbnail = getBitmapFromDiskCache(imageKey); - - // Not found in disk cache - if (thumbnail == null) { - // Converts dp to pixel - Resources r = mContext.getResources(); - int px = Math.round(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 32, r.getDisplayMetrics())); - - if (file.isDown()) { - Bitmap bitmap = BitmapFactory.decodeFile(file.getStoragePath()); - - if (bitmap != null) { - thumbnail = ThumbnailUtils.extractThumbnail(bitmap, px, px); - - // Add thumbnail to cache - addBitmapToCache(imageKey, thumbnail); - } - - } else { - // Download thumbnail from server - try { - int status = -1; - - String uri = client.getBaseUri() + "/index.php/apps/files/api/v1/thumbnail/" + px + "/" + px - + "/" + Uri.encode(file.getRemotePath(), "/"); - Log_OC.d("Thumbnail", "URI: " + uri); - GetMethod get = new GetMethod(uri); - status = client.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(); - } - } - } - return thumbnail; - } + - @Override - protected void onPostExecute(Bitmap bitmap) { - if (isCancelled()) { - bitmap = null; - } + // initialise thumbnails cache on background thread - new ThumbnailsCacheManager.InitDiskCacheTask().execute(); ++ new ThumbnailsCacheManager.InitDiskCacheTask(mAccount, mContext).execute(); + - if (imageViewReference != null && bitmap != null) { - final ImageView imageView = imageViewReference.get(); - final ThumbnailGenerationTask bitmapWorkerTask = getBitmapWorkerTask(imageView); - if (this == bitmapWorkerTask && imageView != null) { - imageView.setImageBitmap(bitmap); - } - } - } } - - public void addBitmapToCache(String key, Bitmap bitmap) { - synchronized (thumbnailDiskCacheLock) { - if (mThumbnailCache != null && mThumbnailCache.getBitmap(key) == null) { - mThumbnailCache.put(key, bitmap); - } - } - } - - public Bitmap getBitmapFromDiskCache(String key) { - synchronized (thumbnailDiskCacheLock) { - // Wait while disk cache is started from background thread - while (mThumbnailCacheStarting) { - try { - thumbnailDiskCacheLock.wait(); - } catch (InterruptedException e) { - } - } - if (mThumbnailCache != null) { - return mThumbnailCache.getBitmap(key); - } - } - return null; - } - + @Override public boolean areAllItemsEnabled() { return true;