Added requested changes.

This commit is contained in:
tobiasKaminsky 2014-09-01 21:12:51 +02:00
parent ba2d805197
commit db4ccec8ee
6 changed files with 132 additions and 111 deletions

View File

@ -5,6 +5,5 @@
<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>

View File

@ -1,6 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<lint>
<issue id="NewApi">
<ignore path="src/com/owncloud/android/ui/adapter/Utils.java" />
</issue>
</lint>

View File

@ -22,17 +22,18 @@ import com.owncloud.android.utils.Log_OC;
public class DiskLruImageCache {
private DiskLruCache mDiskCache;
private CompressFormat mCompressFormat = CompressFormat.JPEG;
private int mCompressQuality = 70;
private static final int APP_VERSION = 1;
private CompressFormat mCompressFormat;
private int mCompressQuality;
private static final int CACHE_VERSION = 1;
private static final int VALUE_COUNT = 1;
private static final int IO_BUFFER_SIZE = 8 * 1024;
private static final String TAG = "DiskLruImageCache";
public DiskLruImageCache( Context context,String uniqueName, int diskCacheSize,
CompressFormat compressFormat, int quality ) {
try {
final File diskCacheDir = getDiskCacheDir(context, uniqueName );
mDiskCache = DiskLruCache.open( diskCacheDir, APP_VERSION, VALUE_COUNT, diskCacheSize );
mDiskCache = DiskLruCache.open( diskCacheDir, CACHE_VERSION, VALUE_COUNT, diskCacheSize );
mCompressFormat = compressFormat;
mCompressQuality = quality;
} catch (IOException e) {
@ -44,7 +45,7 @@ public class DiskLruImageCache {
throws IOException, FileNotFoundException {
OutputStream out = null;
try {
out = new BufferedOutputStream( editor.newOutputStream( 0 ), Utils.IO_BUFFER_SIZE );
out = new BufferedOutputStream( editor.newOutputStream( 0 ), IO_BUFFER_SIZE );
return bitmap.compress( mCompressFormat, mCompressQuality, out );
} finally {
if ( out != null ) {
@ -57,11 +58,7 @@ public class DiskLruImageCache {
// 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 =
Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState()) ||
!Utils.isExternalStorageRemovable() ?
Utils.getExternalCacheDir(context).getPath() :
context.getCacheDir().getPath();
final String cachePath = context.getExternalCacheDir().getPath();
Log_OC.d("DiskCache", "create dir: " + cachePath + File.separator + uniqueName);
@ -116,7 +113,7 @@ public class DiskLruImageCache {
final InputStream in = snapshot.getInputStream( 0 );
if ( in != null ) {
final BufferedInputStream buffIn =
new BufferedInputStream( in, Utils.IO_BUFFER_SIZE );
new BufferedInputStream( in, IO_BUFFER_SIZE );
bitmap = BitmapFactory.decodeStream( buffIn );
}
} catch ( IOException e ) {

View File

@ -19,6 +19,7 @@ package com.owncloud.android.ui.adapter;
import java.io.File;
import java.io.IOException;
import java.lang.ref.WeakReference;
import java.net.URLEncoder;
import java.util.Vector;
@ -30,6 +31,8 @@ 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.os.AsyncTask;
import android.util.TypedValue;
@ -69,6 +72,7 @@ import org.apache.http.util.EntityUtils;
* instance.
*
* @author Bartek Przybylski
* @Author Tobias Kaminsky
*
*/
public class FileListListAdapter extends BaseAdapter implements ListAdapter {
@ -81,18 +85,21 @@ public class FileListListAdapter extends BaseAdapter implements ListAdapter {
private FileDataStorageManager mStorageManager;
private Account mAccount;
private ComponentsGetter mTransferServiceGetter;
private final Object mDiskCacheLock = new Object();
private DiskLruImageCache mDiskLruCache;
private boolean mDiskCacheStarting = true;
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 CompressFormat mCompressFormat = CompressFormat.JPEG;
private int mCompressQuality = 70;
private static final CompressFormat mCompressFormat = CompressFormat.JPEG;
private static final int mCompressQuality = 70;
private OwnCloudClient mClient;
private Bitmap defaultImg;
public FileListListAdapter(Context context, ComponentsGetter transferServiceGetter) {
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();
@ -101,8 +108,9 @@ public class FileListListAdapter extends BaseAdapter implements ListAdapter {
class InitDiskCacheTask extends AsyncTask<File, Void, Void> {
@Override
protected Void doInBackground(File... params) {
synchronized (mDiskCacheLock) {
mDiskLruCache = new DiskLruImageCache(mContext, "thumbnailCache", DISK_CACHE_SIZE, mCompressFormat,mCompressQuality);
synchronized (thumbnailDiskCacheLock) {
mThumbnailCache = new DiskLruImageCache(mContext, "thumbnailCache",
DISK_CACHE_SIZE, mCompressFormat, mCompressQuality);
try {
OwnCloudAccount ocAccount = new OwnCloudAccount(mAccount, mContext);
@ -122,24 +130,42 @@ public class FileListListAdapter extends BaseAdapter implements ListAdapter {
e.printStackTrace();
}
mDiskCacheStarting = false; // Finished initialization
mDiskCacheLock.notifyAll(); // Wake any waiting threads
mThumbnailCacheStarting = false; // Finished initialization
thumbnailDiskCacheLock.notifyAll(); // Wake any waiting threads
}
return null;
}
}
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();
}
}
class ThumbnailGenerationTask extends AsyncTask<OCFile, Void, Bitmap> {
private final WeakReference<ImageView> imageViewReference;
private OCFile file;
class BitmapWorkerTask extends AsyncTask<OCFile, Void, Bitmap> {
private final ImageView fileIcon;
public BitmapWorkerTask(ImageView fileIcon) {
this.fileIcon = fileIcon;
public ThumbnailGenerationTask(ImageView imageView) {
// Use a WeakReference to ensure the ImageView can be garbage collected
imageViewReference = new WeakReference<ImageView>(imageView);
}
// Decode image in background.
@Override
protected Bitmap doInBackground(OCFile... params) {
OCFile file = params[0];
file = params[0];
final String imageKey = String.valueOf(file.getRemoteId());
// Check disk cache in background thread
@ -160,64 +186,72 @@ public class FileListListAdapter extends BaseAdapter implements ListAdapter {
} else {
// Download thumbnail from server
DefaultHttpClient httpclient = new DefaultHttpClient();
try {
httpclient.getCredentialsProvider().setCredentials(
new AuthScope(mClient.getBaseUri().toString().replace("https://", ""), 443),
new UsernamePasswordCredentials(mClient.getCredentials().getUsername(), mClient.getCredentials().getAuthToken()));
// TODO change to user preview.png
//HttpGet httpget = new HttpGet(mClient.getBaseUri() + "/index.php/core/preview.png?file="+URLEncoder.encode(file.getRemotePath(), "UTF-8")+"&x=36&y=36&forceIcon=1");
HttpGet httpget = new HttpGet(mClient.getBaseUri() + "/ocs/v1.php/thumbnail?x=50&y=50&path=" + URLEncoder.encode(file.getRemotePath(), "UTF-8"));
HttpResponse response = httpclient.execute(httpget);
HttpEntity entity = response.getEntity();
if (entity != null) {
byte[] bytes = EntityUtils.toByteArray(entity);
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();
}finally {
httpclient.getConnectionManager().shutdown();
}
// Commented out as maybe changes to client library are needed
// DefaultHttpClient httpclient = new DefaultHttpClient();
// try {
// httpclient.getCredentialsProvider().setCredentials(
// new AuthScope(mClient.getBaseUri().toString().replace("https://", ""), 443),
// new UsernamePasswordCredentials(mClient.getCredentials().getUsername(), mClient.getCredentials().getAuthToken()));
//
//
// HttpGet httpget = new HttpGet(mClient.getBaseUri() + "/ocs/v1.php/thumbnail?x=50&y=50&path=" + URLEncoder.encode(file.getRemotePath(), "UTF-8"));
// HttpResponse response = httpclient.execute(httpget);
// HttpEntity entity = response.getEntity();
//
// if (entity != null) {
// byte[] bytes = EntityUtils.toByteArray(entity);
// 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();
// }finally {
// httpclient.getConnectionManager().shutdown();
// }
}
}
return thumbnail;
}
protected void onPostExecute(Bitmap bitmap){
if (bitmap != null){
fileIcon.setImageBitmap(bitmap);
if (isCancelled()) {
bitmap = null;
}
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 (mDiskCacheLock) {
if (mDiskLruCache != null && mDiskLruCache.getBitmap(key) == null) {
mDiskLruCache.put(key, bitmap);
synchronized (thumbnailDiskCacheLock) {
if (mThumbnailCache != null && mThumbnailCache.getBitmap(key) == null) {
mThumbnailCache.put(key, bitmap);
}
}
}
public Bitmap getBitmapFromDiskCache(String key) {
synchronized (mDiskCacheLock) {
synchronized (thumbnailDiskCacheLock) {
// Wait while disk cache is started from background thread
while (mDiskCacheStarting) {
while (mThumbnailCacheStarting) {
try {
mDiskCacheLock.wait();
thumbnailDiskCacheLock.wait();
} catch (InterruptedException e) {}
}
if (mDiskLruCache != null) {
return (Bitmap) mDiskLruCache.getBitmap(key);
if (mThumbnailCache != null) {
return (Bitmap) mThumbnailCache.getBitmap(key);
}
}
return null;
@ -321,20 +355,23 @@ public class FileListListAdapter extends BaseAdapter implements ListAdapter {
checkBoxV.setImageResource(android.R.drawable.checkbox_off_background);
}
checkBoxV.setVisibility(View.VISIBLE);
}
// first set thumbnail according to Mimetype, prevents empty thumbnails
fileIcon.setImageResource(DisplayUtils.getResourceId(file.getMimetype(), file.getFileName()));
}
// get Thumbnail if file is image
if (file.isImage()){
// Thumbnail in Cache?
// Thumbnail in Cache?
Bitmap thumbnail = getBitmapFromDiskCache(String.valueOf(file.getRemoteId()));
if (thumbnail != null){
fileIcon.setImageBitmap(thumbnail);
} else {
// generate new Thumbnail
new BitmapWorkerTask(fileIcon).execute(file);
if (cancelPotentialWork(file, fileIcon)) {
final ThumbnailGenerationTask task = new ThumbnailGenerationTask(fileIcon);
final AsyncDrawable asyncDrawable =
new AsyncDrawable(mContext.getResources(), defaultImg, task);
fileIcon.setImageDrawable(asyncDrawable);
task.execute(file);
}
}
}
@ -373,6 +410,35 @@ public class FileListListAdapter extends BaseAdapter implements ListAdapter {
return view;
}
public static boolean cancelPotentialWork(OCFile file, ImageView imageView) {
final ThumbnailGenerationTask bitmapWorkerTask = getBitmapWorkerTask(imageView);
if (bitmapWorkerTask != null) {
final OCFile bitmapData = bitmapWorkerTask.file;
// 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;
}
private 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;
}
@Override
public int getViewTypeCount() {

View File

@ -1,35 +0,0 @@
package com.owncloud.android.ui.adapter;
import java.io.File;
import android.content.Context;
import android.os.Build;
import android.os.Environment;
public class Utils {
public static final int IO_BUFFER_SIZE = 8 * 1024;
private Utils() {};
public static boolean isExternalStorageRemovable() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD) {
return Environment.isExternalStorageRemovable();
}
return true;
}
public static File getExternalCacheDir(Context context) {
if (hasExternalCacheDir()) {
return context.getExternalCacheDir();
}
// Before Froyo we need to construct the external cache dir ourselves
final String cacheDir = "/Android/data/" + context.getPackageName() + "/cache/";
return new File(Environment.getExternalStorageDirectory().getPath() + cacheDir);
}
public static boolean hasExternalCacheDir() {
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.FROYO;
}
}