diff --git a/app/src/main/java/org/linphone/compatibility/Api26Compatibility.kt b/app/src/main/java/org/linphone/compatibility/Api26Compatibility.kt index 43860d978..2f6da50f4 100644 --- a/app/src/main/java/org/linphone/compatibility/Api26Compatibility.kt +++ b/app/src/main/java/org/linphone/compatibility/Api26Compatibility.kt @@ -34,11 +34,13 @@ import android.widget.RemoteViews import androidx.core.app.NotificationCompat import androidx.core.app.NotificationManagerCompat import androidx.core.content.ContextCompat -import org.linphone.LinphoneApplication +import org.linphone.LinphoneApplication.Companion.coreContext +import org.linphone.LinphoneApplication.Companion.corePreferences import org.linphone.R import org.linphone.contact.Contact import org.linphone.core.Call import org.linphone.core.tools.Log +import org.linphone.notifications.Notifiable import org.linphone.notifications.NotificationsManager import org.linphone.telecom.NativeCallWrapper import org.linphone.utils.ImageUtils @@ -134,12 +136,14 @@ class Api26Compatibility { return WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY } - fun createIncomingCallNotificationBuilder( + fun createIncomingCallNotification( context: Context, call: Call, + notifiable: Notifiable, + pendingIntent: PendingIntent, notificationsManager: NotificationsManager - ): NotificationCompat.Builder { - val contact: Contact? = LinphoneApplication.coreContext.contactsManager.findContactByAddress(call.remoteAddress) + ): Notification { + val contact: Contact? = coreContext.contactsManager.findContactByAddress(call.remoteAddress) val pictureUri = contact?.getContactThumbnailPictureUri() val roundPicture = ImageUtils.getRoundBitmapFromUri(context, pictureUri) val displayName = contact?.fullName ?: LinphoneUtils.getDisplayName(call.remoteAddress) @@ -154,7 +158,7 @@ class Api26Compatibility { notificationLayoutHeadsUp.setImageViewBitmap(R.id.caller_picture, roundPicture) } - return NotificationCompat.Builder(context, context.getString(R.string.notification_channel_incoming_call_id)) + val builder = NotificationCompat.Builder(context, context.getString(R.string.notification_channel_incoming_call_id)) .setStyle(NotificationCompat.DecoratedCustomViewStyle()) .addPerson(notificationsManager.getPerson(contact, displayName, roundPicture)) .setSmallIcon(R.drawable.topbar_call_notification) @@ -168,7 +172,16 @@ class Api26Compatibility { .setShowWhen(true) .setOngoing(true) .setColor(ContextCompat.getColor(context, R.color.primary_color)) + .setFullScreenIntent(pendingIntent, true) + .addAction(notificationsManager.getCallDeclineAction(notifiable)) + .addAction(notificationsManager.getCallAnswerAction(notifiable)) .setCustomHeadsUpContentView(notificationLayoutHeadsUp) + + if (!corePreferences.preventInterfaceFromShowingUp) { + builder.setContentIntent(pendingIntent) + } + + return builder.build() } @SuppressLint("MissingPermission") diff --git a/app/src/main/java/org/linphone/compatibility/Api31Compatibility.kt b/app/src/main/java/org/linphone/compatibility/Api31Compatibility.kt index a1c454e70..c5ab3b1e0 100644 --- a/app/src/main/java/org/linphone/compatibility/Api31Compatibility.kt +++ b/app/src/main/java/org/linphone/compatibility/Api31Compatibility.kt @@ -20,7 +20,20 @@ package org.linphone.compatibility import android.annotation.TargetApi +import android.app.Notification import android.app.PendingIntent +import android.app.Person +import android.content.Context +import androidx.core.content.ContextCompat +import org.linphone.LinphoneApplication.Companion.coreContext +import org.linphone.LinphoneApplication.Companion.corePreferences +import org.linphone.R +import org.linphone.contact.Contact +import org.linphone.core.Call +import org.linphone.notifications.Notifiable +import org.linphone.notifications.NotificationsManager +import org.linphone.utils.ImageUtils +import org.linphone.utils.LinphoneUtils @TargetApi(31) class Api31Compatibility { @@ -28,5 +41,47 @@ class Api31Compatibility { fun getUpdateCurrentPendingIntentFlag(): Int { return PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_MUTABLE } + + fun createIncomingCallNotification( + context: Context, + call: Call, + notifiable: Notifiable, + pendingIntent: PendingIntent, + notificationsManager: NotificationsManager + ): Notification { + val contact: Contact? = coreContext.contactsManager.findContactByAddress(call.remoteAddress) + val pictureUri = contact?.getContactThumbnailPictureUri() + val roundPicture = ImageUtils.getRoundBitmapFromUri(context, pictureUri) + val displayName = contact?.fullName ?: LinphoneUtils.getDisplayName(call.remoteAddress) + + val person = notificationsManager.getPerson(contact, displayName, roundPicture) + val caller = Person.Builder() + .setName(person.name) + .setIcon(person.icon?.toIcon(context)) + .setUri(person.uri) + .setKey(person.key) + .setImportant(person.isImportant) + .build() + val declineIntent = notificationsManager.getCallDeclinePendingIntent(notifiable) + val answerIntent = notificationsManager.getCallAnswerPendingIntent(notifiable) + val builder = Notification.Builder(context, context.getString(R.string.notification_channel_incoming_call_id)) + .setStyle(Notification.CallStyle.forIncomingCall(caller, declineIntent, answerIntent)) + .setSmallIcon(R.drawable.topbar_call_notification) + .setCategory(Notification.CATEGORY_CALL) + .setVisibility(Notification.VISIBILITY_PUBLIC) + .setPriority(Notification.PRIORITY_HIGH) + .setWhen(System.currentTimeMillis()) + .setAutoCancel(false) + .setShowWhen(true) + .setOngoing(true) + .setColor(ContextCompat.getColor(context, R.color.primary_color)) + .setFullScreenIntent(pendingIntent, true) + + if (!corePreferences.preventInterfaceFromShowingUp) { + builder.setContentIntent(pendingIntent) + } + + return builder.build() + } } } diff --git a/app/src/main/java/org/linphone/compatibility/Compatibility.kt b/app/src/main/java/org/linphone/compatibility/Compatibility.kt index d149e0d0b..db62fba0b 100644 --- a/app/src/main/java/org/linphone/compatibility/Compatibility.kt +++ b/app/src/main/java/org/linphone/compatibility/Compatibility.kt @@ -20,6 +20,8 @@ package org.linphone.compatibility import android.app.Activity +import android.app.Notification +import android.app.PendingIntent import android.content.Context import android.content.Intent import android.content.pm.PackageManager @@ -30,7 +32,6 @@ import android.os.Vibrator import android.telephony.TelephonyManager import android.view.View import android.view.WindowManager -import androidx.core.app.NotificationCompat import androidx.core.app.NotificationManagerCompat import androidx.fragment.app.Fragment import java.util.* @@ -38,6 +39,7 @@ import org.linphone.core.Call import org.linphone.core.ChatRoom import org.linphone.core.Content import org.linphone.mediastream.Version +import org.linphone.notifications.Notifiable import org.linphone.notifications.NotificationsManager import org.linphone.telecom.NativeCallWrapper @@ -170,15 +172,19 @@ class Compatibility { return WindowManager.LayoutParams.TYPE_PHONE } - fun createIncomingCallNotificationBuilder( + fun createIncomingCallNotification( context: Context, call: Call, + notifiable: Notifiable, + pendingIntent: PendingIntent, notificationsManager: NotificationsManager - ): NotificationCompat.Builder { - if (Build.MANUFACTURER.lowercase(Locale.getDefault()) == "xiaomi") { - return XiaomiCompatibility.createIncomingCallNotificationBuilder(context, call, notificationsManager) + ): Notification { + if (Version.sdkAboveOrEqual(Version.API31_ANDROID_12)) { + return Api31Compatibility.createIncomingCallNotification(context, call, notifiable, pendingIntent, notificationsManager) + } else if (Build.MANUFACTURER.lowercase(Locale.getDefault()) == "xiaomi") { + return XiaomiCompatibility.createIncomingCallNotification(context, call, notifiable, pendingIntent, notificationsManager) } - return Api26Compatibility.createIncomingCallNotificationBuilder(context, call, notificationsManager) + return Api26Compatibility.createIncomingCallNotification(context, call, notifiable, pendingIntent, notificationsManager) } /* Call */ diff --git a/app/src/main/java/org/linphone/compatibility/XiaomiCompatibility.kt b/app/src/main/java/org/linphone/compatibility/XiaomiCompatibility.kt index baced6f4f..05b6a482c 100644 --- a/app/src/main/java/org/linphone/compatibility/XiaomiCompatibility.kt +++ b/app/src/main/java/org/linphone/compatibility/XiaomiCompatibility.kt @@ -25,10 +25,12 @@ import android.content.Context import android.graphics.BitmapFactory import androidx.core.app.NotificationCompat import androidx.core.content.ContextCompat -import org.linphone.LinphoneApplication +import org.linphone.LinphoneApplication.Companion.coreContext +import org.linphone.LinphoneApplication.Companion.corePreferences import org.linphone.R import org.linphone.contact.Contact import org.linphone.core.Call +import org.linphone.notifications.Notifiable import org.linphone.notifications.NotificationsManager import org.linphone.utils.ImageUtils import org.linphone.utils.LinphoneUtils @@ -36,18 +38,20 @@ import org.linphone.utils.LinphoneUtils @TargetApi(26) class XiaomiCompatibility { companion object { - fun createIncomingCallNotificationBuilder( + fun createIncomingCallNotification( context: Context, call: Call, + notifiable: Notifiable, + pendingIntent: PendingIntent, notificationsManager: NotificationsManager - ): NotificationCompat.Builder { - val contact: Contact? = LinphoneApplication.coreContext.contactsManager.findContactByAddress(call.remoteAddress) + ): Notification { + val contact: Contact? = coreContext.contactsManager.findContactByAddress(call.remoteAddress) val pictureUri = contact?.getContactThumbnailPictureUri() val roundPicture = ImageUtils.getRoundBitmapFromUri(context, pictureUri) val displayName = contact?.fullName ?: LinphoneUtils.getDisplayName(call.remoteAddress) val address = LinphoneUtils.getDisplayableAddress(call.remoteAddress) - return NotificationCompat.Builder(context, context.getString(R.string.notification_channel_incoming_call_id)) + val builder = NotificationCompat.Builder(context, context.getString(R.string.notification_channel_incoming_call_id)) .addPerson(notificationsManager.getPerson(contact, displayName, roundPicture)) .setSmallIcon(R.drawable.topbar_call_notification) .setLargeIcon(roundPicture ?: BitmapFactory.decodeResource(context.resources, R.drawable.avatar)) @@ -62,6 +66,15 @@ class XiaomiCompatibility { .setShowWhen(true) .setOngoing(true) .setColor(ContextCompat.getColor(context, R.color.primary_color)) + .setFullScreenIntent(pendingIntent, true) + .addAction(notificationsManager.getCallDeclineAction(notifiable)) + .addAction(notificationsManager.getCallAnswerAction(notifiable)) + + if (!corePreferences.preventInterfaceFromShowingUp) { + builder.setContentIntent(pendingIntent) + } + + return builder.build() } } } diff --git a/app/src/main/java/org/linphone/notifications/NotificationsManager.kt b/app/src/main/java/org/linphone/notifications/NotificationsManager.kt index c6ca1f0ec..94bca1ff6 100644 --- a/app/src/main/java/org/linphone/notifications/NotificationsManager.kt +++ b/app/src/main/java/org/linphone/notifications/NotificationsManager.kt @@ -55,7 +55,7 @@ import org.linphone.utils.FileUtils import org.linphone.utils.ImageUtils import org.linphone.utils.LinphoneUtils -private class Notifiable(val notificationId: Int) { +class Notifiable(val notificationId: Int) { val messages: ArrayList = arrayListOf() var isGroup: Boolean = false @@ -66,7 +66,7 @@ private class Notifiable(val notificationId: Int) { var dismissNotificationUponReadChatRoom: Boolean = true } -private class NotifiableMessage( +class NotifiableMessage( var message: String, val contact: Contact?, val sender: String, @@ -433,17 +433,7 @@ class NotificationsManager(private val context: Context) { PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE ) - val builder = Compatibility.createIncomingCallNotificationBuilder(context, call, this) - builder - .setFullScreenIntent(pendingIntent, true) - .addAction(getCallDeclineAction(notifiable)) - .addAction(getCallAnswerAction(notifiable)) - - if (!corePreferences.preventInterfaceFromShowingUp) { - builder.setContentIntent(pendingIntent) - } - - val notification = builder.build() + val notification = Compatibility.createIncomingCallNotification(context, call, notifiable, pendingIntent, this) Log.i("[Notifications Manager] Notifying incoming call notification [${notifiable.notificationId}]") notify(notifiable.notificationId, notification) @@ -851,43 +841,47 @@ class NotificationsManager(private val context: Context) { /* Notifications actions */ - private fun getCallAnswerAction(notifiable: Notifiable): NotificationCompat.Action { + fun getCallAnswerPendingIntent(notifiable: Notifiable): PendingIntent { val answerIntent = Intent(context, NotificationBroadcastReceiver::class.java) answerIntent.action = INTENT_ANSWER_CALL_NOTIF_ACTION answerIntent.putExtra(INTENT_NOTIF_ID, notifiable.notificationId) answerIntent.putExtra(INTENT_REMOTE_ADDRESS, notifiable.remoteAddress) - val answerPendingIntent = PendingIntent.getBroadcast( + return PendingIntent.getBroadcast( context, notifiable.notificationId, answerIntent, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE ) + } + fun getCallAnswerAction(notifiable: Notifiable): NotificationCompat.Action { return NotificationCompat.Action.Builder( R.drawable.call_audio_start, context.getString(R.string.incoming_call_notification_answer_action_label), - answerPendingIntent + getCallAnswerPendingIntent(notifiable) ).build() } - private fun getCallDeclineAction(notifiable: Notifiable): NotificationCompat.Action { + fun getCallDeclinePendingIntent(notifiable: Notifiable): PendingIntent { val hangupIntent = Intent(context, NotificationBroadcastReceiver::class.java) hangupIntent.action = INTENT_HANGUP_CALL_NOTIF_ACTION hangupIntent.putExtra(INTENT_NOTIF_ID, notifiable.notificationId) hangupIntent.putExtra(INTENT_REMOTE_ADDRESS, notifiable.remoteAddress) - val hangupPendingIntent = PendingIntent.getBroadcast( + return PendingIntent.getBroadcast( context, notifiable.notificationId, hangupIntent, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE ) + } + fun getCallDeclineAction(notifiable: Notifiable): NotificationCompat.Action { return NotificationCompat.Action.Builder( R.drawable.call_hangup, context.getString(R.string.incoming_call_notification_hangup_action_label), - hangupPendingIntent + getCallDeclinePendingIntent(notifiable) ).build() }