Thumbnail
authortobiasKaminsky <tobias@kaminsky.me>
Sat, 9 Aug 2014 08:19:50 +0000 (10:19 +0200)
committertobiasKaminsky <tobias@kaminsky.me>
Sat, 9 Aug 2014 08:19:50 +0000 (10:19 +0200)
.classpath
lint.xml
src/com/owncloud/android/ui/adapter/FileListListAdapter.java

index 7bc01d9..fa15a28 100644 (file)
@@ -1,9 +1,10 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <classpath>
 <?xml version="1.0" encoding="UTF-8"?>
 <classpath>
-       <classpathentry kind="src" path="src"/>
-       <classpathentry kind="src" path="gen"/>
        <classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>
        <classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.LIBRARIES"/>
        <classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.DEPENDENCIES"/>
        <classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>
        <classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.LIBRARIES"/>
        <classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.DEPENDENCIES"/>
+       <classpathentry kind="src" path="src"/>
+       <classpathentry kind="src" path="gen"/>
+       <classpathentry exported="true" kind="lib" path="third_party/disklrucache-2.0.2.jar"/>
        <classpathentry kind="output" path="bin/classes"/>
 </classpath>
        <classpathentry kind="output" path="bin/classes"/>
 </classpath>
index ee0eead..ce54dad 100644 (file)
--- a/lint.xml
+++ b/lint.xml
@@ -1,3 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <lint>
 <?xml version="1.0" encoding="UTF-8"?>
 <lint>
+    <issue id="NewApi">
+        <ignore path="src/com/owncloud/android/ui/adapter/Utils.java" />
+    </issue>
 </lint>
\ No newline at end of file
 </lint>
\ No newline at end of file
index 4a30be6..88e64b1 100644 (file)
  */\r
 package com.owncloud.android.ui.adapter;\r
 \r
  */\r
 package com.owncloud.android.ui.adapter;\r
 \r
+import java.io.File;\r
+import java.io.IOException;\r
+import java.net.URLEncoder;\r
 import java.util.Vector;\r
 \r
 import android.accounts.Account;\r
 import java.util.Vector;\r
 \r
 import android.accounts.Account;\r
+import android.accounts.AuthenticatorException;\r
+import android.accounts.OperationCanceledException;\r
 import android.content.Context;\r
 import android.content.Context;\r
+import android.content.res.Resources;\r
+import android.graphics.Bitmap;\r
+import android.graphics.Bitmap.CompressFormat;\r
+import android.graphics.BitmapFactory;\r
+import android.media.ThumbnailUtils;\r
+import android.os.AsyncTask;\r
+import android.util.TypedValue;\r
 import android.view.LayoutInflater;\r
 import android.view.View;\r
 import android.view.ViewGroup;\r
 import android.view.LayoutInflater;\r
 import android.view.View;\r
 import android.view.ViewGroup;\r
@@ -36,9 +48,21 @@ import com.owncloud.android.datamodel.FileDataStorageManager;
 import com.owncloud.android.datamodel.OCFile;\r
 import com.owncloud.android.files.services.FileDownloader.FileDownloaderBinder;\r
 import com.owncloud.android.files.services.FileUploader.FileUploaderBinder;\r
 import com.owncloud.android.datamodel.OCFile;\r
 import com.owncloud.android.files.services.FileDownloader.FileDownloaderBinder;\r
 import com.owncloud.android.files.services.FileUploader.FileUploaderBinder;\r
+import com.owncloud.android.lib.common.OwnCloudAccount;\r
+import com.owncloud.android.lib.common.OwnCloudClient;\r
+import com.owncloud.android.lib.common.OwnCloudClientManagerFactory;\r
+import com.owncloud.android.lib.common.accounts.AccountUtils.AccountNotFoundException;\r
 import com.owncloud.android.ui.activity.ComponentsGetter;\r
 import com.owncloud.android.utils.DisplayUtils;\r
 \r
 import com.owncloud.android.ui.activity.ComponentsGetter;\r
 import com.owncloud.android.utils.DisplayUtils;\r
 \r
