diff --git a/app/src/main/java/org/linphone/contacts/ContactsManager.kt b/app/src/main/java/org/linphone/contacts/ContactsManager.kt index ed90d4e67..16a5b53a9 100644 --- a/app/src/main/java/org/linphone/contacts/ContactsManager.kt +++ b/app/src/main/java/org/linphone/contacts/ContactsManager.kt @@ -19,9 +19,7 @@ */ package org.linphone.contacts -import android.Manifest import android.content.ContentUris -import android.content.pm.PackageManager import android.graphics.Bitmap import android.net.Uri import android.os.Bundle @@ -29,7 +27,6 @@ import android.provider.ContactsContract import androidx.annotation.MainThread import androidx.annotation.UiThread import androidx.annotation.WorkerThread -import androidx.core.app.ActivityCompat import androidx.core.app.Person import androidx.core.graphics.drawable.IconCompat import androidx.core.text.isDigitsOnly @@ -390,8 +387,9 @@ class ContactsManager notifyContactsListChanged() - Log.i("$TAG Native contacts have been loaded, creating chat rooms shortcuts") - ShortcutUtils.createShortcutsToChatRooms(coreContext.context) + Log.i("$TAG Native contacts have been loaded") + // No longer create chat room shortcuts depending on most recents ones, create it when a message is sent or received instead + // ShortcutUtils.createShortcutsToChatRooms(coreContext.context) } @WorkerThread @@ -572,14 +570,16 @@ class ContactsManager } val context = coreContext.context - if (ActivityCompat.checkSelfPermission( + ShortcutUtils.removeLegacyShortcuts(context) + // No longer create chat room shortcuts depending on most recents ones, create it when a message is sent or received instead + /*if (ActivityCompat.checkSelfPermission( context, Manifest.permission.READ_CONTACTS ) != PackageManager.PERMISSION_GRANTED ) { - Log.w("$TAG READ_CONTACTS permission was denied, creating chat rooms shortcuts") + Log.w("$TAG READ_CONTACTS permission was denied, creating chat rooms shortcuts now") ShortcutUtils.createShortcutsToChatRooms(context) - } + }*/ for (list in core.friendsLists) { if (list.type == FriendList.Type.CardDAV && !list.uri.isNullOrEmpty()) { diff --git a/app/src/main/java/org/linphone/notifications/NotificationsManager.kt b/app/src/main/java/org/linphone/notifications/NotificationsManager.kt index dd20cbbcc..79476bcec 100644 --- a/app/src/main/java/org/linphone/notifications/NotificationsManager.kt +++ b/app/src/main/java/org/linphone/notifications/NotificationsManager.kt @@ -318,6 +318,11 @@ class NotificationsManager Log.i("$TAG Received ${messages.size} aggregated messages") if (corePreferences.disableChat) return + if (!ShortcutUtils.isShortcutToChatRoomAlreadyCreated(context, chatRoom)) { + Log.i("$TAG A message was received in a chat room for which there is no dynamic shortcut, let's create it") + ShortcutUtils.createDynamicShortcutToChatRoom(context, chatRoom) + } + val id = LinphoneUtils.getConversationId(chatRoom) if (currentlyDisplayedChatRoomId.isNotEmpty() && id == currentlyDisplayedChatRoomId) { Log.i( @@ -342,15 +347,14 @@ class NotificationsManager return } - if (ShortcutUtils.isShortcutToChatRoomAlreadyCreated(context, chatRoom)) { - Log.i("$TAG Conversation shortcut already exists") - showChatRoomNotification(chatRoom, messages) - } else { - Log.i( - "$TAG Ensure conversation shortcut exists for notification" - ) - ShortcutUtils.createShortcutsToChatRooms(context) - showChatRoomNotification(chatRoom, messages) + showChatRoomNotification(chatRoom, messages) + } + + @WorkerThread + override fun onMessageSent(core: Core, chatRoom: ChatRoom, message: ChatMessage) { + if (!ShortcutUtils.isShortcutToChatRoomAlreadyCreated(context, chatRoom)) { + Log.i("$TAG A message was sent in a chat room for which there is no dynamic shortcut, let's create it") + ShortcutUtils.createDynamicShortcutToChatRoom(context, chatRoom) } } diff --git a/app/src/main/java/org/linphone/utils/ShortcutUtils.kt b/app/src/main/java/org/linphone/utils/ShortcutUtils.kt index 381a1baef..70fcd14dd 100644 --- a/app/src/main/java/org/linphone/utils/ShortcutUtils.kt +++ b/app/src/main/java/org/linphone/utils/ShortcutUtils.kt @@ -51,6 +51,40 @@ class ShortcutUtils { ShortcutManagerCompat.removeLongLivedShortcuts(coreContext.context, arrayListOf(id)) } + @WorkerThread + fun removeLegacyShortcuts(context: Context) { + val dynamicShortcutsToRemove = arrayListOf() + for (shortcut in ShortcutManagerCompat.getDynamicShortcuts(context)) { + val id = shortcut.id + Log.d("$TAG Found dynamic shortcut with ID [$id]") + if (id.contains("#~#")) { + Log.w("$TAG Found legacy dynamic shortcut with ID [$id] detected, removing it") + dynamicShortcutsToRemove.add(id) + } + } + if (dynamicShortcutsToRemove.isNotEmpty()) { + ShortcutManagerCompat.removeDynamicShortcuts(context, dynamicShortcutsToRemove) + } + + // Check for non-dynamic cached legacy shortcuts + // Warning: on Android >= 10 dynamic shortcuts will still be returned! + val flags = ShortcutManagerCompat.FLAG_MATCH_MANIFEST or ShortcutManagerCompat.FLAG_MATCH_PINNED or ShortcutManagerCompat.FLAG_MATCH_CACHED + val cachedShortcutsToRemove = arrayListOf() + for (shortcut in ShortcutManagerCompat.getShortcuts(context, flags)) { + val id = shortcut.id + val dynamic = shortcut.isDynamic + val cached = shortcut.isCached + if (!dynamic && cached && id.contains("#~#")) { + Log.i("$TAG Found cached legacy shortcut with ID [$id], removing it") + cachedShortcutsToRemove.add(id) + } + } + if (cachedShortcutsToRemove.isNotEmpty()) { + ShortcutManagerCompat.removeLongLivedShortcuts(context, cachedShortcutsToRemove) + } + } + + /* @WorkerThread fun createShortcutsToChatRooms(context: Context) { if (ShortcutManagerCompat.isRateLimitingActive(context)) { @@ -100,11 +134,26 @@ class ShortcutUtils { } Log.i("$TAG Created $count dynamic shortcuts") } + */ + + @WorkerThread + fun createDynamicShortcutToChatRoom(context: Context, chatRoom: ChatRoom) { + val shortcut: ShortcutInfoCompat? = createChatRoomShortcut(context, chatRoom) + if (shortcut != null) { + Log.i("$TAG Created dynamic shortcut for ${shortcut.shortLabel}, pushing it") + try { + ShortcutManagerCompat.pushDynamicShortcut(context, shortcut) + } catch (e: Exception) { + Log.e("$TAG Failed to push dynamic shortcut for ${shortcut.shortLabel}: $e") + } + } + } @WorkerThread private fun createChatRoomShortcut(context: Context, chatRoom: ChatRoom): ShortcutInfoCompat? { val peerAddress = chatRoom.peerAddress val id = LinphoneUtils.getConversationId(chatRoom) + Log.i("$TAG Creating dynamic shortcut for chat room [$id]") try { val categories: ArraySet = ArraySet() @@ -112,6 +161,7 @@ class ShortcutUtils { val personsList = arrayListOf() val subject: String + var isGroup = false val icon: IconCompat = if (chatRoom.hasCapability( ChatRoom.Capabilities.Basic.toInt() ) @@ -141,6 +191,7 @@ class ShortcutUtils { AppUtils.getInitials(subject) ).buildIcon() } else { + isGroup = true subject = chatRoom.subject.orEmpty() AvatarGenerator(context).setInitials(AppUtils.getInitials(subject)).buildIcon() } @@ -157,15 +208,25 @@ class ShortcutUtils { intent.putExtra(ARGUMENTS_CHAT, true) intent.putExtra(ARGUMENTS_CONVERSATION_ID, id) - return ShortcutInfoCompat.Builder(context, id) + val builder = ShortcutInfoCompat.Builder(context, id) .setShortLabel(subject) .setIcon(icon) .setPersons(persons) .setCategories(categories) .setIntent(intent) + .setIsConversation() .setLongLived(Version.sdkAboveOrEqual(Version.API30_ANDROID_11)) .setLocusId(LocusIdCompat(id)) - .build() + // See https://developer.android.com/training/sharing/direct-share-targets#track-shortcut-usage-comms-apps + if (isGroup) { + builder.addCapabilityBinding("actions.intent.SEND_MESSAGE", "message.recipient.@type", listOf("Audience")) + builder.addCapabilityBinding("actions.intent.RECEIVE_MESSAGE", "message.sender.@type", listOf("Audience")) + } else { + builder.addCapabilityBinding("actions.intent.SEND_MESSAGE") + builder.addCapabilityBinding("actions.intent.RECEIVE_MESSAGE") + } + + return builder.build() } catch (e: NumberFormatException) { Log.e("$TAG createChatRoomShortcut for id [$id] exception: $e") } @@ -179,6 +240,7 @@ class ShortcutUtils { val found = ShortcutManagerCompat.getDynamicShortcuts(context).find { it.id == id } + Log.d("$TAG Dynamic shortcut for chat room with ID [$id] ${if (found != null) "exists" else "doesn't exists"}") return found != null } }