Load all contact pictures by Glide, and fix the wrong getPhotoUri method
This commit is contained in:
parent
76a948e811
commit
2cd31048ac
3 changed files with 142 additions and 244 deletions
|
@ -20,7 +20,6 @@ import android.widget.Filterable;
|
||||||
import android.widget.ImageView;
|
import android.widget.ImageView;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
import com.bumptech.glide.Glide;
|
|
||||||
import com.fsck.k9.R;
|
import com.fsck.k9.R;
|
||||||
import com.fsck.k9.helper.ContactPicture;
|
import com.fsck.k9.helper.ContactPicture;
|
||||||
import com.fsck.k9.view.RecipientSelectView.Recipient;
|
import com.fsck.k9.view.RecipientSelectView.Recipient;
|
||||||
|
@ -126,16 +125,7 @@ public class RecipientAdapter extends BaseAdapter implements Filterable {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void setContactPhotoOrPlaceholder(Context context, ImageView imageView, Recipient recipient) {
|
public static void setContactPhotoOrPlaceholder(Context context, ImageView imageView, Recipient recipient) {
|
||||||
// TODO don't use two different mechanisms for loading!
|
ContactPicture.getContactPictureLoader(context).loadContactPicture(recipient, imageView);
|
||||||
if (recipient.photoThumbnailUri != null) {
|
|
||||||
Glide.with(context).load(recipient.photoThumbnailUri)
|
|
||||||
// for some reason, this fixes loading issues.
|
|
||||||
.placeholder(null)
|
|
||||||
.dontAnimate()
|
|
||||||
.into(imageView);
|
|
||||||
} else {
|
|
||||||
ContactPicture.getContactPictureLoader(context).loadContactPicture(recipient.address, imageView);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -1,34 +1,43 @@
|
||||||
package com.fsck.k9.activity.misc;
|
package com.fsck.k9.activity.misc;
|
||||||
|
|
||||||
import java.io.FileNotFoundException;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
|
||||||
import java.lang.ref.WeakReference;
|
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.concurrent.RejectedExecutionException;
|
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
import android.app.ActivityManager;
|
|
||||||
import android.content.ContentResolver;
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.res.Resources;
|
import android.content.res.Resources;
|
||||||
import android.graphics.Bitmap;
|
import android.graphics.Bitmap;
|
||||||
import android.graphics.BitmapFactory;
|
|
||||||
import android.graphics.Canvas;
|
import android.graphics.Canvas;
|
||||||
import android.graphics.Paint;
|
import android.graphics.Paint;
|
||||||
|
import android.graphics.Paint.Style;
|
||||||
import android.graphics.Rect;
|
import android.graphics.Rect;
|
||||||
import android.graphics.drawable.BitmapDrawable;
|
|
||||||
import android.graphics.drawable.Drawable;
|
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.AsyncTask;
|
|
||||||
import android.support.annotation.VisibleForTesting;
|
import android.support.annotation.VisibleForTesting;
|
||||||
import android.support.v4.util.LruCache;
|
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.widget.ImageView;
|
import android.widget.ImageView;
|
||||||
|
|
||||||
|
import com.bumptech.glide.Glide;
|
||||||
|
import com.bumptech.glide.Priority;
|
||||||
|
import com.bumptech.glide.load.ResourceDecoder;
|
||||||
|
import com.bumptech.glide.load.data.DataFetcher;
|
||||||
|
import com.bumptech.glide.load.engine.DiskCacheStrategy;
|
||||||
|
import com.bumptech.glide.load.engine.Resource;
|
||||||
|
import com.bumptech.glide.load.engine.bitmap_recycle.BitmapPool;
|
||||||
|
import com.bumptech.glide.load.model.ModelLoader;
|
||||||
|
import com.bumptech.glide.load.resource.bitmap.BitmapEncoder;
|
||||||
|
import com.bumptech.glide.load.resource.bitmap.BitmapResource;
|
||||||
|
import com.bumptech.glide.load.resource.bitmap.StreamBitmapDecoder;
|
||||||
|
import com.bumptech.glide.load.resource.drawable.GlideDrawable;
|
||||||
|
import com.bumptech.glide.load.resource.file.FileToStreamDecoder;
|
||||||
|
import com.bumptech.glide.load.resource.transcode.BitmapToGlideDrawableTranscoder;
|
||||||
|
import com.bumptech.glide.request.RequestListener;
|
||||||
|
import com.bumptech.glide.request.target.Target;
|
||||||
import com.fsck.k9.helper.Contacts;
|
import com.fsck.k9.helper.Contacts;
|
||||||
import com.fsck.k9.mail.Address;
|
import com.fsck.k9.mail.Address;
|
||||||
|
import com.fsck.k9.view.RecipientSelectView.Recipient;
|
||||||
|
|
||||||
|
|
||||||
public class ContactPictureLoader {
|
public class ContactPictureLoader {
|
||||||
/**
|
/**
|
||||||
|
@ -47,18 +56,12 @@ public class ContactPictureLoader {
|
||||||
private static final String FALLBACK_CONTACT_LETTER = "?";
|
private static final String FALLBACK_CONTACT_LETTER = "?";
|
||||||
|
|
||||||
|
|
||||||
private ContentResolver mContentResolver;
|
|
||||||
private Resources mResources;
|
private Resources mResources;
|
||||||
private Contacts mContactsHelper;
|
private Contacts mContactsHelper;
|
||||||
private int mPictureSizeInPx;
|
private int mPictureSizeInPx;
|
||||||
|
|
||||||
private int mDefaultBackgroundColor;
|
private int mDefaultBackgroundColor;
|
||||||
|
|
||||||
/**
|
|
||||||
* LRU cache of contact pictures.
|
|
||||||
*/
|
|
||||||
private final LruCache<Address, Bitmap> mBitmapCache;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see <a href="http://developer.android.com/design/style/color.html">Color palette used</a>
|
* @see <a href="http://developer.android.com/design/style/color.html">Color palette used</a>
|
||||||
*/
|
*/
|
||||||
|
@ -80,7 +83,6 @@ public class ContactPictureLoader {
|
||||||
String letter = null;
|
String letter = null;
|
||||||
String personal = address.getPersonal();
|
String personal = address.getPersonal();
|
||||||
String str = (personal != null) ? personal : address.getAddress();
|
String str = (personal != null) ? personal : address.getAddress();
|
||||||
|
|
||||||
Matcher m = EXTRACT_LETTER_PATTERN.matcher(str);
|
Matcher m = EXTRACT_LETTER_PATTERN.matcher(str);
|
||||||
if (m.find()) {
|
if (m.find()) {
|
||||||
letter = m.group(0).toUpperCase(Locale.US);
|
letter = m.group(0).toUpperCase(Locale.US);
|
||||||
|
@ -101,7 +103,6 @@ public class ContactPictureLoader {
|
||||||
*/
|
*/
|
||||||
public ContactPictureLoader(Context context, int defaultBackgroundColor) {
|
public ContactPictureLoader(Context context, int defaultBackgroundColor) {
|
||||||
Context appContext = context.getApplicationContext();
|
Context appContext = context.getApplicationContext();
|
||||||
mContentResolver = appContext.getContentResolver();
|
|
||||||
mResources = appContext.getResources();
|
mResources = appContext.getResources();
|
||||||
mContactsHelper = Contacts.getInstance(appContext);
|
mContactsHelper = Contacts.getInstance(appContext);
|
||||||
|
|
||||||
|
@ -110,59 +111,64 @@ public class ContactPictureLoader {
|
||||||
|
|
||||||
mDefaultBackgroundColor = defaultBackgroundColor;
|
mDefaultBackgroundColor = defaultBackgroundColor;
|
||||||
|
|
||||||
ActivityManager activityManager =
|
}
|
||||||
(ActivityManager) appContext.getSystemService(Context.ACTIVITY_SERVICE);
|
|
||||||
int memClass = activityManager.getMemoryClass();
|
|
||||||
|
|
||||||
// Use 1/16th of the available memory for this memory cache.
|
public void loadContactPicture(final Address address, final ImageView imageView) {
|
||||||
final int cacheSize = 1024 * 1024 * memClass / 16;
|
Uri photoUri = mContactsHelper.getPhotoUri(address.getAddress());
|
||||||
|
loadContactPicture(photoUri, address, imageView);
|
||||||
|
}
|
||||||
|
|
||||||
mBitmapCache = new LruCache<Address, Bitmap>(cacheSize) {
|
public void loadContactPicture(Recipient recipient, ImageView imageView) {
|
||||||
|
loadContactPicture(recipient.photoThumbnailUri, recipient.address, imageView);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void loadFallbackPicture(Address address, ImageView imageView) {
|
||||||
|
Context context = imageView.getContext();
|
||||||
|
|
||||||
|
Glide.with(context)
|
||||||
|
.using(new FallbackGlideModelLoader(), FallbackGlideParams.class)
|
||||||
|
.from(FallbackGlideParams.class)
|
||||||
|
.as(Bitmap.class)
|
||||||
|
.transcode(new BitmapToGlideDrawableTranscoder(context), GlideDrawable.class)
|
||||||
|
.decoder(new FallbackGlideBitmapDecoder(context))
|
||||||
|
.encoder(new BitmapEncoder(Bitmap.CompressFormat.PNG, 0))
|
||||||
|
.cacheDecoder(new FileToStreamDecoder<>(new StreamBitmapDecoder(context)))
|
||||||
|
.diskCacheStrategy(DiskCacheStrategy.NONE)
|
||||||
|
.load(new FallbackGlideParams(address))
|
||||||
|
// for some reason, following 2 lines fix loading issues.
|
||||||
|
.dontAnimate()
|
||||||
|
.override(mPictureSizeInPx, mPictureSizeInPx)
|
||||||
|
.into(imageView);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void loadContactPicture(Uri photoUri, final Address address, final ImageView imageView) {
|
||||||
|
if (photoUri != null) {
|
||||||
|
RequestListener<Uri, GlideDrawable> noPhotoListener = new RequestListener<Uri, GlideDrawable>() {
|
||||||
@Override
|
@Override
|
||||||
protected int sizeOf(Address key, Bitmap bitmap) {
|
public boolean onException(Exception e, Uri model, Target<GlideDrawable> target,
|
||||||
// The cache size will be measured in bytes rather than number of items.
|
boolean isFirstResource) {
|
||||||
return bitmap.getByteCount();
|
loadFallbackPicture(address, imageView);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onResourceReady(GlideDrawable resource, Uri model,
|
||||||
|
Target<GlideDrawable> target,
|
||||||
|
boolean isFromMemoryCache, boolean isFirstResource) {
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
Glide.with(imageView.getContext())
|
||||||
* Load a contact picture and display it using the supplied {@link ImageView} instance.
|
.load(photoUri)
|
||||||
*
|
.diskCacheStrategy(DiskCacheStrategy.NONE)
|
||||||
* <p>
|
.listener(noPhotoListener)
|
||||||
* If a picture is found in the cache, it is displayed in the {@code ContactBadge}
|
// for some reason, following 2 lines fix loading issues.
|
||||||
* immediately. Otherwise a {@link ContactPictureRetrievalTask} is started to try to load the
|
.dontAnimate()
|
||||||
* contact picture in a background thread. Depending on the result the contact picture or a
|
.override(mPictureSizeInPx, mPictureSizeInPx)
|
||||||
* fallback picture is then stored in the bitmap cache.
|
.into(imageView);
|
||||||
* </p>
|
} else {
|
||||||
*
|
loadFallbackPicture(address, imageView);
|
||||||
* @param address
|
|
||||||
* The {@link Address} instance holding the email address that is used to search the
|
|
||||||
* contacts database.
|
|
||||||
* @param imageView
|
|
||||||
* The {@code ContactBadge} instance to receive the picture.
|
|
||||||
*
|
|
||||||
* @see #mBitmapCache
|
|
||||||
* @see #calculateFallbackBitmap(Address)
|
|
||||||
*/
|
|
||||||
public void loadContactPicture(Address address, ImageView imageView) {
|
|
||||||
Bitmap bitmap = getBitmapFromCache(address);
|
|
||||||
if (bitmap != null) {
|
|
||||||
// The picture was found in the bitmap cache
|
|
||||||
imageView.setImageBitmap(bitmap);
|
|
||||||
} else if (cancelPotentialWork(address, imageView)) {
|
|
||||||
// Query the contacts database in a background thread and try to load the contact
|
|
||||||
// picture, if there is one.
|
|
||||||
ContactPictureRetrievalTask task = new ContactPictureRetrievalTask(imageView, address);
|
|
||||||
AsyncDrawable asyncDrawable = new AsyncDrawable(mResources,
|
|
||||||
calculateFallbackBitmap(address), task);
|
|
||||||
imageView.setImageDrawable(asyncDrawable);
|
|
||||||
try {
|
|
||||||
task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
|
||||||
} catch (RejectedExecutionException e) {
|
|
||||||
// We flooded the thread pool queue... use a fallback picture
|
|
||||||
imageView.setImageBitmap(calculateFallbackBitmap(address));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -176,23 +182,17 @@ public class ContactPictureLoader {
|
||||||
return CONTACT_DUMMY_COLORS_ARGB[colorIndex];
|
return CONTACT_DUMMY_COLORS_ARGB[colorIndex];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
private Bitmap drawTextAndBgColorOnBitmap(Bitmap bitmap, FallbackGlideParams params) {
|
||||||
* Calculates a bitmap with a color and a capital letter for contacts without picture.
|
Canvas canvas = new Canvas(bitmap);
|
||||||
*/
|
|
||||||
private Bitmap calculateFallbackBitmap(Address address) {
|
|
||||||
Bitmap result = Bitmap.createBitmap(mPictureSizeInPx, mPictureSizeInPx,
|
|
||||||
Bitmap.Config.ARGB_8888);
|
|
||||||
|
|
||||||
Canvas canvas = new Canvas(result);
|
int rgb = calcUnknownContactColor(params.address);
|
||||||
|
bitmap.eraseColor(rgb);
|
||||||
|
|
||||||
int rgb = calcUnknownContactColor(address);
|
String letter = calcUnknownContactLetter(params.address);
|
||||||
result.eraseColor(rgb);
|
|
||||||
|
|
||||||
String letter = calcUnknownContactLetter(address);
|
|
||||||
|
|
||||||
Paint paint = new Paint();
|
Paint paint = new Paint();
|
||||||
paint.setAntiAlias(true);
|
paint.setAntiAlias(true);
|
||||||
paint.setStyle(Paint.Style.FILL);
|
paint.setStyle(Style.FILL);
|
||||||
paint.setARGB(255, 255, 255, 255);
|
paint.setARGB(255, 255, 255, 255);
|
||||||
paint.setTextSize(mPictureSizeInPx * 3 / 4); // just scale this down a bit
|
paint.setTextSize(mPictureSizeInPx * 3 / 4); // just scale this down a bit
|
||||||
Rect rect = new Rect();
|
Rect rect = new Rect();
|
||||||
|
@ -202,146 +202,73 @@ public class ContactPictureLoader {
|
||||||
(mPictureSizeInPx / 2f) - (width / 2f),
|
(mPictureSizeInPx / 2f) - (width / 2f),
|
||||||
(mPictureSizeInPx / 2f) + (rect.height() / 2f), paint);
|
(mPictureSizeInPx / 2f) + (rect.height() / 2f), paint);
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void addBitmapToCache(Address key, Bitmap bitmap) {
|
|
||||||
if (getBitmapFromCache(key) == null) {
|
|
||||||
mBitmapCache.put(key, bitmap);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private Bitmap getBitmapFromCache(Address key) {
|
|
||||||
return mBitmapCache.get(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks if a {@code ContactPictureRetrievalTask} was already created to load the contact
|
|
||||||
* picture for the supplied {@code Address}.
|
|
||||||
*
|
|
||||||
* @param address
|
|
||||||
* The {@link Address} instance holding the email address that is used to search the
|
|
||||||
* contacts database.
|
|
||||||
* @param imageView
|
|
||||||
* The {@link ImageView} instance that will receive the picture.
|
|
||||||
*
|
|
||||||
* @return {@code true}, if the contact picture should be loaded in a background thread.
|
|
||||||
* {@code false}, if another {@link ContactPictureRetrievalTask} was already scheduled
|
|
||||||
* to load that contact picture.
|
|
||||||
*/
|
|
||||||
private boolean cancelPotentialWork(Address address, ImageView imageView) {
|
|
||||||
final ContactPictureRetrievalTask task = getContactPictureRetrievalTask(imageView);
|
|
||||||
|
|
||||||
if (task != null && address != null) {
|
|
||||||
if (!address.equals(task.getAddress())) {
|
|
||||||
// Cancel previous task
|
|
||||||
task.cancel(true);
|
|
||||||
} else {
|
|
||||||
// The same work is already in progress
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// No task associated with the ContactBadge, or an existing task was cancelled
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private ContactPictureRetrievalTask getContactPictureRetrievalTask(ImageView imageView) {
|
|
||||||
if (imageView != null) {
|
|
||||||
Drawable drawable = imageView.getDrawable();
|
|
||||||
if (drawable instanceof AsyncDrawable) {
|
|
||||||
AsyncDrawable asyncDrawable = (AsyncDrawable) drawable;
|
|
||||||
return asyncDrawable.getContactPictureRetrievalTask();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Load a contact picture in a background thread.
|
|
||||||
*/
|
|
||||||
class ContactPictureRetrievalTask extends AsyncTask<Void, Void, Bitmap> {
|
|
||||||
private final WeakReference<ImageView> mImageViewReference;
|
|
||||||
private final Address mAddress;
|
|
||||||
|
|
||||||
ContactPictureRetrievalTask(ImageView imageView, Address address) {
|
|
||||||
mImageViewReference = new WeakReference<ImageView>(imageView);
|
|
||||||
mAddress = new Address(address);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Address getAddress() {
|
|
||||||
return mAddress;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Bitmap doInBackground(Void... args) {
|
|
||||||
final String email = mAddress.getAddress();
|
|
||||||
final Uri photoUri = mContactsHelper.getPhotoUri(email);
|
|
||||||
Bitmap bitmap = null;
|
|
||||||
if (photoUri != null) {
|
|
||||||
try {
|
|
||||||
InputStream stream = mContentResolver.openInputStream(photoUri);
|
|
||||||
if (stream != null) {
|
|
||||||
try {
|
|
||||||
Bitmap tempBitmap = BitmapFactory.decodeStream(stream);
|
|
||||||
if (tempBitmap != null) {
|
|
||||||
bitmap = Bitmap.createScaledBitmap(tempBitmap, mPictureSizeInPx,
|
|
||||||
mPictureSizeInPx, true);
|
|
||||||
if (tempBitmap != bitmap) {
|
|
||||||
tempBitmap.recycle();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
try { stream.close(); } catch (IOException e) { /* ignore */ }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (FileNotFoundException e) {
|
|
||||||
/* ignore */
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if (bitmap == null) {
|
|
||||||
bitmap = calculateFallbackBitmap(mAddress);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Save the picture of the contact with that email address in the bitmap cache
|
|
||||||
addBitmapToCache(mAddress, bitmap);
|
|
||||||
|
|
||||||
return bitmap;
|
return bitmap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private class FallbackGlideBitmapDecoder implements ResourceDecoder<FallbackGlideParams, Bitmap> {
|
||||||
|
private final Context context;
|
||||||
|
|
||||||
|
FallbackGlideBitmapDecoder(Context context) {
|
||||||
|
this.context = context;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onPostExecute(Bitmap bitmap) {
|
public Resource<Bitmap> decode(FallbackGlideParams source, int width, int height) throws IOException {
|
||||||
ImageView imageView = mImageViewReference.get();
|
BitmapPool pool = Glide.get(context).getBitmapPool();
|
||||||
if (imageView != null && getContactPictureRetrievalTask(imageView) == this) {
|
Bitmap bitmap = pool.getDirty(mPictureSizeInPx, mPictureSizeInPx, Bitmap.Config.ARGB_8888);
|
||||||
imageView.setImageBitmap(bitmap);
|
if (bitmap == null) {
|
||||||
|
bitmap = Bitmap.createBitmap(mPictureSizeInPx, mPictureSizeInPx, Bitmap.Config.ARGB_8888);
|
||||||
}
|
}
|
||||||
|
drawTextAndBgColorOnBitmap(bitmap, source);
|
||||||
|
return BitmapResource.obtain(bitmap, pool);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getId() {
|
||||||
|
return "fallback-photo";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
private class FallbackGlideParams {
|
||||||
* {@code Drawable} subclass that stores a reference to the {@link ContactPictureRetrievalTask}
|
final Address address;
|
||||||
* that is trying to load the contact picture.
|
|
||||||
*
|
|
||||||
* <p>
|
|
||||||
* The reference is used by {@link ContactPictureLoader#cancelPotentialWork(Address,
|
|
||||||
* ImageView)} to find out if the contact picture is already being loaded by a
|
|
||||||
* {@code ContactPictureRetrievalTask}.
|
|
||||||
* </p>
|
|
||||||
*/
|
|
||||||
static class AsyncDrawable extends BitmapDrawable {
|
|
||||||
private final WeakReference<ContactPictureRetrievalTask> mAsyncTaskReference;
|
|
||||||
|
|
||||||
public AsyncDrawable(Resources res, Bitmap bitmap, ContactPictureRetrievalTask task) {
|
FallbackGlideParams(Address address) {
|
||||||
super(res, bitmap);
|
this.address = address;
|
||||||
mAsyncTaskReference = new WeakReference<ContactPictureRetrievalTask>(task);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public ContactPictureRetrievalTask getContactPictureRetrievalTask() {
|
public String getId() {
|
||||||
return mAsyncTaskReference.get();
|
return String.format(Locale.ROOT, "%s-%s", address.getAddress(), address.getPersonal());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private class FallbackGlideModelLoader implements ModelLoader<FallbackGlideParams, FallbackGlideParams> {
|
||||||
|
@Override
|
||||||
|
public DataFetcher<FallbackGlideParams> getResourceFetcher(final FallbackGlideParams model, int width,
|
||||||
|
int height) {
|
||||||
|
|
||||||
|
return new DataFetcher<FallbackGlideParams>() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public FallbackGlideParams loadData(Priority priority) throws Exception {
|
||||||
|
return model;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void cleanup() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getId() {
|
||||||
|
return model.getId();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void cancel() {
|
||||||
|
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,15 +2,14 @@ package com.fsck.k9.helper;
|
||||||
|
|
||||||
|
|
||||||
import android.content.ContentResolver;
|
import android.content.ContentResolver;
|
||||||
import android.content.ContentUris;
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.database.Cursor;
|
import android.database.Cursor;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.provider.ContactsContract;
|
import android.provider.ContactsContract;
|
||||||
import timber.log.Timber;
|
import timber.log.Timber;
|
||||||
|
import android.provider.ContactsContract.CommonDataKinds.Photo;
|
||||||
|
|
||||||
import com.fsck.k9.K9;
|
|
||||||
import com.fsck.k9.mail.Address;
|
import com.fsck.k9.mail.Address;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -229,7 +228,6 @@ public class Contacts {
|
||||||
* no such contact could be found or the contact doesn't have a picture.
|
* no such contact could be found or the contact doesn't have a picture.
|
||||||
*/
|
*/
|
||||||
public Uri getPhotoUri(String address) {
|
public Uri getPhotoUri(String address) {
|
||||||
Long contactId;
|
|
||||||
try {
|
try {
|
||||||
final Cursor c = getContactByAddress(address);
|
final Cursor c = getContactByAddress(address);
|
||||||
if (c == null) {
|
if (c == null) {
|
||||||
|
@ -240,30 +238,13 @@ public class Contacts {
|
||||||
if (!c.moveToFirst()) {
|
if (!c.moveToFirst()) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
final String uriString = c.getString(c.getColumnIndex(Photo.PHOTO_URI));
|
||||||
contactId = c.getLong(CONTACT_ID_INDEX);
|
return Uri.parse(uriString);
|
||||||
|
} catch (IllegalStateException e) {
|
||||||
|
return null;
|
||||||
} finally {
|
} finally {
|
||||||
c.close();
|
c.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
Cursor cur = mContentResolver.query(
|
|
||||||
ContactsContract.Data.CONTENT_URI,
|
|
||||||
null,
|
|
||||||
ContactsContract.Data.CONTACT_ID + "=" + contactId + " AND "
|
|
||||||
+ ContactsContract.Data.MIMETYPE + "='"
|
|
||||||
+ ContactsContract.CommonDataKinds.Photo.CONTENT_ITEM_TYPE + "'", null,
|
|
||||||
null);
|
|
||||||
if (cur == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
if (!cur.moveToFirst()) {
|
|
||||||
cur.close();
|
|
||||||
return null; // no photo
|
|
||||||
}
|
|
||||||
// Ok, they have a photo
|
|
||||||
cur.close();
|
|
||||||
Uri person = ContentUris.withAppendedId(ContactsContract.Contacts.CONTENT_URI, contactId);
|
|
||||||
return Uri.withAppendedPath(person, ContactsContract.Contacts.Photo.CONTENT_DIRECTORY);
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
Timber.e(e, "Couldn't fetch photo for contact with email %s", address);
|
Timber.e(e, "Couldn't fetch photo for contact with email %s", address);
|
||||||
return null;
|
return null;
|
||||||
|
|
Loading…
Reference in a new issue