Move whole avatar stack from Bitmap to Drawable

Stephen Paul Weber created

Change summary

src/cheogram/java/com/cheogram/android/ConnectionService.java                       |  5 
src/cheogram/java/eu/siacs/conversations/ui/adapter/BackupFileAdapter.java          | 10 
src/main/java/eu/siacs/conversations/entities/Contact.java                          |  3 
src/main/java/eu/siacs/conversations/persistance/FileBackend.java                   |  8 
src/main/java/eu/siacs/conversations/services/AvatarService.java                    | 79 
src/main/java/eu/siacs/conversations/services/ContactChooserTargetService.java      |  5 
src/main/java/eu/siacs/conversations/services/NotificationService.java              | 24 
src/main/java/eu/siacs/conversations/ui/PublishGroupChatProfilePictureActivity.java |  8 
src/main/java/eu/siacs/conversations/ui/PublishProfilePictureActivity.java          |  8 
src/main/java/eu/siacs/conversations/ui/util/AvatarWorkerTask.java                  | 20 
src/main/res/layout/message_sent.xml                                                | 32 
11 files changed, 101 insertions(+), 101 deletions(-)

Detailed changes

src/cheogram/java/com/cheogram/android/ConnectionService.java 🔗

@@ -44,6 +44,7 @@ import io.michaelrocks.libphonenumber.android.NumberParseException;
 
 import eu.siacs.conversations.R;
 import eu.siacs.conversations.entities.Account;
+import eu.siacs.conversations.persistance.FileBackend;
 import eu.siacs.conversations.services.AppRTCAudioManager;
 import eu.siacs.conversations.services.AvatarService;
 import eu.siacs.conversations.services.XmppConnectionService.XmppConnectionBinder;
