mirror of
https://github.com/nextcloud/android.git
synced 2024-11-26 23:28:42 +03:00
Use ETag for avatars
This commit is contained in:
parent
c650f3a341
commit
3a1c1c904b
3 changed files with 111 additions and 97 deletions
|
@ -38,6 +38,7 @@ import android.media.ThumbnailUtils;
|
|||
import android.net.Uri;
|
||||
import android.os.AsyncTask;
|
||||
import android.provider.MediaStore;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.text.TextUtils;
|
||||
import android.view.Display;
|
||||
import android.view.MenuItem;
|
||||
|
@ -53,6 +54,7 @@ import com.owncloud.android.lib.common.OwnCloudClientManagerFactory;
|
|||
import com.owncloud.android.lib.common.operations.RemoteOperation;
|
||||
import com.owncloud.android.lib.common.utils.Log_OC;
|
||||
import com.owncloud.android.lib.resources.status.OwnCloudVersion;
|
||||
import com.owncloud.android.ui.TextDrawable;
|
||||
import com.owncloud.android.ui.adapter.DiskLruImageCache;
|
||||
import com.owncloud.android.ui.preview.PreviewImageFragment;
|
||||
import com.owncloud.android.utils.BitmapUtils;
|
||||
|
@ -84,31 +86,25 @@ public class ThumbnailsCacheManager {
|
|||
private static final String TAG = ThumbnailsCacheManager.class.getSimpleName();
|
||||
private static final String PNG_MIMETYPE = "image/png";
|
||||
private static final String CACHE_FOLDER = "thumbnailCache";
|
||||
private static final String AVATAR = "avatar";
|
||||
private static final String ETAG = "ETag";
|
||||
|
||||
private static final Object mThumbnailsDiskCacheLock = new Object();
|
||||
private static DiskLruImageCache mThumbnailCache = null;
|
||||
private static boolean mThumbnailCacheStarting = true;
|
||||
|
||||
|
||||
private static final int DISK_CACHE_SIZE = 1024 * 1024 * 200; // 200MB
|
||||
private static final CompressFormat mCompressFormat = CompressFormat.JPEG;
|
||||
private static final int mCompressQuality = 70;
|
||||
private static OwnCloudClient mClient = null;
|
||||
|
||||
public static final Bitmap mDefaultImg =
|
||||
BitmapFactory.decodeResource(
|
||||
MainApp.getAppContext().getResources(),
|
||||
R.drawable.file_image
|
||||
);
|
||||
|
||||
public static final Bitmap mDefaultVideo =
|
||||
BitmapFactory.decodeResource(
|
||||
MainApp.getAppContext().getResources(),
|
||||
R.drawable.file_movie
|
||||
);
|
||||
public static final Bitmap mDefaultImg = BitmapFactory.decodeResource(MainApp.getAppContext().getResources(),
|
||||
R.drawable.file_image);
|
||||
|
||||
public static final Bitmap mDefaultVideo = BitmapFactory.decodeResource(MainApp.getAppContext().getResources(),
|
||||
R.drawable.file_movie);
|
||||
|
||||
public static class InitDiskCacheTask extends AsyncTask<File, Void, Void> {
|
||||
|
||||
@Override
|
||||
protected Void doInBackground(File... params) {
|
||||
synchronized (mThumbnailsDiskCacheLock) {
|
||||
|
@ -759,27 +755,32 @@ public class ThumbnailsCacheManager {
|
|||
}
|
||||
}
|
||||
|
||||
public static class AvatarGenerationTask extends AsyncTask<String, Void, Bitmap> {
|
||||
public static class AvatarGenerationTask extends AsyncTask<String, Void, Drawable> {
|
||||
private final WeakReference<AvatarGenerationListener> mAvatarGenerationListener;
|
||||
private final Object mCallContext;
|
||||
private final Resources mResources;
|
||||
private final float mAvatarRadius;
|
||||
private Account mAccount;
|
||||
private String mUsername;
|
||||
|
||||
|
||||
public AvatarGenerationTask(AvatarGenerationListener avatarGenerationListener, Object callContext,
|
||||
FileDataStorageManager storageManager, Account account) {
|
||||
FileDataStorageManager storageManager, Account account, Resources resources,
|
||||
float avatarRadius) {
|
||||
mAvatarGenerationListener = new WeakReference<>(avatarGenerationListener);
|
||||
mCallContext = callContext;
|
||||
if (storageManager == null) {
|
||||
throw new IllegalArgumentException("storageManager must not be NULL");
|
||||
}
|
||||
mAccount = account;
|
||||
mResources = resources;
|
||||
mAvatarRadius = avatarRadius;
|
||||
}
|
||||
|
||||
@SuppressFBWarnings("Dm")
|
||||
@Override
|
||||
protected Bitmap doInBackground(String... params) {
|
||||
Bitmap thumbnail = null;
|
||||
protected Drawable doInBackground(String... params) {
|
||||
Drawable thumbnail = null;
|
||||
|
||||
try {
|
||||
if (mAccount != null) {
|
||||
|
@ -802,14 +803,14 @@ public class ThumbnailsCacheManager {
|
|||
return thumbnail;
|
||||
}
|
||||
|
||||
protected void onPostExecute(Bitmap bitmap) {
|
||||
if (bitmap != null) {
|
||||
protected void onPostExecute(Drawable drawable) {
|
||||
if (drawable != null) {
|
||||
AvatarGenerationListener listener = mAvatarGenerationListener.get();
|
||||
AvatarGenerationTask avatarWorkerTask = getAvatarWorkerTask(mCallContext);
|
||||
if (this == avatarWorkerTask
|
||||
&& listener.shouldCallGeneratedCallback(mUsername, mCallContext)) {
|
||||
listener.avatarGenerated(new BitmapDrawable(bitmap), mCallContext);
|
||||
}
|
||||
|
||||
if (this == avatarWorkerTask && listener.shouldCallGeneratedCallback(mUsername, mCallContext)) {
|
||||
listener.avatarGenerated(drawable, mCallContext);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -823,63 +824,91 @@ public class ThumbnailsCacheManager {
|
|||
return Math.round(r.getDimension(R.dimen.file_avatar_size));
|
||||
}
|
||||
|
||||
private Bitmap doAvatarInBackground() {
|
||||
private @Nullable
|
||||
Drawable doAvatarInBackground() {
|
||||
Bitmap avatar = null;
|
||||
String username = mUsername;
|
||||
|
||||
final String imageKey = "a_" + username;
|
||||
ArbitraryDataProvider arbitraryDataProvider = new ArbitraryDataProvider(
|
||||
MainApp.getAppContext().getContentResolver());
|
||||
|
||||
// Check disk cache in background thread
|
||||
Bitmap avatar = getBitmapFromDiskCache(imageKey);
|
||||
String eTag = arbitraryDataProvider.getValue(mAccount, AVATAR);
|
||||
|
||||
// Not found in disk cache
|
||||
if (avatar == null) {
|
||||
final String imageKey = "a_" + username + "_" + eTag;
|
||||
|
||||
int px = getAvatarDimension();
|
||||
int px = getAvatarDimension();
|
||||
|
||||
// Download avatar from server
|
||||
OwnCloudVersion serverOCVersion = AccountUtils.getServerVersion(mAccount);
|
||||
if (mClient != null && serverOCVersion != null) {
|
||||
if (serverOCVersion.supportsRemoteThumbnails()) {
|
||||
GetMethod get = null;
|
||||
try {
|
||||
// Download avatar from server
|
||||
OwnCloudVersion serverOCVersion = AccountUtils.getServerVersion(mAccount);
|
||||
if (mClient != null && serverOCVersion != null) {
|
||||
if (serverOCVersion.supportsRemoteThumbnails()) {
|
||||
GetMethod get = null;
|
||||
try {
|
||||
String userId = AccountManager.get(MainApp.getAppContext()).getUserData(mAccount,
|
||||
com.owncloud.android.lib.common.accounts.AccountUtils.Constants.KEY_USER_ID);
|
||||
|
||||
String userId = AccountManager.get(MainApp.getAppContext()).getUserData(mAccount,
|
||||
com.owncloud.android.lib.common.accounts.AccountUtils.Constants.KEY_USER_ID);
|
||||
if (TextUtils.isEmpty(userId)) {
|
||||
userId = AccountUtils.getAccountUsername(username);
|
||||
}
|
||||
|
||||
if (TextUtils.isEmpty(userId)) {
|
||||
userId = AccountUtils.getAccountUsername(username);
|
||||
}
|
||||
String uri = mClient.getBaseUri() + "/index.php/avatar/" + Uri.encode(userId) + "/" + px;
|
||||
Log_OC.d("Avatar", "URI: " + uri);
|
||||
get = new GetMethod(uri);
|
||||
|
||||
String uri = mClient.getBaseUri() + "/index.php/avatar/" + Uri.encode(userId) + "/" + px;
|
||||
Log_OC.d("Avatar", "URI: " + uri);
|
||||
get = new GetMethod(uri);
|
||||
int status = mClient.executeMethod(get);
|
||||
if (status == HttpStatus.SC_OK) {
|
||||
if (!eTag.isEmpty()) {
|
||||
get.setRequestHeader("If-None-Match", eTag);
|
||||
}
|
||||
|
||||
int status = mClient.executeMethod(get);
|
||||
|
||||
// we are using eTag to download a new avatar only if it changed
|
||||
switch (status) {
|
||||
case HttpStatus.SC_OK:
|
||||
// new avatar
|
||||
InputStream inputStream = get.getResponseBodyAsStream();
|
||||
|
||||
if (get.getResponseHeader(ETAG) != null) {
|
||||
eTag = get.getResponseHeader(ETAG).getValue().replace("\"", "");
|
||||
arbitraryDataProvider.storeOrUpdateKeyValue(mAccount.name, AVATAR, eTag);
|
||||
}
|
||||
|
||||
Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
|
||||
avatar = ThumbnailUtils.extractThumbnail(bitmap, px, px);
|
||||
|
||||
// Add avatar to cache
|
||||
if (avatar != null) {
|
||||
avatar = handlePNG(avatar, px);
|
||||
addBitmapToCache(imageKey, avatar);
|
||||
String newImageKey = "a_" + username + "_" + eTag;
|
||||
addBitmapToCache(newImageKey, avatar);
|
||||
} else {
|
||||
return TextDrawable.createAvatar(mAccount.name, mAvatarRadius);
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
|
||||
case HttpStatus.SC_NOT_MODIFIED:
|
||||
// old avatar
|
||||
avatar = getBitmapFromDiskCache(imageKey);
|
||||
mClient.exhaustResponse(get.getResponseBodyAsStream());
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Log_OC.e(TAG, "Error downloading avatar", e);
|
||||
} finally {
|
||||
if (get != null) {
|
||||
get.releaseConnection();
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
// everything else
|
||||
mClient.exhaustResponse(get.getResponseBodyAsStream());
|
||||
break;
|
||||
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Log_OC.e(TAG, "Error downloading avatar", e);
|
||||
} finally {
|
||||
if (get != null) {
|
||||
get.releaseConnection();
|
||||
}
|
||||
} else {
|
||||
Log_OC.d(TAG, "Server too old");
|
||||
}
|
||||
} else {
|
||||
Log_OC.d(TAG, "Server too old");
|
||||
}
|
||||
}
|
||||
return avatar;
|
||||
return BitmapUtils.bitmapToCircularBitmapDrawable(mResources, avatar);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1077,13 +1106,9 @@ public class ThumbnailsCacheManager {
|
|||
public static class AsyncAvatarDrawable extends BitmapDrawable {
|
||||
private final WeakReference<AvatarGenerationTask> avatarWorkerTaskReference;
|
||||
|
||||
public AsyncAvatarDrawable(
|
||||
Resources res, Bitmap bitmap, AvatarGenerationTask avatarWorkerTask
|
||||
) {
|
||||
|
||||
public AsyncAvatarDrawable(Resources res, Bitmap bitmap, AvatarGenerationTask avatarWorkerTask) {
|
||||
super(res, bitmap);
|
||||
avatarWorkerTaskReference =
|
||||
new WeakReference<AvatarGenerationTask>(avatarWorkerTask);
|
||||
avatarWorkerTaskReference = new WeakReference<>(avatarWorkerTask);
|
||||
}
|
||||
|
||||
public AvatarGenerationTask getAvatarWorkerTask() {
|
||||
|
|
|
@ -641,9 +641,11 @@ public abstract class DrawerActivity extends ToolbarActivity implements DisplayU
|
|||
|
||||
// activate second/end account avatar
|
||||
if (mAvatars[1] != null) {
|
||||
View accountEndView = findNavigationViewChildById(R.id.drawer_account_end);
|
||||
accountEndView.setTag(mAvatars[1].name);
|
||||
|
||||
DisplayUtils.setAvatar(mAvatars[1], this,
|
||||
mOtherAccountAvatarRadiusDimension, getResources(), getStorageManager(),
|
||||
findNavigationViewChildById(R.id.drawer_account_end));
|
||||
mOtherAccountAvatarRadiusDimension, getResources(), getStorageManager(), accountEndView);
|
||||
mAccountEndAccountAvatar.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
mAccountEndAccountAvatar.setVisibility(View.GONE);
|
||||
|
@ -651,9 +653,11 @@ public abstract class DrawerActivity extends ToolbarActivity implements DisplayU
|
|||
|
||||
// activate third/middle account avatar
|
||||
if (mAvatars[2] != null) {
|
||||
View accountMiddleView = findNavigationViewChildById(R.id.drawer_account_middle);
|
||||
accountMiddleView.setTag(mAvatars[2].name);
|
||||
|
||||
DisplayUtils.setAvatar(mAvatars[2], this,
|
||||
mOtherAccountAvatarRadiusDimension, getResources(), getStorageManager(),
|
||||
findNavigationViewChildById(R.id.drawer_account_middle));
|
||||
mOtherAccountAvatarRadiusDimension, getResources(), getStorageManager(), accountMiddleView);
|
||||
mAccountMiddleAccountAvatar.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
mAccountMiddleAccountAvatar.setVisibility(View.GONE);
|
||||
|
@ -749,9 +753,11 @@ public abstract class DrawerActivity extends ToolbarActivity implements DisplayU
|
|||
username.setText(AccountUtils.getAccountUsername(account.name));
|
||||
}
|
||||
|
||||
View currentAccountView = findNavigationViewChildById(R.id.drawer_current_account);
|
||||
currentAccountView.setTag(account.name);
|
||||
|
||||
DisplayUtils.setAvatar(account, this,
|
||||
mCurrentAccountAvatarRadiusDimension, getResources(), getStorageManager(),
|
||||
findNavigationViewChildById(R.id.drawer_current_account));
|
||||
mCurrentAccountAvatarRadiusDimension, getResources(), getStorageManager(), currentAccountView);
|
||||
|
||||
// check and show quota info if available
|
||||
getAndDisplayUserQuota();
|
||||
|
|
|
@ -66,7 +66,6 @@ import com.owncloud.android.datamodel.ThumbnailsCacheManager;
|
|||
import com.owncloud.android.lib.common.OwnCloudAccount;
|
||||
import com.owncloud.android.lib.common.utils.Log_OC;
|
||||
import com.owncloud.android.lib.resources.files.SearchOperation;
|
||||
import com.owncloud.android.ui.TextDrawable;
|
||||
import com.owncloud.android.ui.activity.FileDisplayActivity;
|
||||
import com.owncloud.android.ui.events.MenuItemClickEvent;
|
||||
import com.owncloud.android.ui.events.SearchEvent;
|
||||
|
@ -433,33 +432,17 @@ public class DisplayUtils {
|
|||
((View) callContext).setContentDescription(account.name);
|
||||
}
|
||||
|
||||
// Thumbnail in Cache?
|
||||
Bitmap thumbnail = ThumbnailsCacheManager.getBitmapFromDiskCache("a_" + account.name);
|
||||
Bitmap thumbnail = null;
|
||||
|
||||
if (thumbnail != null) {
|
||||
listener.avatarGenerated(
|
||||
BitmapUtils.bitmapToCircularBitmapDrawable(MainApp.getAppContext().getResources(), thumbnail),
|
||||
callContext);
|
||||
} else {
|
||||
// generate new avatar
|
||||
if (ThumbnailsCacheManager.cancelPotentialAvatarWork(account.name, callContext)) {
|
||||
final ThumbnailsCacheManager.AvatarGenerationTask task =
|
||||
new ThumbnailsCacheManager.AvatarGenerationTask(listener, callContext, storageManager, account);
|
||||
if (thumbnail == null) {
|
||||
try {
|
||||
listener.avatarGenerated(TextDrawable.createAvatar(account.name, avatarRadius), callContext);
|
||||
} catch (Exception e) {
|
||||
Log_OC.e(TAG, "Error calculating RGB value for active account icon.", e);
|
||||
listener.avatarGenerated(resources.getDrawable(R.drawable.ic_account_circle), callContext);
|
||||
}
|
||||
} else {
|
||||
final ThumbnailsCacheManager.AsyncAvatarDrawable asyncDrawable =
|
||||
new ThumbnailsCacheManager.AsyncAvatarDrawable(resources, thumbnail, task);
|
||||
listener.avatarGenerated(BitmapUtils.bitmapToCircularBitmapDrawable(
|
||||
resources, asyncDrawable.getBitmap()), callContext);
|
||||
}
|
||||
task.execute(account.name);
|
||||
}
|
||||
if (ThumbnailsCacheManager.cancelPotentialAvatarWork(account.name, callContext)) {
|
||||
final ThumbnailsCacheManager.AvatarGenerationTask task =
|
||||
new ThumbnailsCacheManager.AvatarGenerationTask(listener, callContext, storageManager,
|
||||
account, resources, avatarRadius);
|
||||
|
||||
final ThumbnailsCacheManager.AsyncAvatarDrawable asyncDrawable =
|
||||
new ThumbnailsCacheManager.AsyncAvatarDrawable(resources, thumbnail, task);
|
||||
listener.avatarGenerated(asyncDrawable, callContext);
|
||||
task.execute(account.name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue