Skip to content

Commit

Permalink
Merge pull request #746 from owncloud/thumbnailForUpload
Browse files Browse the repository at this point in the history
Thumbnails added to Upload activity
  • Loading branch information
davivel committed Jan 14, 2015
2 parents 369fb6a + 6c70154 commit 9bf4e0f
Show file tree
Hide file tree
Showing 6 changed files with 348 additions and 217 deletions.
322 changes: 189 additions & 133 deletions src/com/owncloud/android/datamodel/ThumbnailsCacheManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,8 @@
import android.graphics.Bitmap;
import android.graphics.Bitmap.CompressFormat;
import android.graphics.BitmapFactory;
import android.graphics.Matrix;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.media.ExifInterface;
import android.media.ThumbnailUtils;
import android.net.Uri;
import android.os.AsyncTask;
Expand Down Expand Up @@ -76,7 +74,7 @@ public class ThumbnailsCacheManager {
public static Bitmap mDefaultImg =
BitmapFactory.decodeResource(
MainApp.getAppContext().getResources(),
DisplayUtils.getResourceId("image/png", "default.png")
DisplayUtils.getFileTypeIconId("image/png", "default.png")
);


Expand Down Expand Up @@ -139,188 +137,246 @@ public static Bitmap getBitmapFromDiskCache(String 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<OCFile, Void, Bitmap> {
public static class ThumbnailGenerationTask extends AsyncTask<Object, Void, Bitmap> {
private final WeakReference<ImageView> mImageViewReference;
private static Account mAccount;
private OCFile mFile;
private Object mFile;
private FileDataStorageManager mStorageManager;



public ThumbnailGenerationTask(ImageView imageView, FileDataStorageManager storageManager, Account account) {
// Use a WeakReference to ensure the ImageView can be garbage collected
// 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;
}

// Decode image in background.
public ThumbnailGenerationTask(ImageView imageView) {
// Use a WeakReference to ensure the ImageView can be garbage collected
mImageViewReference = new WeakReference<ImageView>(imageView);
}

@Override
protected Bitmap doInBackground(OCFile... params) {
protected Bitmap doInBackground(Object... params) {
Bitmap thumbnail = null;

try {
if (mAccount != null) {
AccountManager accountMgr = AccountManager.get(MainApp.getAppContext());

mServerVersion = accountMgr.getUserData(mAccount, Constants.KEY_OC_VERSION);
OwnCloudAccount ocAccount = new OwnCloudAccount(mAccount, MainApp.getAppContext());
mClient = OwnCloudClientManagerFactory.getDefaultSingleton().
getClientFor(ocAccount, MainApp.getAppContext());
}

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(r.getDimension(R.dimen.file_icon_size));

if (mFile.isDown()){
Bitmap bitmap = BitmapUtils.decodeSampledBitmapFromFile(
mFile.getStoragePath(), px, px);

if (bitmap != null) {
thumbnail = ThumbnailUtils.extractThumbnail(bitmap, px, px);

// Rotate image, obeying exif tag
thumbnail = BitmapUtils.rotateImage(thumbnail, mFile.getStoragePath());

// Add thumbnail to cache
addBitmapToCache(imageKey, thumbnail);

mFile.setNeedsUpdateThumbnail(false);
mStorageManager.saveFile(mFile);
}

} else {
// Download thumbnail from server
if (mClient != null && mServerVersion != null) {
OwnCloudVersion serverOCVersion = new OwnCloudVersion(mServerVersion);
if (serverOCVersion.compareTo(new OwnCloudVersion(MINOR_SERVER_VERSION_FOR_THUMBS)) >= 0) {
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();
}
} else {
Log_OC.d(TAG, "Server too old");
}
}
}
if (mFile instanceof OCFile) {
thumbnail = doOCFileInBackground();
} else if (mFile instanceof File) {
thumbnail = doFileInBackground();
} else {
// do nothing
}

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

}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);
final ThumbnailGenerationTask bitmapWorkerTask = getBitmapWorkerTask(imageView);
if (this == bitmapWorkerTask && imageView != null) {
if (imageView.getTag().equals(mFile.getFileId())) {
String tagId = "";
if (mFile instanceof OCFile){
tagId = String.valueOf(((OCFile)mFile).getFileId());
} else if (mFile instanceof File){
tagId = String.valueOf(((File)mFile).hashCode());
}
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 getThumbnailDimension(){
// Converts dp to pixel
Resources r = MainApp.getAppContext().getResources();
return (int) Math.round(r.getDimension(R.dimen.file_icon_size));
}

private Bitmap doOCFileInBackground() {
Bitmap thumbnail = null;
OCFile file = (OCFile)mFile;

final String imageKey = String.valueOf(file.getRemoteId());

// Check disk cache in background thread
thumbnail = getBitmapFromDiskCache(imageKey);

// Not found in disk cache
if (thumbnail == null || file.needsUpdateThumbnail()) {

int px = getThumbnailDimension();

if (file.isDown()) {
Bitmap bitmap = BitmapUtils.decodeSampledBitmapFromFile(
file.getStoragePath(), px, px);

if (bitmap != null) {
thumbnail = addThumbnailToCache(imageKey, bitmap, file.getStoragePath(), px);

file.setNeedsUpdateThumbnail(false);
mStorageManager.saveFile(file);
}

} else {
// Download thumbnail from server
if (mClient != null && mServerVersion != null) {
OwnCloudVersion serverOCVersion = new OwnCloudVersion(mServerVersion);
if (serverOCVersion.compareTo(new OwnCloudVersion(MINOR_SERVER_VERSION_FOR_THUMBS)) >= 0) {
try {
int status = -1;

String uri = mClient.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 = 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();
}
} else {
Log_OC.d(TAG, "Server too old");
}
}
}
}

return thumbnail;

}

private Bitmap doFileInBackground() {
Bitmap thumbnail = null;
File file = (File)mFile;

final String imageKey = String.valueOf(file.hashCode());

// Check disk cache in background thread
thumbnail = getBitmapFromDiskCache(imageKey);

// Not found in disk cache
if (thumbnail == null) {

int px = getThumbnailDimension();

Bitmap bitmap = BitmapUtils.decodeSampledBitmapFromFile(
file.getAbsolutePath(), px, px);

if (bitmap != null) {
thumbnail = addThumbnailToCache(imageKey, bitmap, file.getPath(), px);
}
}
return thumbnail;
}

}



public static boolean cancelPotentialWork(Object file, ImageView imageView) {
final ThumbnailGenerationTask bitmapWorkerTask = getBitmapWorkerTask(imageView);

if (bitmapWorkerTask != null) {
final Object 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 AsyncDrawable extends BitmapDrawable {
private final WeakReference<ThumbnailGenerationTask> bitmapWorkerTaskReference;

public AsyncDrawable(
Resources res, Bitmap bitmap, ThumbnailGenerationTask bitmapWorkerTask
) {
) {

super(res, bitmap);
bitmapWorkerTaskReference =
new WeakReference<ThumbnailGenerationTask>(bitmapWorkerTask);
new WeakReference<ThumbnailGenerationTask>(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
}
}

}
Loading

0 comments on commit 9bf4e0f

Please sign in to comment.