@@ -215,11 +216,11 @@ public class ConnectionService extends android.telecom.ConnectionService {
 			this.account = account;
 			this.with = with;
 
-			gatewayIcon = Icon.createWithBitmap(xmppConnectionService.getAvatarService().get(
+			gatewayIcon = Icon.createWithBitmap(FileBackend.drawDrawable(xmppConnectionService.getAvatarService().get(
 				account.getRoster().getContact(Jid.of(with.getDomain())),
 				AvatarService.getSystemUiAvatarSize(xmppConnectionService),
 				false
-			));
+			)));
 
 			if (postDialString != null) {
 				for (int i = postDialString.length() - 1; i >= 0; i--) {

src/cheogram/java/eu/siacs/conversations/ui/adapter/BackupFileAdapter.java 🔗

@@ -86,7 +86,7 @@ public class BackupFileAdapter extends RecyclerView.Adapter<BackupFileAdapter.Ba
         void onClick(ImportBackupService.BackupFile backupFile);
     }
 
-    static class BitmapWorkerTask extends AsyncTask<Jid, Void, Bitmap> {
+    static class BitmapWorkerTask extends AsyncTask<Jid, Void, Drawable> {
         private final WeakReference<ImageView> imageViewReference;
         private Jid jid  = null;
         private final int size;
@@ -98,17 +98,17 @@ public class BackupFileAdapter extends RecyclerView.Adapter<BackupFileAdapter.Ba
         }
 
         @Override
-        protected Bitmap doInBackground(Jid... params) {
+        protected Drawable doInBackground(Jid... params) {
             this.jid = params[0];
             return AvatarService.get(this.jid, size);
         }
 
         @Override
-        protected void onPostExecute(Bitmap bitmap) {
+        protected void onPostExecute(Drawable bitmap) {
             if (bitmap != null && !isCancelled()) {
                 final ImageView imageView = imageViewReference.get();
                 if (imageView != null) {
-                    imageView.setImageBitmap(bitmap);
+                    imageView.setImageDrawable(bitmap);
                     imageView.setBackgroundColor(0x00000000);
                 }
             }
@@ -167,4 +167,4 @@ public class BackupFileAdapter extends RecyclerView.Adapter<BackupFileAdapter.Ba
         }
     }
 
-}
+}

src/main/java/eu/siacs/conversations/entities/Contact.java 🔗

@@ -35,6 +35,7 @@ import eu.siacs.conversations.Config;
 import eu.siacs.conversations.R;
 import eu.siacs.conversations.android.AbstractPhoneContact;
 import eu.siacs.conversations.android.JabberIdContact;
+import eu.siacs.conversations.persistance.FileBackend;
 import eu.siacs.conversations.services.AvatarService;
 import eu.siacs.conversations.services.QuickConversationsService;
 import eu.siacs.conversations.services.XmppConnectionService;
@@ -680,7 +681,7 @@ public class Contact implements ListItem, Blockable {
         ).setAddress(
             Uri.fromParts("xmpp", account.getJid().asBareJid().toString(), null)
         ).setIcon(
-            Icon.createWithBitmap(ctx.getAvatarService().get(this, AvatarService.getSystemUiAvatarSize(ctx) / 2, false))
+            Icon.createWithBitmap(FileBackend.drawDrawable(ctx.getAvatarService().get(this, AvatarService.getSystemUiAvatarSize(ctx) / 2, false)))
         ).setHighlightColor(
             0x7401CF
         ).setShortDescription(

src/main/java/eu/siacs/conversations/persistance/FileBackend.java 🔗

@@ -1293,7 +1293,9 @@ public class FileBackend {
         }
     }
 
-    protected Bitmap drawDrawable(Drawable drawable) {
+    public static Bitmap drawDrawable(Drawable drawable) {
+        if (drawable == null) return null;
+
         Bitmap bitmap = null;
 
         if (drawable instanceof BitmapDrawable) {
@@ -2001,12 +2003,12 @@ public class FileBackend {
         return new Dimensions(h, w);
     }
 
-    public Bitmap getAvatar(String avatar, int size) {
+    public Drawable getAvatar(String avatar, int size) {
         if (avatar == null) {
             return null;
         }
         Bitmap bm = cropCenter(getAvatarUri(avatar), size, size);
-        return bm;
+        return new BitmapDrawable(bm);
     }
 
     private static class Dimensions {

src/main/java/eu/siacs/conversations/services/AvatarService.java 🔗

@@ -39,6 +39,7 @@ import eu.siacs.conversations.entities.Message;
 import eu.siacs.conversations.entities.MucOptions;
 import eu.siacs.conversations.entities.RawBlockable;
 import eu.siacs.conversations.entities.Room;
+import eu.siacs.conversations.persistance.FileBackend;
 import eu.siacs.conversations.utils.UIHelper;
 import eu.siacs.conversations.xmpp.Jid;
 import eu.siacs.conversations.xmpp.OnAdvancedStreamFeaturesLoaded;
@@ -72,7 +73,7 @@ public class AvatarService implements OnAdvancedStreamFeaturesLoaded {
 		return (int) (SYSTEM_UI_AVATAR_SIZE * context.getResources().getDisplayMetrics().density);
 	}
 
-	public Bitmap get(final Avatarable avatarable, final int size, final boolean cachedOnly) {
+	public Drawable get(final Avatarable avatarable, final int size, final boolean cachedOnly) {
 		if (avatarable instanceof Account) {
 			return get((Account) avatarable,size,cachedOnly);
 		} else if (avatarable instanceof Conversation) {
@@ -90,7 +91,7 @@ public class AvatarService implements OnAdvancedStreamFeaturesLoaded {
 
 	}
 
-	private Bitmap get(final Room result, final int size, boolean cacheOnly) {
+	private Drawable get(final Room result, final int size, boolean cacheOnly) {
 		final Jid room = result.getRoom();
 		Conversation conversation = room != null ? mXmppConnectionService.findFirstMuc(room) : null;
 		if (conversation != null) {
@@ -99,12 +100,12 @@ public class AvatarService implements OnAdvancedStreamFeaturesLoaded {
 		return get(CHANNEL_SYMBOL, room != null ? room.asBareJid().toEscapedString() : result.getName(), size, cacheOnly);
 	}
 
-	private Bitmap get(final Contact contact, final int size, boolean cachedOnly) {
+	private Drawable get(final Contact contact, final int size, boolean cachedOnly) {
 		if (contact.isSelf()) {
 			return get(contact.getAccount(), size, cachedOnly);
 		}
 		final String KEY = key(contact, size);
-		Bitmap avatar = this.mXmppConnectionService.getBitmapCache().get(KEY);
+		Drawable avatar = this.mXmppConnectionService.getDrawableCache().get(KEY);
 		if (avatar != null || cachedOnly) {
 			return avatar;
 		}
@@ -112,7 +113,7 @@ public class AvatarService implements OnAdvancedStreamFeaturesLoaded {
 			avatar = mXmppConnectionService.getFileBackend().getAvatar(contact.getAvatarFilename(), size);
 		}
 		if (avatar == null && contact.getProfilePhoto() != null) {
-			avatar = mXmppConnectionService.getFileBackend().cropCenterSquare(Uri.parse(contact.getProfilePhoto()), size);
+			avatar = new BitmapDrawable(mXmppConnectionService.getFileBackend().cropCenterSquare(Uri.parse(contact.getProfilePhoto()), size));
 		}
 		if (avatar == null && contact.getAvatarFilename() != null) {
 			avatar = mXmppConnectionService.getFileBackend().getAvatar(contact.getAvatarFilename(), size);
@@ -120,7 +121,7 @@ public class AvatarService implements OnAdvancedStreamFeaturesLoaded {
 		if (avatar == null) {
 			avatar = get(contact.getDisplayName(), contact.getJid().asBareJid().toString(), size, false);
 		}
-		this.mXmppConnectionService.getBitmapCache().put(KEY, avatar);
+		this.mXmppConnectionService.getDrawableCache().put(KEY, avatar);
 		return avatar;
 	}
 
@@ -135,7 +136,7 @@ public class AvatarService implements OnAdvancedStreamFeaturesLoaded {
 	private Bitmap getRoundedShortcut(final Contact contact, boolean withIcon) {
 		DisplayMetrics metrics = mXmppConnectionService.getResources().getDisplayMetrics();
 		int size = Math.round(metrics.density * 48);
-		Bitmap bitmap = get(contact, size);
+		Bitmap bitmap = FileBackend.drawDrawable(get(contact, size));
 		Bitmap output = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), Bitmap.Config.ARGB_8888);
 		Canvas canvas = new Canvas(output);
 		final Paint paint = new Paint();
@@ -191,7 +192,7 @@ public class AvatarService implements OnAdvancedStreamFeaturesLoaded {
 		return bitmap;
 	}
 
-	public Bitmap get(final MucOptions.User user, final int size, boolean cachedOnly) {
+	public Drawable get(final MucOptions.User user, final int size, boolean cachedOnly) {
 		Contact c = user.getContact();
 		if (c != null && (c.getProfilePhoto() != null || c.getAvatarFilename() != null || user.getAvatar() == null)) {
 			return get(c, size, cachedOnly);
@@ -200,9 +201,9 @@ public class AvatarService implements OnAdvancedStreamFeaturesLoaded {
 		}
 	}
 
-	private Bitmap getImpl(final MucOptions.User user, final int size, boolean cachedOnly) {
+	private Drawable getImpl(final MucOptions.User user, final int size, boolean cachedOnly) {
 		final String KEY = key(user, size);
-		Bitmap avatar = this.mXmppConnectionService.getBitmapCache().get(KEY);
+		Drawable avatar = this.mXmppConnectionService.getDrawableCache().get(KEY);
 		if (avatar != null || cachedOnly) {
 			return avatar;
 		}
@@ -218,14 +219,14 @@ public class AvatarService implements OnAdvancedStreamFeaturesLoaded {
 				avatar = get(user.getName(), seed, size, false);
 			}
 		}
-		this.mXmppConnectionService.getBitmapCache().put(KEY, avatar);
+		this.mXmppConnectionService.getDrawableCache().put(KEY, avatar);
 		return avatar;
 	}
 
 	public void clear(Contact contact) {
 		synchronized (this.sizes) {
 			for (final Integer size : sizes) {
-				this.mXmppConnectionService.getBitmapCache().remove(key(contact, size));
+				this.mXmppConnectionService.getDrawableCache().remove(key(contact, size));
 			}
 		}
 		for (Conversation conversation : mXmppConnectionService.findAllConferencesWith(contact)) {
@@ -265,11 +266,11 @@ public class AvatarService implements OnAdvancedStreamFeaturesLoaded {
 				size;
 	}
 
-	public Bitmap get(ListItem item, int size) {
+	public Drawable get(ListItem item, int size) {
 		return get(item, size, false);
 	}
 
-	public Bitmap get(ListItem item, int size, boolean cachedOnly) {
+	public Drawable get(ListItem item, int size, boolean cachedOnly) {
 		if (item instanceof RawBlockable) {
 			return get(item.getDisplayName(), item.getJid().toEscapedString(), size, cachedOnly);
 		} else if (item instanceof Contact) {
@@ -294,11 +295,11 @@ public class AvatarService implements OnAdvancedStreamFeaturesLoaded {
 		}
 	}
 
-	public Bitmap get(Conversation conversation, int size) {
+	public Drawable get(Conversation conversation, int size) {
 		return get(conversation, size, false);
 	}
 
-	public Bitmap get(Conversation conversation, int size, boolean cachedOnly) {
+	public Drawable get(Conversation conversation, int size, boolean cachedOnly) {
 		if (conversation.getMode() == Conversation.MODE_SINGLE) {
 			return get(conversation.getContact(), size, cachedOnly);
 		} else {
@@ -316,7 +317,7 @@ public class AvatarService implements OnAdvancedStreamFeaturesLoaded {
 				if (keys == null) {
 					return;
 				}
-				LruCache<String, Bitmap> cache = this.mXmppConnectionService.getBitmapCache();
+				LruCache<String, Drawable> cache = this.mXmppConnectionService.getDrawableCache();
 				for (String key : keys) {
 					cache.remove(key);
 				}
@@ -325,9 +326,9 @@ public class AvatarService implements OnAdvancedStreamFeaturesLoaded {
 		}
 	}
 
-	private Bitmap get(MucOptions mucOptions, int size, boolean cachedOnly) {
+	private Drawable get(MucOptions mucOptions, int size, boolean cachedOnly) {
 		final String KEY = key(mucOptions, size);
-		Bitmap bitmap = this.mXmppConnectionService.getBitmapCache().get(KEY);
+		Drawable bitmap = this.mXmppConnectionService.getDrawableCache().get(KEY);
 		if (bitmap != null || cachedOnly) {
 			return bitmap;
 		}
@@ -348,23 +349,23 @@ public class AvatarService implements OnAdvancedStreamFeaturesLoaded {
 			}
 		}
 
-		this.mXmppConnectionService.getBitmapCache().put(KEY, bitmap);
+		this.mXmppConnectionService.getDrawableCache().put(KEY, bitmap);
 
 		return bitmap;
 	}
 
-	private Bitmap get(List<MucOptions.User> users, int size, boolean cachedOnly) {
+	private Drawable get(List<MucOptions.User> users, int size, boolean cachedOnly) {
 		final String KEY = key(users, size);
-		Bitmap bitmap = this.mXmppConnectionService.getBitmapCache().get(KEY);
+		Drawable bitmap = this.mXmppConnectionService.getDrawableCache().get(KEY);
 		if (bitmap != null || cachedOnly) {
 			return bitmap;
 		}
 		bitmap = getImpl(users, size);
-		this.mXmppConnectionService.getBitmapCache().put(KEY, bitmap);
+		this.mXmppConnectionService.getDrawableCache().put(KEY, bitmap);
 		return bitmap;
 	}
 
-	private Bitmap getImpl(List<MucOptions.User> users, int size) {
+	private Drawable getImpl(List<MucOptions.User> users, int size) {
 		int count = users.size();
 		Bitmap bitmap = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888);
 		Canvas canvas = new Canvas(bitmap);
@@ -395,7 +396,7 @@ public class AvatarService implements OnAdvancedStreamFeaturesLoaded {
 			drawTile(canvas, "\u2026", PLACEHOLDER_COLOR, size / 2 + 1, size / 2 + 1,
 					size, size);
 		}
-		return bitmap;
+		return new BitmapDrawable(bitmap);
 	}
 
 	public void clear(final MucOptions options) {
@@ -404,7 +405,7 @@ public class AvatarService implements OnAdvancedStreamFeaturesLoaded {
 		}
 		synchronized (this.sizes) {
 			for (Integer size : sizes) {
-				this.mXmppConnectionService.getBitmapCache().remove(key(options, size));
+				this.mXmppConnectionService.getDrawableCache().remove(key(options, size));
 			}
 		}
 	}
@@ -443,13 +444,13 @@ public class AvatarService implements OnAdvancedStreamFeaturesLoaded {
 		return key;
 	}
 
-	public Bitmap get(Account account, int size) {
+	public Drawable get(Account account, int size) {
 		return get(account, size, false);
 	}
 
-	public Bitmap get(Account account, int size, boolean cachedOnly) {
+	public Drawable get(Account account, int size, boolean cachedOnly) {
 		final String KEY = key(account, size);
-		Bitmap avatar = mXmppConnectionService.getBitmapCache().get(KEY);
+		Drawable avatar = mXmppConnectionService.getDrawableCache().get(KEY);
 		if (avatar != null || cachedOnly) {
 			return avatar;
 		}
@@ -463,11 +464,11 @@ public class AvatarService implements OnAdvancedStreamFeaturesLoaded {
 				avatar = get(jid, null, size, false);
 			}
 		}
-		mXmppConnectionService.getBitmapCache().put(KEY, avatar);
+		mXmppConnectionService.getDrawableCache().put(KEY, avatar);
 		return avatar;
 	}
 
-	public Bitmap get(Message message, int size, boolean cachedOnly) {
+	public Drawable get(Message message, int size, boolean cachedOnly) {
 		final Conversational conversation = message.getConversation();
 		if (message.getType() == Message.TYPE_STATUS && message.getCounterparts() != null && message.getCounterparts().size() > 1) {
 			return get(message.getCounterparts(), size, cachedOnly);
@@ -503,7 +504,7 @@ public class AvatarService implements OnAdvancedStreamFeaturesLoaded {
 	public void clear(Account account) {
 		synchronized (this.sizes) {
 			for (Integer size : sizes) {
-				this.mXmppConnectionService.getBitmapCache().remove(key(account, size));
+				this.mXmppConnectionService.getDrawableCache().remove(key(account, size));
 			}
 		}
 	}
@@ -511,7 +512,7 @@ public class AvatarService implements OnAdvancedStreamFeaturesLoaded {
 	public void clear(MucOptions.User user) {
 		synchronized (this.sizes) {
 			for (Integer size : sizes) {
-				this.mXmppConnectionService.getBitmapCache().remove(key(user, size));
+				this.mXmppConnectionService.getDrawableCache().remove(key(user, size));
 			}
 		}
 	}
@@ -528,27 +529,27 @@ public class AvatarService implements OnAdvancedStreamFeaturesLoaded {
 		return get(name,null, size,false);
 	}*/
 
-	public Bitmap get(final String name, String seed, final int size, boolean cachedOnly) {
+	public Drawable get(final String name, String seed, final int size, boolean cachedOnly) {
 		final String KEY = key(seed == null ? name : name+"\0"+seed, size);
-		Bitmap bitmap = mXmppConnectionService.getBitmapCache().get(KEY);
+		Drawable bitmap = mXmppConnectionService.getDrawableCache().get(KEY);
 		if (bitmap != null || cachedOnly) {
 			return bitmap;
 		}
 		bitmap = getImpl(name, seed, size);
-		mXmppConnectionService.getBitmapCache().put(KEY, bitmap);
+		mXmppConnectionService.getDrawableCache().put(KEY, bitmap);
 		return bitmap;
 	}
 
-	public static Bitmap get(final Jid jid, final int size) {
+	public static Drawable get(final Jid jid, final int size) {
 		return getImpl(jid.asBareJid().toEscapedString(), null, size);
 	}
 
-	private static Bitmap getImpl(final String name, final String seed, final int size) {
+	private static Drawable getImpl(final String name, final String seed, final int size) {
 		Bitmap bitmap = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888);
 		Canvas canvas = new Canvas(bitmap);
 		final String trimmedName = name == null ? "" : name.trim();
 		drawTile(canvas, trimmedName, seed, 0, 0, size, size);
-		return bitmap;
+		return new BitmapDrawable(bitmap);
 	}
 
 	private String key(String name, int size) {

src/main/java/eu/siacs/conversations/services/ContactChooserTargetService.java 🔗

@@ -21,6 +21,7 @@ import java.util.List;
 
 import eu.siacs.conversations.Config;
 import eu.siacs.conversations.entities.Conversation;
+import eu.siacs.conversations.persistance.FileBackend;
 import eu.siacs.conversations.ui.ConversationsActivity;
 import eu.siacs.conversations.utils.Compatibility;
 
@@ -69,8 +70,8 @@ public class ContactChooserTargetService extends ChooserTargetService implements
                 }
                 final String name = conversation.getName().toString();
                 final Icon icon =
-                        Icon.createWithBitmap(
-                                mXmppConnectionService.getAvatarService().get(conversation, pixel));
+                        Icon.createWithBitmap(FileBackend.drawDrawable(
+                                mXmppConnectionService.getAvatarService().get(conversation, pixel)));
                 final float score = 1 - (1.0f / MAX_TARGETS) * chooserTargets.size();
                 final Bundle extras = new Bundle();
                 extras.putString(ConversationsActivity.EXTRA_CONVERSATION, conversation.getUuid());

src/main/java/eu/siacs/conversations/services/NotificationService.java 🔗

@@ -660,10 +660,10 @@ public class NotificationService {
                     mXmppConnectionService.getString(R.string.rtp_state_incoming_call));
         }
         builder.setStyle(style);
-        builder.setLargeIcon(
+        builder.setLargeIcon(FileBackend.drawDrawable(
                 mXmppConnectionService
                         .getAvatarService()
-                        .get(contact, AvatarService.getSystemUiAvatarSize(mXmppConnectionService)));
+                        .get(contact, AvatarService.getSystemUiAvatarSize(mXmppConnectionService))));
         final Uri systemAccount = contact.getSystemAccount();
         if (systemAccount != null) {
             builder.addPerson(systemAccount.toString());
@@ -1150,12 +1150,12 @@ public class NotificationService {
         builder.setContentIntent(createContentIntent(conversation));
         builder.setDeleteIntent(createMissedCallsDeleteIntent(conversation));
         if (!publicVersion && conversation instanceof Conversation) {
-            builder.setLargeIcon(
+            builder.setLargeIcon(FileBackend.drawDrawable(
                     mXmppConnectionService
                             .getAvatarService()
                             .get(
                                     (Conversation) conversation,
-                                    AvatarService.getSystemUiAvatarSize(mXmppConnectionService)));
+                                    AvatarService.getSystemUiAvatarSize(mXmppConnectionService))));
         }
         modifyMissedCall(builder, conversation.getAccount());
         return builder;
@@ -1250,12 +1250,12 @@ public class NotificationService {
                         quietHours ? "quiet_hours" : (notify ? "messages" : "silent_messages"));
         if (messages.size() >= 1) {
             final Conversation conversation = (Conversation) messages.get(0).getConversation();
-            mBuilder.setLargeIcon(
+            mBuilder.setLargeIcon(FileBackend.drawDrawable(
                     mXmppConnectionService
                             .getAvatarService()
                             .get(
                                     conversation,
-                                    AvatarService.getSystemUiAvatarSize(mXmppConnectionService)));
+                                    AvatarService.getSystemUiAvatarSize(mXmppConnectionService))));
             mBuilder.setContentTitle(conversation.getName());
             if (Config.HIDE_MESSAGE_TEXT_IN_NOTIFICATION) {
                 int count = messages.size();
@@ -1446,14 +1446,14 @@ public class NotificationService {
                 builder.setImportant(c.getBooleanAttribute(Conversation.ATTRIBUTE_PINNED_ON_TOP, false));
             }
             builder.setIcon(
-                    IconCompat.createWithBitmap(
+                    IconCompat.createWithBitmap(FileBackend.drawDrawable(
                             mXmppConnectionService
                                     .getAvatarService()
                                     .get(
                                             message,
                                             AvatarService.getSystemUiAvatarSize(
                                                     mXmppConnectionService),
-                                            false)));
+                                            false))));
         }
         return builder.build();
     }
@@ -1473,14 +1473,14 @@ public class NotificationService {
                 builder.setImportant(c.getBooleanAttribute(Conversation.ATTRIBUTE_PINNED_ON_TOP, false));
             }
             builder.setIcon(
-                    IconCompat.createWithBitmap(
+                    IconCompat.createWithBitmap(FileBackend.drawDrawable(
                             mXmppConnectionService
                                     .getAvatarService()
                                     .get(
                                             contact,
                                             AvatarService.getSystemUiAvatarSize(
                                                     mXmppConnectionService),
-                                            false)));
+                                            false))));
         }
         return builder.build();
     }
@@ -1492,13 +1492,13 @@ public class NotificationService {
                     new Person.Builder().setName(mXmppConnectionService.getString(R.string.me));
             if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
                 meBuilder.setIcon(
-                        IconCompat.createWithBitmap(
+                        IconCompat.createWithBitmap(FileBackend.drawDrawable(
                                 mXmppConnectionService
                                         .getAvatarService()
                                         .get(
                                                 conversation.getAccount(),
                                                 AvatarService.getSystemUiAvatarSize(
-                                                        mXmppConnectionService))));
+                                                        mXmppConnectionService)))));
             }
             final Person me = meBuilder.build();
             NotificationCompat.MessagingStyle messagingStyle =

src/main/java/eu/siacs/conversations/ui/PublishGroupChatProfilePictureActivity.java 🔗

@@ -31,6 +31,8 @@ package eu.siacs.conversations.ui;
 
 import android.content.Intent;
 import android.graphics.Bitmap;
+import android.graphics.drawable.BitmapDrawable;
+import android.graphics.drawable.Drawable;
 import android.net.Uri;
 import android.os.Bundle;
 import android.util.Log;
@@ -76,14 +78,14 @@ public class PublishGroupChatProfilePictureActivity extends XmppActivity impleme
 
     private void reloadAvatar() {
         final int size = (int) getResources().getDimension(R.dimen.publish_avatar_size);
-        Bitmap bitmap;
+        Drawable bitmap;
         if (uri == null) {
             bitmap = xmppConnectionService.getAvatarService().get(conversation, size);
         } else {
             Log.d(Config.LOGTAG, "loading " + uri.toString() + " into preview");
-            bitmap = xmppConnectionService.getFileBackend().cropCenterSquare(uri, size);
+            bitmap = new BitmapDrawable(xmppConnectionService.getFileBackend().cropCenterSquare(uri, size));
         }
-        this.binding.accountImage.setImageBitmap(bitmap);
+        this.binding.accountImage.setImageDrawable(bitmap);
         this.binding.publishButton.setEnabled(uri != null);
     }
 

src/main/java/eu/siacs/conversations/ui/PublishProfilePictureActivity.java 🔗

@@ -2,6 +2,8 @@ package eu.siacs.conversations.ui;
 
 import android.app.Activity;
 import android.content.Intent;
+import android.graphics.drawable.BitmapDrawable;
+import android.graphics.drawable.Drawable;
 import android.graphics.Bitmap;
 import android.net.Uri;
 import android.os.Build;
@@ -244,12 +246,12 @@ public class PublishProfilePictureActivity extends XmppActivity implements XmppC
 
     protected void loadImageIntoPreview(Uri uri) {
 
-        Bitmap bm = null;
+        Drawable bm = null;
         if (uri == null) {
             bm = avatarService().get(account, (int) getResources().getDimension(R.dimen.publish_avatar_size));
         } else {
             try {
-                bm = xmppConnectionService.getFileBackend().cropCenterSquare(uri, (int) getResources().getDimension(R.dimen.publish_avatar_size));
+                bm = new BitmapDrawable(xmppConnectionService.getFileBackend().cropCenterSquare(uri, (int) getResources().getDimension(R.dimen.publish_avatar_size)));
             } catch (Exception e) {
                 Log.d(Config.LOGTAG, "unable to load bitmap into image view", e);
             }
@@ -262,7 +264,7 @@ public class PublishProfilePictureActivity extends XmppActivity implements XmppC
             this.hintOrWarning.setText(R.string.error_publish_avatar_converting);
             return;
         }
-        this.avatar.setImageBitmap(bm);
+        this.avatar.setImageDrawable(bm);
         if (support) {
             togglePublishButton(uri != null, R.string.publish);
             this.hintOrWarning.setVisibility(View.INVISIBLE);

src/main/java/eu/siacs/conversations/ui/util/AvatarWorkerTask.java 🔗

@@ -3,9 +3,11 @@ package eu.siacs.conversations.ui.util;
 import android.content.Context;
 import android.content.res.Resources;
 import android.graphics.Bitmap;
+import android.graphics.drawable.AnimatedImageDrawable;
 import android.graphics.drawable.BitmapDrawable;
 import android.graphics.drawable.Drawable;
 import android.os.AsyncTask;
+import android.os.Build;
 import android.widget.ImageView;
 
 import androidx.annotation.DimenRes;
@@ -18,7 +20,7 @@ import eu.siacs.conversations.entities.Account;
 import eu.siacs.conversations.services.AvatarService;
 import eu.siacs.conversations.ui.XmppActivity;
 
-public class AvatarWorkerTask extends AsyncTask<AvatarService.Avatarable, Void, Bitmap> {
+public class AvatarWorkerTask extends AsyncTask<AvatarService.Avatarable, Void, Drawable> {
     private final WeakReference<ImageView> imageViewReference;
     private AvatarService.Avatarable avatarable = null;
     private @DimenRes
@@ -30,7 +32,7 @@ public class AvatarWorkerTask extends AsyncTask<AvatarService.Avatarable, Void,
     }
 
     @Override
-    protected Bitmap doInBackground(AvatarService.Avatarable... params) {
+    protected Drawable doInBackground(AvatarService.Avatarable... params) {
         this.avatarable = params[0];
         final XmppActivity activity = XmppActivity.find(imageViewReference);
         if (activity == null) {
@@ -40,12 +42,15 @@ public class AvatarWorkerTask extends AsyncTask<AvatarService.Avatarable, Void,
     }
 
     @Override
-    protected void onPostExecute(Bitmap bitmap) {
+    protected void onPostExecute(Drawable bitmap) {
         if (bitmap != null && !isCancelled()) {
             final ImageView imageView = imageViewReference.get();
             if (imageView != null) {
-                imageView.setImageBitmap(bitmap);
+                imageView.setImageDrawable(bitmap);
                 imageView.setBackgroundColor(0x00000000);
+                if (Build.VERSION.SDK_INT >= 28 && bitmap instanceof AnimatedImageDrawable) {
+                    ((AnimatedImageDrawable) bitmap).start();
+                }
             }
         }
     }
@@ -81,12 +86,15 @@ public class AvatarWorkerTask extends AsyncTask<AvatarService.Avatarable, Void,
             if (activity == null) {
                 return;
             }
-            final Bitmap bm = activity.avatarService().get(avatarable, (int) activity.getResources().getDimension(size), true);
+            final Drawable bm = activity.avatarService().get(avatarable, (int) activity.getResources().getDimension(size), true);
             setContentDescription(avatarable, imageView);
             if (bm != null) {
                 cancelPotentialWork(avatarable, imageView);
-                imageView.setImageBitmap(bm);
+                imageView.setImageDrawable(bm);
                 imageView.setBackgroundColor(0x00000000);
+                if (Build.VERSION.SDK_INT >= 28 && bm instanceof AnimatedImageDrawable) {
+                    ((AnimatedImageDrawable) bm).start();
+                }
             } else {
                 imageView.setBackgroundColor(avatarable.getAvatarBackgroundColor());
                 imageView.setImageDrawable(null);

src/main/res/layout/message_sent.xml 🔗

@@ -10,34 +10,16 @@
     android:paddingRight="8dp"
     android:paddingBottom="3dp">
 
-    <RelativeLayout
-        android:id="@+id/message_photo_box"
+    <com.google.android.material.imageview.ShapeableImageView
+        android:id="@+id/message_photo"
         android:layout_width="48dp"
         android:layout_height="48dp"
         android:layout_alignParentEnd="true"
         android:layout_alignParentRight="true"
-        android:layout_alignParentBottom="true">
-
-        <LinearLayout
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:orientation="vertical">
-
-            <com.google.android.material.imageview.ShapeableImageView
-                android:id="@+id/message_photo"
-                android:layout_width="match_parent"
-                android:layout_height="match_parent"
-                android:scaleType="fitXY"
-                app:strokeColor="@color/custom_theme_accent"
-                app:shapeAppearance="@style/ShapeAppearanceOverlay.Photo" />
-
-            <View
-                android:id="@+id/placeholder"
-                android:layout_width="match_parent"
-                android:layout_height="3dp" />
-        </LinearLayout>
-
-    </RelativeLayout>
+        android:layout_alignParentBottom="true"
+        android:scaleType="fitXY"
+        app:strokeColor="@color/custom_theme_accent"
+        app:shapeAppearance="@style/ShapeAppearanceOverlay.Photo" />
 
     <LinearLayout
         android:id="@+id/message_box"
@@ -48,7 +30,7 @@
         android:paddingRight="20dp"
         android:paddingTop="5dp"
         android:paddingBottom="5dp"
-        android:layout_toLeftOf="@+id/message_photo_box"
+        android:layout_toLeftOf="@+id/message_photo"
         android:elevation="3dp"
         android:background="@drawable/message_bubble_sent"
         android:longClickable="true"