+import org.apache.http.HttpEntity;\r
+import org.apache.http.HttpResponse;\r
+import org.apache.http.auth.AuthScope;\r
+import org.apache.http.auth.UsernamePasswordCredentials;\r
+import org.apache.http.client.methods.HttpGet;\r
+import org.apache.http.impl.client.DefaultHttpClient;\r
+import org.apache.http.util.EntityUtils;\r
+\r
 \r
 /**\r
  * This Adapter populates a ListView with all files and folders in an ownCloud\r
 \r
 /**\r
  * This Adapter populates a ListView with all files and folders in an ownCloud\r
@@ -57,11 +81,144 @@ public class FileListListAdapter extends BaseAdapter implements ListAdapter {
     private FileDataStorageManager mStorageManager;
     private Account mAccount;
     private ComponentsGetter mTransferServiceGetter;\r
     private FileDataStorageManager mStorageManager;
     private Account mAccount;
     private ComponentsGetter mTransferServiceGetter;\r
-    \r
+    private final Object mDiskCacheLock = new Object();\r
+    private DiskLruImageCache mDiskLruCache;\r
+    private boolean mDiskCacheStarting = true;\r
+    private static final int DISK_CACHE_SIZE = 1024 * 1024 * 10; // 10MB\r
+    private CompressFormat mCompressFormat = CompressFormat.JPEG;\r
+    private int mCompressQuality = 70;\r
+    private OwnCloudClient mClient;\r
+        \r
     public FileListListAdapter(Context context, ComponentsGetter transferServiceGetter) {\r
         mContext = context;\r
         mAccount = AccountUtils.getCurrentOwnCloudAccount(mContext);\r
         mTransferServiceGetter = transferServiceGetter;\r
     public FileListListAdapter(Context context, ComponentsGetter transferServiceGetter) {\r
         mContext = context;\r
         mAccount = AccountUtils.getCurrentOwnCloudAccount(mContext);\r
         mTransferServiceGetter = transferServiceGetter;\r
+        \r
+        // Initialise disk cache on background thread\r
+        new InitDiskCacheTask().execute();\r
+    }\r
+    \r
+    class InitDiskCacheTask extends AsyncTask<File, Void, Void> {\r
+        @Override\r
+        protected Void doInBackground(File... params) {\r
+            synchronized (mDiskCacheLock) {\r
+                mDiskLruCache = new DiskLruImageCache(mContext, "thumbnailCache", DISK_CACHE_SIZE, mCompressFormat,mCompressQuality);\r
+                \r
+                try {\r
+                    OwnCloudAccount ocAccount = new OwnCloudAccount(mAccount, mContext);\r
+                    mClient = OwnCloudClientManagerFactory.getDefaultSingleton().\r
+                            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
+                mDiskCacheStarting = false; // Finished initialization\r
+                mDiskCacheLock.notifyAll(); // Wake any waiting threads\r
+            }\r
+            return null;\r
+        }\r
+    }\r
+\r
+    class BitmapWorkerTask extends AsyncTask<OCFile, Void, Bitmap> {\r
+        private final ImageView fileIcon;\r
+        \r
+        public BitmapWorkerTask(ImageView fileIcon) {\r
+            this.fileIcon = fileIcon;\r
+        }\r
+\r
+        // Decode image in background.\r
+        @Override\r
+        protected Bitmap doInBackground(OCFile... params) {\r
+            OCFile file = params[0];\r
+            final String imageKey = String.valueOf(file.getRemoteId());\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 = (int) Math.round(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 150, r.getDisplayMetrics()));\r
+                \r
+                if (file.isDown()){\r
+                    Bitmap bitmap = BitmapFactory.decodeFile(file.getStoragePath());\r
+                    thumbnail = ThumbnailUtils.extractThumbnail(bitmap, px, px);\r
+                    \r
+                    // Add thumbnail to cache\r
+                    addBitmapToCache(imageKey, thumbnail);\r
+\r
+                } else {\r
+                    // Download thumbnail from server\r
+                    DefaultHttpClient httpclient = new DefaultHttpClient();\r
+                    try {\r
+                        httpclient.getCredentialsProvider().setCredentials(\r
+                                new AuthScope(mClient.getBaseUri().toString().replace("https://", ""), 443), \r
+                                new UsernamePasswordCredentials(mClient.getCredentials().getUsername(), mClient.getCredentials().getAuthToken()));\r
+                        \r
+\r
+                        // TODO change to user preview.png\r
+                        HttpGet httpget = new HttpGet(mClient.getBaseUri() + "/ocs/v1.php/thumbnail?path=" + URLEncoder.encode(file.getRemotePath(), "UTF-8"));\r
+                        HttpResponse response = httpclient.execute(httpget);\r
+                        HttpEntity entity = response.getEntity();\r
+                        \r
+                        if (entity != null) {\r
+                            byte[] bytes = EntityUtils.toByteArray(entity);\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
+                        }\r
+                    } catch(Exception e){\r
+                        e.printStackTrace();\r
+                    }finally {\r
+                        httpclient.getConnectionManager().shutdown();\r
+                    }\r
+                } \r
+            }\r
+            return thumbnail;\r
+        }\r
+        \r
+        protected void onPostExecute(Bitmap bitmap){\r
+            fileIcon.setImageBitmap(bitmap);\r
+        }\r
+    }\r
+  \r
+    public void addBitmapToCache(String key, Bitmap bitmap) {\r
+        synchronized (mDiskCacheLock) {\r
+            if (mDiskLruCache != null && mDiskLruCache.getBitmap(key) == null) {\r
+                mDiskLruCache.put(key, bitmap);\r
+            }\r
+        }\r
+    }\r
+\r
+    public Bitmap getBitmapFromDiskCache(String key) {\r
+        synchronized (mDiskCacheLock) {\r
+            // Wait while disk cache is started from background thread\r
+            while (mDiskCacheStarting) {\r
+                try {\r
+                    mDiskCacheLock.wait();\r
+                } catch (InterruptedException e) {}\r
+            }\r
+            if (mDiskLruCache != null) {\r
+                return (Bitmap) mDiskLruCache.getBitmap(key);\r
+            }\r
+        }\r
+        return null;\r
     }
 \r
     @Override\r
     }
 \r
     @Override\r
@@ -163,15 +320,27 @@ public class FileListListAdapter extends BaseAdapter implements ListAdapter {
                     }\r
                     checkBoxV.setVisibility(View.VISIBLE);\r
                 }\r
                     }\r
                     checkBoxV.setVisibility(View.VISIBLE);\r
                 }\r
-\r
+                \r
+                // first set thumbnail according to Mimetype, prevents empty thumbnails\r
                 fileIcon.setImageResource(DisplayUtils.getResourceId(file.getMimetype(), file.getFileName()));\r
                 fileIcon.setImageResource(DisplayUtils.getResourceId(file.getMimetype(), file.getFileName()));\r
-\r
+                \r
+                // get Thumbnail if file is image\r
+                if (file.isImage()){\r
+                    // Thumbnail in Cache?\r
+                    Bitmap thumbnail = getBitmapFromDiskCache(String.valueOf(file.getRemoteId()));\r
+                    if (thumbnail != null){\r
+                        fileIcon.setImageBitmap(thumbnail);\r
+                    } else {\r
+                        // generate new Thumbnail\r
+                        new BitmapWorkerTask(fileIcon).execute(file);\r
+                    }\r
+                }\r
+                \r
                 if (checkIfFileIsSharedWithMe(file)) {\r
                     sharedWithMeIconV.setVisibility(View.VISIBLE);\r
                 }\r
             } \r
             else {\r
                 if (checkIfFileIsSharedWithMe(file)) {\r
                     sharedWithMeIconV.setVisibility(View.VISIBLE);\r
                 }\r
             } \r
             else {\r
-                \r
                 fileSizeV.setVisibility(View.INVISIBLE);\r
                 //fileSizeV.setText(DisplayUtils.bytesToHumanReadable(file.getFileLength()));\r
                 lastModV.setVisibility(View.VISIBLE);\r
                 fileSizeV.setVisibility(View.INVISIBLE);\r
                 //fileSizeV.setText(DisplayUtils.bytesToHumanReadable(file.getFileLength()));\r
                 lastModV.setVisibility(View.VISIBLE);\r