From e5617d53ee29e51435510d75df2224dac91b2c44 Mon Sep 17 00:00:00 2001 From: Sylvain Berfini Date: Thu, 28 Sep 2023 10:53:59 +0200 Subject: [PATCH] Reworked & improved how we load contact pictures --- .../org/linphone/contacts/ContactsManager.kt | 21 +++---- .../notifications/NotificationsManager.kt | 43 +++----------- .../java/org/linphone/utils/ImageUtils.kt | 59 +++++-------------- 3 files changed, 32 insertions(+), 91 deletions(-) diff --git a/app/src/main/java/org/linphone/contacts/ContactsManager.kt b/app/src/main/java/org/linphone/contacts/ContactsManager.kt index 710a46dc9..ef51c63e4 100644 --- a/app/src/main/java/org/linphone/contacts/ContactsManager.kt +++ b/app/src/main/java/org/linphone/contacts/ContactsManager.kt @@ -25,7 +25,6 @@ import android.content.Context import android.content.pm.PackageManager import android.database.Cursor import android.graphics.Bitmap -import android.graphics.BitmapFactory import android.net.Uri import android.provider.ContactsContract import androidx.annotation.UiThread @@ -47,6 +46,7 @@ import org.linphone.ui.main.MainActivity import org.linphone.ui.main.contacts.model.ContactNumberOrAddressClickListener import org.linphone.ui.main.contacts.model.ContactNumberOrAddressModel import org.linphone.ui.main.model.isInSecureMode +import org.linphone.utils.ImageUtils import org.linphone.utils.LinphoneUtils import org.linphone.utils.PhoneNumberUtils @@ -304,12 +304,7 @@ class ContactsManager @UiThread constructor(context: Context) { val personBuilder = Person.Builder().setName(name) val photo = account?.params?.pictureUri.orEmpty() - val bm: Bitmap? = if (photo.isNotEmpty()) { - BitmapFactory.decodeFile(photo) - } else { - null - } - + val bm = ImageUtils.getBitmap(coreContext.context, photo) personBuilder.setIcon( if (bm == null) { coreContext.contactsManager.contactAvatar @@ -329,16 +324,16 @@ class ContactsManager @UiThread constructor(context: Context) { } } +@WorkerThread +fun Friend.getAvatarBitmap(): Bitmap? { + return ImageUtils.getBitmap(coreContext.context, photo) +} + @WorkerThread fun Friend.getPerson(): Person { val personBuilder = Person.Builder().setName(name) - val bm: Bitmap? = if (!photo.isNullOrEmpty()) { - BitmapFactory.decodeFile(photo) - } else { - null - } - + val bm: Bitmap? = getAvatarBitmap() personBuilder.setIcon( if (bm == null) { coreContext.contactsManager.contactAvatar diff --git a/app/src/main/java/org/linphone/notifications/NotificationsManager.kt b/app/src/main/java/org/linphone/notifications/NotificationsManager.kt index 7a9f7c9ea..fa99d64d5 100644 --- a/app/src/main/java/org/linphone/notifications/NotificationsManager.kt +++ b/app/src/main/java/org/linphone/notifications/NotificationsManager.kt @@ -30,7 +30,6 @@ import android.content.Intent import android.content.pm.PackageManager import android.content.pm.ServiceInfo import android.graphics.Bitmap -import android.graphics.BitmapFactory import android.net.Uri import androidx.annotation.AnyThread import androidx.annotation.MainThread @@ -42,10 +41,10 @@ import androidx.core.app.Person import androidx.core.app.RemoteInput import androidx.core.content.ContextCompat import androidx.core.content.LocusIdCompat -import androidx.core.graphics.drawable.IconCompat import org.linphone.LinphoneApplication.Companion.coreContext import org.linphone.LinphoneApplication.Companion.corePreferences import org.linphone.R +import org.linphone.contacts.getAvatarBitmap import org.linphone.contacts.getPerson import org.linphone.core.Address import org.linphone.core.Call @@ -488,12 +487,6 @@ class NotificationsManager @MainThread constructor(private val context: Context) val contact = coreContext.contactsManager.findContactByAddress(address) - val contactPicture = contact?.photo - val roundPicture = if (!contactPicture.isNullOrEmpty()) { - BitmapFactory.decodeFile(contactPicture) - } else { - null - } val displayName = contact?.name ?: LinphoneUtils.getDisplayName(address) val originalMessage = getTextDescribingMessage(message) @@ -508,7 +501,6 @@ class NotificationsManager @MainThread constructor(private val context: Context) contact, displayName, message.time, - senderAvatar = roundPicture, isOutgoing = false, isReaction = true, reactionToMessageId = message.messageId, @@ -590,12 +582,6 @@ class NotificationsManager @MainThread constructor(private val context: Context) private fun getNotifiableForChatMessage(message: ChatMessage): NotifiableMessage { val contact = coreContext.contactsManager.findContactByAddress(message.fromAddress) - val contactPicture = contact?.photo - val roundPicture = if (!contactPicture.isNullOrEmpty()) { - BitmapFactory.decodeFile(contactPicture) - } else { - null - } val displayName = contact?.name ?: LinphoneUtils.getDisplayName(message.fromAddress) val text = getTextDescribingMessage(message) @@ -604,7 +590,6 @@ class NotificationsManager @MainThread constructor(private val context: Context) contact, displayName, message.time * 1000, /* Linphone timestamps are in seconds */ - senderAvatar = roundPicture, isOutgoing = message.isOutgoing ) @@ -648,15 +633,9 @@ class NotificationsManager @MainThread constructor(private val context: Context) val contact = coreContext.contactsManager.findContactByAddress(call.remoteAddress) - val contactPicture = contact?.photo - val roundPicture = if (!contactPicture.isNullOrEmpty()) { - BitmapFactory.decodeFile(contactPicture) - } else { - null - } val displayName = contact?.name ?: LinphoneUtils.getDisplayName(call.remoteAddress) - val person = getPerson(contact, displayName, roundPicture) + val person = getPerson(contact, displayName) val caller = Person.Builder() .setName(person.name) .setIcon(person.icon) @@ -743,12 +722,12 @@ class NotificationsManager @MainThread constructor(private val context: Context) var lastPerson: Person? = null for (message in notifiable.messages) { val friend = message.friend - val person = getPerson(friend, message.sender, message.senderAvatar) + val person = getPerson(friend, message.sender) if (!message.isOutgoing) { // We don't want to see our own avatar lastPerson = person - lastPersonAvatar = message.senderAvatar + lastPersonAvatar = friend?.getAvatarBitmap() if (allPersons.find { it.key == person.key } == null) { allPersons.add(person) @@ -797,6 +776,8 @@ class NotificationsManager @MainThread constructor(private val context: Context) notificationBuilder.addPerson(person) } + // TODO FIXME: shortcuts! + return notificationBuilder.build() } @@ -957,17 +938,11 @@ class NotificationsManager @MainThread constructor(private val context: Context) } @WorkerThread - private fun getPerson(friend: Friend?, displayName: String, picture: Bitmap?): Person { + private fun getPerson(friend: Friend?, displayName: String): Person { return friend?.getPerson() ?: Person.Builder() .setName(displayName) - .setIcon( - if (picture != null) { - IconCompat.createWithAdaptiveBitmap(picture) - } else { - coreContext.contactsManager.contactAvatar - } - ) + .setIcon(coreContext.contactsManager.contactAvatar) .setKey(displayName) .build() } @@ -1013,7 +988,6 @@ class NotificationsManager @MainThread constructor(private val context: Context) channel.enableLights(true) channel.enableVibration(true) channel.setShowBadge(true) - channel.setAllowBubbles(false) notificationManager.createNotificationChannel(channel) } @@ -1071,7 +1045,6 @@ class NotificationsManager @MainThread constructor(private val context: Context) val friend: Friend?, val sender: String, val time: Long, - val senderAvatar: Bitmap? = null, var filePath: Uri? = null, var fileMime: String? = null, val isOutgoing: Boolean = false, diff --git a/app/src/main/java/org/linphone/utils/ImageUtils.kt b/app/src/main/java/org/linphone/utils/ImageUtils.kt index 7a69cd86b..ac8d18d4a 100644 --- a/app/src/main/java/org/linphone/utils/ImageUtils.kt +++ b/app/src/main/java/org/linphone/utils/ImageUtils.kt @@ -21,14 +21,8 @@ package org.linphone.utils import android.content.Context import android.graphics.Bitmap -import android.graphics.Canvas import android.graphics.ImageDecoder -import android.graphics.Paint -import android.graphics.PorterDuff -import android.graphics.PorterDuffXfermode -import android.graphics.Rect import android.net.Uri -import androidx.annotation.AnyThread import androidx.annotation.WorkerThread import java.io.FileNotFoundException import org.linphone.core.tools.Log @@ -38,58 +32,37 @@ class ImageUtils { private const val TAG = "[Image Utils]" @WorkerThread - fun getRoundBitmapFromUri( + fun getBitmap( context: Context, - fromPictureUri: Uri? + path: String? ): Bitmap? { - var bm: Bitmap? = null - if (fromPictureUri != null) { - bm = try { + Log.d("$TAG Trying to create Bitmap from path [$path]") + if (path != null) { + try { + val fromPictureUri = Uri.parse(path) + if (fromPictureUri == null) { + Log.e("$TAG Failed to parse path [$path] as URI") + return null + } + // We make a copy to ensure Bitmap will be Software and not Hardware, required for shortcuts - ImageDecoder.decodeBitmap( + return ImageDecoder.decodeBitmap( ImageDecoder.createSource(context.contentResolver, fromPictureUri) ).copy( Bitmap.Config.ARGB_8888, true ) } catch (fnfe: FileNotFoundException) { + Log.e("$TAG File [$path] not found: $fnfe") return null } catch (e: Exception) { - Log.e("$TAG Failed to get bitmap from URI [$fromPictureUri]: $e") + Log.e("$TAG Failed to get bitmap using path [$path]: $e") return null } } - if (bm != null) { - val roundBm = getRoundBitmap(bm) - if (roundBm != null) { - bm.recycle() - return roundBm - } - } - return bm - } - @AnyThread - private fun getRoundBitmap(bitmap: Bitmap): Bitmap? { - val output = - Bitmap.createBitmap(bitmap.width, bitmap.height, Bitmap.Config.ARGB_8888) - val canvas = Canvas(output) - val color = -0xbdbdbe - val paint = Paint() - val rect = - Rect(0, 0, bitmap.width, bitmap.height) - paint.isAntiAlias = true - canvas.drawARGB(0, 0, 0, 0) - paint.color = color - canvas.drawCircle( - bitmap.width / 2.toFloat(), - bitmap.height / 2.toFloat(), - bitmap.width / 2.toFloat(), - paint - ) - paint.xfermode = PorterDuffXfermode(PorterDuff.Mode.SRC_IN) - canvas.drawBitmap(bitmap, rect, rect, paint) - return output + Log.e("$TAG Can't get bitmap from null URI") + return null } } }