浏览代码

wip

Conflicts:
	res/layout/drawer.xml
	src/com/owncloud/android/ui/activity/FileActivity.java
	src/com/owncloud/android/ui/activity/FileDisplayActivity.java
tobiasKaminsky 9 年之前
父节点
当前提交
8dbb5b6305

+ 1 - 0
res/values/dims.xml

@@ -28,6 +28,7 @@
 
     <dimen name="file_icon_size">32dp</dimen>
     <dimen name="file_icon_size_grid">128dp</dimen>
+    <dimen name="file_avatar_size">128dp</dimen>
     <dimen name="standard_padding">16dp</dimen>
     <dimen name="standard_half_padding">8dp</dimen>
     <dimen name="standard_margin">16dp</dimen>

+ 246 - 14
src/com/owncloud/android/datamodel/ThumbnailsCacheManager.java

@@ -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();
+        }
+    }
 }

+ 1 - 0
src/com/owncloud/android/services/OperationsService.java

@@ -107,6 +107,7 @@ public class OperationsService extends Service {
     public static final String ACTION_GET_SERVER_INFO = "GET_SERVER_INFO";
     public static final String ACTION_OAUTH2_GET_ACCESS_TOKEN = "OAUTH2_GET_ACCESS_TOKEN";
     public static final String ACTION_GET_USER_NAME = "GET_USER_NAME";
+    public static final String ACTION_GET_USER_AVATAR = "GET_USER_AVATAR";
     public static final String ACTION_RENAME = "RENAME";
     public static final String ACTION_REMOVE = "REMOVE";
     public static final String ACTION_CREATE_FOLDER = "CREATE_FOLDER";

+ 3 - 3
src/com/owncloud/android/ui/adapter/FileListListAdapter.java

@@ -311,7 +311,7 @@ public class FileListListAdapter extends BaseAdapter implements ListAdapter {
                         fileIcon.setImageBitmap(thumbnail);
                     } else {
                         // generate new Thumbnail
-                        if (ThumbnailsCacheManager.cancelPotentialWork(file, fileIcon)) {
+                        if (ThumbnailsCacheManager.cancelPotentialThumbnailWork(file, fileIcon)) {
                             final ThumbnailsCacheManager.ThumbnailGenerationTask task =
                                     new ThumbnailsCacheManager.ThumbnailGenerationTask(
                                             fileIcon, mStorageManager, mAccount
@@ -319,8 +319,8 @@ public class FileListListAdapter extends BaseAdapter implements ListAdapter {
                             if (thumbnail == null) {
                                 thumbnail = ThumbnailsCacheManager.mDefaultImg;
                             }
-                            final ThumbnailsCacheManager.AsyncDrawable asyncDrawable =
-                                    new ThumbnailsCacheManager.AsyncDrawable(
+                            final ThumbnailsCacheManager.AsyncThumbnailDrawable asyncDrawable =
+                                    new ThumbnailsCacheManager.AsyncThumbnailDrawable(
                                     mContext.getResources(), 
                                     thumbnail, 
                                     task

+ 8 - 8
src/com/owncloud/android/ui/adapter/LocalFileListAdapter.java

@@ -20,10 +20,6 @@
  */
 package com.owncloud.android.ui.adapter;
 
-import java.io.File;
-import java.util.Arrays;
-import java.util.Comparator;
-
 import android.content.Context;
 import android.graphics.Bitmap;
 import android.view.LayoutInflater;
@@ -42,6 +38,10 @@ import com.owncloud.android.utils.BitmapUtils;
 import com.owncloud.android.utils.DisplayUtils;
 import com.owncloud.android.utils.MimetypeIconUtil;
 
+import java.io.File;
+import java.util.Arrays;
+import java.util.Comparator;
+
 /**
  * This Adapter populates a ListView with all files and directories contained
  * in a local directory
@@ -109,9 +109,9 @@ public class LocalFileListAdapter extends BaseAdapter implements ListAdapter {
             ImageView fileIcon = (ImageView) view.findViewById(R.id.thumbnail);
 
             /** Cancellation needs do be checked and done before changing the drawable in fileIcon, or
-             * {@link ThumbnailsCacheManager#cancelPotentialWork} will NEVER cancel any task.
+             * {@link ThumbnailsCacheManager#cancelPotentialThumbnailWork} will NEVER cancel any task.
              **/
-            boolean allowedToCreateNewThumbnail = (ThumbnailsCacheManager.cancelPotentialWork(file, fileIcon));
+            boolean allowedToCreateNewThumbnail = (ThumbnailsCacheManager.cancelPotentialThumbnailWork(file, fileIcon));
 
             if (!file.isDirectory()) {
                 fileIcon.setImageResource(R.drawable.file);
@@ -161,8 +161,8 @@ public class LocalFileListAdapter extends BaseAdapter implements ListAdapter {
                             if (thumbnail == null) {
                                 thumbnail = ThumbnailsCacheManager.mDefaultImg;
                             }
-                            final ThumbnailsCacheManager.AsyncDrawable asyncDrawable =
-                        		new ThumbnailsCacheManager.AsyncDrawable(
+                            final ThumbnailsCacheManager.AsyncThumbnailDrawable asyncDrawable =
+                        		new ThumbnailsCacheManager.AsyncThumbnailDrawable(
                                     mContext.getResources(), 
                                     thumbnail, 
                                     task

+ 3 - 3
src/com/owncloud/android/ui/fragment/FileDetailFragment.java

@@ -434,7 +434,7 @@ public class FileDetailFragment extends FileFragment implements OnClickListener
                     iv.setImageBitmap(thumbnail);
                 } else {
                     // generate new Thumbnail
-                    if (ThumbnailsCacheManager.cancelPotentialWork(file, iv)) {
+                    if (ThumbnailsCacheManager.cancelPotentialThumbnailWork(file, iv)) {
                         final ThumbnailsCacheManager.ThumbnailGenerationTask task =
                                 new ThumbnailsCacheManager.ThumbnailGenerationTask(
                                         iv, mContainerActivity.getStorageManager(), mAccount
@@ -442,8 +442,8 @@ public class FileDetailFragment extends FileFragment implements OnClickListener
                         if (thumbnail == null) {
                             thumbnail = ThumbnailsCacheManager.mDefaultImg;
                         }
-                        final ThumbnailsCacheManager.AsyncDrawable asyncDrawable =
-                                new ThumbnailsCacheManager.AsyncDrawable(
+                        final ThumbnailsCacheManager.AsyncThumbnailDrawable asyncDrawable =
+                                new ThumbnailsCacheManager.AsyncThumbnailDrawable(
                                         MainApp.getAppContext().getResources(),
                                         thumbnail,
                                         task