|
@@ -21,13 +21,6 @@
|
|
|
|
|
|
package com.owncloud.android.datamodel;
|
|
|
|
|
|
-import java.io.File;
|
|
|
-import java.io.InputStream;
|
|
|
-import java.lang.ref.WeakReference;
|
|
|
-
|
|
|
-import org.apache.commons.httpclient.HttpStatus;
|
|
|
-import org.apache.commons.httpclient.methods.GetMethod;
|
|
|
-
|
|
|
import android.accounts.Account;
|
|
|
import android.content.res.Resources;
|
|
|
import android.graphics.Bitmap;
|
|
@@ -35,7 +28,6 @@ import android.graphics.Bitmap.CompressFormat;
|
|
|
import android.graphics.BitmapFactory;
|
|
|
import android.graphics.Canvas;
|
|
|
import android.graphics.drawable.BitmapDrawable;
|
|
|
-import android.graphics.drawable.ColorDrawable;
|
|
|
import android.graphics.drawable.Drawable;
|
|
|
import android.media.ThumbnailUtils;
|
|
|
import android.net.Uri;
|
|
@@ -52,7 +44,13 @@ import com.owncloud.android.lib.common.utils.Log_OC;
|
|
|
import com.owncloud.android.lib.resources.status.OwnCloudVersion;
|
|
|
import com.owncloud.android.ui.adapter.DiskLruImageCache;
|
|
|
import com.owncloud.android.utils.BitmapUtils;
|
|
|
-import com.owncloud.android.utils.DisplayUtils;
|
|
|
+
|
|
|
+import org.apache.commons.httpclient.HttpStatus;
|
|
|
+import org.apache.commons.httpclient.methods.GetMethod;
|
|
|
+
|
|
|
+import java.io.File;
|
|
|
+import java.io.InputStream;
|
|
|
+import java.lang.ref.WeakReference;
|
|
|
|
|
|
/**
|
|
|
* Manager for concurrent access to thumbnails cache.
|
|
@@ -361,7 +359,194 @@ public class ThumbnailsCacheManager {
|
|
|
|
|
|
}
|
|
|
|
|
|
- public static boolean cancelPotentialWork(Object file, ImageView imageView) {
|
|
|
+ public static class AvatarGenerationTask extends AsyncTask<Object, Void, Bitmap> {
|
|
|
+ private final WeakReference<ImageView> mImageViewReference;
|
|
|
+ private static Account mAccount;
|
|
|
+ private Object mUsername;
|
|
|
+ private FileDataStorageManager mStorageManager;
|
|
|
+
|
|
|
+
|
|
|
+ public AvatarGenerationTask(ImageView imageView, FileDataStorageManager storageManager,
|
|
|
+ Account account) {
|
|
|
+ // 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;
|
|
|
+ mAccount = account;
|
|
|
+ }
|
|
|
+
|
|
|
+ public AvatarGenerationTask(ImageView imageView) {
|
|
|
+ // Use a WeakReference to ensure the ImageView can be garbage collected
|
|
|
+ mImageViewReference = new WeakReference<ImageView>(imageView);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ protected Bitmap doInBackground(Object... params) {
|
|
|
+ Bitmap thumbnail = null;
|
|
|
+
|
|
|
+ try {
|
|
|
+ if (mAccount != null) {
|
|
|
+ OwnCloudAccount ocAccount = new OwnCloudAccount(mAccount,
|
|
|
+ MainApp.getAppContext());
|
|
|
+ mClient = OwnCloudClientManagerFactory.getDefaultSingleton().
|
|
|
+ getClientFor(ocAccount, MainApp.getAppContext());
|
|
|
+ }
|
|
|
+
|
|
|
+ mUsername = params[0];
|
|
|
+
|
|
|
+ if (mUsername instanceof String) {
|
|
|
+ thumbnail = doAvatarInBackground();
|
|
|
+ }
|
|
|
+
|
|
|
+ }catch(Throwable t){
|
|
|
+ // the app should never break due to a problem with avatars
|
|
|
+ Log_OC.e(TAG, "Generation of avatar for " + mUsername + " failed", t);
|
|
|
+ if (t instanceof OutOfMemoryError) {
|
|
|
+ System.gc();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return thumbnail;
|
|
|
+ }
|
|
|
+
|
|
|
+ protected void onPostExecute(Bitmap bitmap) {
|
|
|
+ if (bitmap != null) {
|
|
|
+ final ImageView imageView = mImageViewReference.get();
|
|
|
+ final AvatarGenerationTask avatarWorkerTask = getAvatarWorkerTask(imageView);
|
|
|
+ if (this == avatarWorkerTask) {
|
|
|
+ String tagId = "";
|
|
|
+ if (mUsername instanceof String) {
|
|
|
+ tagId = (String) mUsername;
|
|
|
+ if (String.valueOf(imageView.getTag()).equals(tagId)) {
|
|
|
+ imageView.setImageBitmap(bitmap);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Add thumbnail to cache
|
|
|
+ * @param imageKey: thumb key
|
|
|
+ * @param bitmap: image for extracting thumbnail
|
|
|
+ * @param path: image path
|
|
|
+ * @param px: thumbnail dp
|
|
|
+ * @return Bitmap
|
|
|
+ */
|
|
|
+ private Bitmap addThumbnailToCache(String imageKey, Bitmap bitmap, String path, int px){
|
|
|
+
|
|
|
+ Bitmap thumbnail = ThumbnailUtils.extractThumbnail(bitmap, px, px);
|
|
|
+
|
|
|
+ // Rotate image, obeying exif tag
|
|
|
+ thumbnail = BitmapUtils.rotateImage(thumbnail,path);
|
|
|
+
|
|
|
+ // Add thumbnail to cache
|
|
|
+ addBitmapToCache(imageKey, thumbnail);
|
|
|
+
|
|
|
+ return thumbnail;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Converts size of file icon from dp to pixel
|
|
|
+ * @return int
|
|
|
+ */
|
|
|
+ private int getAvatarDimension(){
|
|
|
+ // Converts dp to pixel
|
|
|
+ Resources r = MainApp.getAppContext().getResources();
|
|
|
+ return Math.round(r.getDimension(R.dimen.file_avatar_size));
|
|
|
+ }
|
|
|
+
|
|
|
+ private Bitmap doAvatarInBackground() {
|
|
|
+ String username = (String) mUsername;
|
|
|
+
|
|
|
+ final String imageKey = "a_" + username;
|
|
|
+
|
|
|
+ // Check disk cache in background thread
|
|
|
+ Bitmap avatar = getBitmapFromDiskCache(imageKey);
|
|
|
+
|
|
|
+ // Not found in disk cache
|
|
|
+ if (avatar == null) {
|
|
|
+
|
|
|
+ int px = getAvatarDimension();
|
|
|
+
|
|
|
+ // Download avatar from server
|
|
|
+ OwnCloudVersion serverOCVersion = AccountUtils.getServerVersion(mAccount);
|
|
|
+ if (mClient != null && serverOCVersion != null) {
|
|
|
+ if (serverOCVersion.supportsRemoteThumbnails()) {
|
|
|
+ GetMethod get = null;
|
|
|
+ try {
|
|
|
+ String uri = mClient.getBaseUri() + "" +
|
|
|
+ "/index.php/avatar/" + username + "/" + px;
|
|
|
+ Log_OC.d("Avatar", "URI: " + uri);
|
|
|
+ get = new GetMethod(uri);
|
|
|
+ int status = mClient.executeMethod(get);
|
|
|
+ if (status == HttpStatus.SC_OK) {
|
|
|
+ InputStream inputStream = get.getResponseBodyAsStream();
|
|
|
+ Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
|
|
|
+ avatar = ThumbnailUtils.extractThumbnail(bitmap, px, px);
|
|
|
+
|
|
|
+ // Add avatar to cache
|
|
|
+ if (avatar != null) {
|
|
|
+ addBitmapToCache(imageKey, avatar);
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ mClient.exhaustResponse(get.getResponseBodyAsStream());
|
|
|
+ }
|
|
|
+ } catch (Exception e) {
|
|
|
+ e.printStackTrace();
|
|
|
+ } finally {
|
|
|
+ if (get != null) {
|
|
|
+ get.releaseConnection();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ Log_OC.d(TAG, "Server too old");
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return avatar;
|
|
|
+ }
|
|
|
+
|
|
|
+ private Bitmap handlePNG(Bitmap bitmap, int px){
|
|
|
+ Bitmap resultBitmap = Bitmap.createBitmap(px,
|
|
|
+ px,
|
|
|
+ Bitmap.Config.ARGB_8888);
|
|
|
+ Canvas c = new Canvas(resultBitmap);
|
|
|
+
|
|
|
+ c.drawColor(MainApp.getAppContext().getResources().
|
|
|
+ getColor(R.color.background_color));
|
|
|
+ c.drawBitmap(bitmap, 0, 0, null);
|
|
|
+
|
|
|
+ return resultBitmap;
|
|
|
+ }
|
|
|
+
|
|
|
+ private Bitmap doFileInBackground() {
|
|
|
+ File file = (File) mUsername;
|
|
|
+
|
|
|
+ final String imageKey = String.valueOf(file.hashCode());
|
|
|
+
|
|
|
+ // Check disk cache in background thread
|
|
|
+ Bitmap thumbnail = getBitmapFromDiskCache(imageKey);
|
|
|
+
|
|
|
+ // Not found in disk cache
|
|
|
+ if (thumbnail == null) {
|
|
|
+
|
|
|
+ int px = getAvatarDimension();
|
|
|
+
|
|
|
+ Bitmap bitmap = BitmapUtils.decodeSampledBitmapFromFile(
|
|
|
+ file.getAbsolutePath(), px, px);
|
|
|
+
|
|
|
+ if (bitmap != null) {
|
|
|
+ thumbnail = addThumbnailToCache(imageKey, bitmap, file.getPath(), px);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return thumbnail;
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ public static boolean cancelPotentialThumbnailWork(Object file, ImageView imageView) {
|
|
|
final ThumbnailGenerationTask bitmapWorkerTask = getBitmapWorkerTask(imageView);
|
|
|
|
|
|
if (bitmapWorkerTask != null) {
|
|
@@ -380,21 +565,51 @@ public class ThumbnailsCacheManager {
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
+ public static boolean cancelPotentialAvatarWork(Object file, ImageView imageView) {
|
|
|
+ final AvatarGenerationTask avatarWorkerTask = getAvatarWorkerTask(imageView);
|
|
|
+
|
|
|
+ if (avatarWorkerTask != null) {
|
|
|
+ final Object usernameData = avatarWorkerTask.mUsername;
|
|
|
+ // If usernameData is not yet set or it differs from the new data
|
|
|
+ if (usernameData == null || usernameData != file) {
|
|
|
+ // Cancel previous task
|
|
|
+ avatarWorkerTask.cancel(true);
|
|
|
+ Log_OC.v(TAG, "Cancelled generation of avatar for a reused imageView");
|
|
|
+ } 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;
|
|
|
+ if (drawable instanceof AsyncThumbnailDrawable) {
|
|
|
+ final AsyncThumbnailDrawable asyncDrawable = (AsyncThumbnailDrawable) drawable;
|
|
|
return asyncDrawable.getBitmapWorkerTask();
|
|
|
}
|
|
|
}
|
|
|
return null;
|
|
|
}
|
|
|
|
|
|
- public static class AsyncDrawable extends BitmapDrawable {
|
|
|
+ public static AvatarGenerationTask getAvatarWorkerTask(ImageView imageView) {
|
|
|
+ if (imageView != null) {
|
|
|
+ final Drawable drawable = imageView.getDrawable();
|
|
|
+ if (drawable instanceof AsyncAvatarDrawable) {
|
|
|
+ final AsyncAvatarDrawable asyncDrawable = (AsyncAvatarDrawable) drawable;
|
|
|
+ return asyncDrawable.getAvatarWorkerTask();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+
|
|
|
+ public static class AsyncThumbnailDrawable extends BitmapDrawable {
|
|
|
private final WeakReference<ThumbnailGenerationTask> bitmapWorkerTaskReference;
|
|
|
|
|
|
- public AsyncDrawable(
|
|
|
+ public AsyncThumbnailDrawable(
|
|
|
Resources res, Bitmap bitmap, ThumbnailGenerationTask bitmapWorkerTask
|
|
|
) {
|
|
|
|
|
@@ -407,4 +622,21 @@ public class ThumbnailsCacheManager {
|
|
|
return bitmapWorkerTaskReference.get();
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+ public static class AsyncAvatarDrawable extends BitmapDrawable {
|
|
|
+ private final WeakReference<AvatarGenerationTask> avatarWorkerTaskReference;
|
|
|
+
|
|
|
+ public AsyncAvatarDrawable(
|
|
|
+ Resources res, Bitmap bitmap, AvatarGenerationTask avatarWorkerTask
|
|
|
+ ) {
|
|
|
+
|
|
|
+ super(res, bitmap);
|
|
|
+ avatarWorkerTaskReference =
|
|
|
+ new WeakReference<AvatarGenerationTask>(avatarWorkerTask);
|
|
|
+ }
|
|
|
+
|
|
|
+ public AvatarGenerationTask getAvatarWorkerTask() {
|
|
|
+ return avatarWorkerTaskReference.get();
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|