diff --git a/stream-video-android-core/api/stream-video-android-core.api b/stream-video-android-core/api/stream-video-android-core.api index 67412f54a4..3c6dc19f9f 100644 --- a/stream-video-android-core/api/stream-video-android-core.api +++ b/stream-video-android-core/api/stream-video-android-core.api @@ -13189,6 +13189,7 @@ public class io/getstream/video/android/core/notifications/DefaultNotificationHa public fun getRejectAction (Landroid/app/PendingIntent;)Landroidx/core/app/NotificationCompat$Action; public fun getRingingCallNotification (Lio/getstream/video/android/core/RingingState;Lio/getstream/video/android/model/StreamCallId;Ljava/lang/String;ZLjava/util/Map;)Landroid/app/Notification; public fun getSettingUpCallNotification ()Landroid/app/Notification; + public fun getSettingUpCallNotification (Ljava/lang/String;Lio/getstream/video/android/model/StreamCallId;)Landroid/app/Notification; public fun getStreamNotificationDispatcher ()Lio/getstream/video/android/core/notifications/dispatchers/NotificationDispatcher; public fun isInForeground ()Z public fun maybeCreateChannel (Ljava/lang/String;Landroid/content/Context;Lkotlin/jvm/functions/Function1;)V @@ -13441,6 +13442,7 @@ public class io/getstream/video/android/core/notifications/handlers/StreamDefaul public fun getOngoingCallNotification (Lio/getstream/video/android/model/StreamCallId;Ljava/lang/String;ZILjava/util/Map;)Landroid/app/Notification; public fun getRingingCallNotification (Lio/getstream/video/android/core/RingingState;Lio/getstream/video/android/model/StreamCallId;Ljava/lang/String;ZLjava/util/Map;)Landroid/app/Notification; public fun getSettingUpCallNotification ()Landroid/app/Notification; + public fun getSettingUpCallNotification (Ljava/lang/String;Lio/getstream/video/android/model/StreamCallId;)Landroid/app/Notification; public fun onCallNotificationUpdate (Lio/getstream/video/android/core/Call;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; public fun onLiveCall (Lio/getstream/video/android/model/StreamCallId;Ljava/lang/String;Ljava/util/Map;)V public fun onMissedCall (Lio/getstream/video/android/model/StreamCallId;Ljava/lang/String;Ljava/util/Map;)V @@ -13544,7 +13546,7 @@ public abstract interface class io/getstream/video/android/core/notifications/ha public abstract fun onRingingCall (Lio/getstream/video/android/model/StreamCallId;Ljava/lang/String;Ljava/util/Map;)V } -public abstract interface class io/getstream/video/android/core/notifications/handlers/StreamNotificationProvider : io/getstream/video/android/core/notifications/handlers/StreamNotificationProviderWithPayload { +public abstract interface class io/getstream/video/android/core/notifications/handlers/StreamNotificationProvider : io/getstream/video/android/core/notifications/handlers/StreamNotificationProviderWithPayload, io/getstream/video/android/core/notifications/handlers/StreamSettingUpCallNotificationProvider { public fun getIncomingCallNotification (Landroid/app/PendingIntent;Landroid/app/PendingIntent;Landroid/app/PendingIntent;Ljava/lang/String;Z)Landroid/app/Notification; public fun getMissedCallNotification (Lio/getstream/video/android/model/StreamCallId;Ljava/lang/String;)Landroid/app/Notification; public static synthetic fun getMissedCallNotification$default (Lio/getstream/video/android/core/notifications/handlers/StreamNotificationProvider;Lio/getstream/video/android/model/StreamCallId;Ljava/lang/String;ILjava/lang/Object;)Landroid/app/Notification; @@ -13552,7 +13554,8 @@ public abstract interface class io/getstream/video/android/core/notifications/ha public static synthetic fun getOngoingCallNotification$default (Lio/getstream/video/android/core/notifications/handlers/StreamNotificationProvider;Lio/getstream/video/android/model/StreamCallId;Ljava/lang/String;ZIILjava/lang/Object;)Landroid/app/Notification; public fun getRingingCallNotification (Lio/getstream/video/android/core/RingingState;Lio/getstream/video/android/model/StreamCallId;Ljava/lang/String;Z)Landroid/app/Notification; public static synthetic fun getRingingCallNotification$default (Lio/getstream/video/android/core/notifications/handlers/StreamNotificationProvider;Lio/getstream/video/android/core/RingingState;Lio/getstream/video/android/model/StreamCallId;Ljava/lang/String;ZILjava/lang/Object;)Landroid/app/Notification; - public abstract fun getSettingUpCallNotification ()Landroid/app/Notification; + public fun getSettingUpCallNotification ()Landroid/app/Notification; + public fun getSettingUpCallNotification (Ljava/lang/String;Lio/getstream/video/android/model/StreamCallId;)Landroid/app/Notification; } public abstract interface class io/getstream/video/android/core/notifications/handlers/StreamNotificationProviderWithPayload { @@ -13589,6 +13592,10 @@ public abstract interface class io/getstream/video/android/core/notifications/ha public abstract fun updateOutgoingCallNotification (Lio/getstream/video/android/core/Call;Ljava/lang/String;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; } +public abstract interface class io/getstream/video/android/core/notifications/handlers/StreamSettingUpCallNotificationProvider { + public abstract fun getSettingUpCallNotification (Ljava/lang/String;Lio/getstream/video/android/model/StreamCallId;)Landroid/app/Notification; +} + public final class io/getstream/video/android/core/notifications/internal/receivers/ToggleCameraBroadcastReceiver : android/content/BroadcastReceiver { public fun (Lkotlinx/coroutines/CoroutineScope;)V public fun onReceive (Landroid/content/Context;Landroid/content/Intent;)V diff --git a/stream-video-android-core/src/main/kotlin/io/getstream/video/android/core/notifications/DefaultNotificationHandler.kt b/stream-video-android-core/src/main/kotlin/io/getstream/video/android/core/notifications/DefaultNotificationHandler.kt index 269298d31a..26fafce4db 100644 --- a/stream-video-android-core/src/main/kotlin/io/getstream/video/android/core/notifications/DefaultNotificationHandler.kt +++ b/stream-video-android-core/src/main/kotlin/io/getstream/video/android/core/notifications/DefaultNotificationHandler.kt @@ -244,6 +244,13 @@ public open class DefaultNotificationHandler( .build() } + @Deprecated( + "Use StreamSettingUpCallNotificationProvider.getSettingUpCallNotification(trigger,callId)", + replaceWith = ReplaceWith( + "StreamSettingUpCallNotificationProvider.getSettingUpCallNotification(trigger,callId)", + ), + level = DeprecationLevel.WARNING, + ) override fun getSettingUpCallNotification(): Notification? { val channelId = application.getString( R.string.stream_video_call_setup_notification_channel_id, @@ -277,6 +284,11 @@ public open class DefaultNotificationHandler( } } + override fun getSettingUpCallNotification( + trigger: String, + callId: StreamCallId, + ): Notification? = getSettingUpCallNotification() + override suspend fun onCallNotificationUpdate(call: Call): Notification? { coroutineScope { val localUser = StreamVideo.instance().state.user.value diff --git a/stream-video-android-core/src/main/kotlin/io/getstream/video/android/core/notifications/handlers/StreamDefaultNotificationHandler.kt b/stream-video-android-core/src/main/kotlin/io/getstream/video/android/core/notifications/handlers/StreamDefaultNotificationHandler.kt index 50eaca304f..579dc1b521 100644 --- a/stream-video-android-core/src/main/kotlin/io/getstream/video/android/core/notifications/handlers/StreamDefaultNotificationHandler.kt +++ b/stream-video-android-core/src/main/kotlin/io/getstream/video/android/core/notifications/handlers/StreamDefaultNotificationHandler.kt @@ -59,6 +59,7 @@ import io.getstream.video.android.core.notifications.StreamIntentResolver import io.getstream.video.android.core.notifications.dispatchers.DefaultNotificationDispatcher import io.getstream.video.android.core.notifications.dispatchers.NotificationDispatcher import io.getstream.video.android.core.notifications.extractor.DefaultNotificationContentExtractor +import io.getstream.video.android.core.notifications.internal.service.CallService.Companion.TRIGGER_INCOMING_CALL import io.getstream.video.android.core.notifications.internal.service.ServiceLauncher import io.getstream.video.android.core.utils.isAppInForeground import io.getstream.video.android.core.utils.safeCall @@ -528,6 +529,13 @@ constructor( } } + @Deprecated( + "Use StreamSettingUpCallNotificationProvider.getSettingUpCallNotification(trigger,callId)", + replaceWith = ReplaceWith( + "StreamSettingUpCallNotificationProvider.getSettingUpCallNotification(trigger,callId)", + ), + level = DeprecationLevel.WARNING, + ) override fun getSettingUpCallNotification(): Notification? { logger.d { "[getSettingUpCallNotification]" } val channelId = notificationChannels.outgoingCallChannel.id @@ -543,6 +551,57 @@ constructor( } } + override fun getSettingUpCallNotification(trigger: String, callId: StreamCallId): Notification? { + return when (trigger) { + /** + * TODO: This logic is duplicated with getIncomingCallNotificationInternal. + * Update it soon + */ + + TRIGGER_INCOMING_CALL -> { + val title = application.getString( + R.string.stream_video_call_setup_notification_title, + ) + val description = + application.getString(R.string.stream_video_call_setup_notification_description) + + val notificationChannel = when { + isAppInForeground() && hideRingingNotificationInForeground -> + notificationChannels.incomingCallLowImportanceChannel + else -> notificationChannels.incomingCallChannel + } + + val fullScreenPendingIntent = intentResolver.searchIncomingCallPendingIntent( + callId, + payload = emptyMap(), + ) + + if (fullScreenPendingIntent == null) { + logger.w { + "[getSettingUpCallNotification] fullScreenPendingIntent is null; lock-screen wake-up may not work." + } + } + return ensureChannelAndBuildNotification(notificationChannel) { + priority = if (hideRingingNotificationInForeground) { + NotificationCompat.PRIORITY_LOW + } else { + NotificationCompat.PRIORITY_MAX + } + setContentTitle(title) + setContentText(description) + setSmallIcon(R.drawable.stream_video_ic_call) + setChannelId(notificationChannel.id) + setOngoing(true) + setCategory(NotificationCompat.CATEGORY_CALL) + setFullScreenIntent(fullScreenPendingIntent, true) + setContentIntent(fullScreenPendingIntent) + } + } + + else -> getSettingUpCallNotification() + } + } + @OptIn(ExperimentalStreamVideoApi::class) private inline fun getOngoingCallNotificationInternal( callId: StreamCallId, diff --git a/stream-video-android-core/src/main/kotlin/io/getstream/video/android/core/notifications/handlers/StreamNotificationHandler.kt b/stream-video-android-core/src/main/kotlin/io/getstream/video/android/core/notifications/handlers/StreamNotificationHandler.kt index 3cee5630f1..efe6908da0 100644 --- a/stream-video-android-core/src/main/kotlin/io/getstream/video/android/core/notifications/handlers/StreamNotificationHandler.kt +++ b/stream-video-android-core/src/main/kotlin/io/getstream/video/android/core/notifications/handlers/StreamNotificationHandler.kt @@ -183,6 +183,10 @@ interface StreamNotificationProviderWithPayload { ): Notification? } +interface StreamSettingUpCallNotificationProvider { + fun getSettingUpCallNotification(trigger: String, callId: StreamCallId): Notification? +} + interface StreamNotificationUpdatesProvider { /** @@ -228,7 +232,7 @@ interface StreamNotificationUpdatesProvider { ): Notification? } -interface StreamNotificationProvider : StreamNotificationProviderWithPayload { +interface StreamNotificationProvider : StreamNotificationProviderWithPayload, StreamSettingUpCallNotificationProvider { /** * Customize the notification when you receive a push notification for ringing call with type [RingingState.Incoming] @@ -348,7 +352,22 @@ interface StreamNotificationProvider : StreamNotificationProviderWithPayload { * * @return A [Notification] object. */ - fun getSettingUpCallNotification(): Notification? + @Deprecated( + "Use StreamSettingUpCallNotificationProvider.getSettingUpCallNotification(trigger,callId)", + replaceWith = ReplaceWith( + "StreamSettingUpCallNotificationProvider.getSettingUpCallNotification(trigger,callId)", + ), + level = DeprecationLevel.WARNING, + ) + fun getSettingUpCallNotification(): Notification? = null + + // Inside StreamNotificationProvider interface, add: + override fun getSettingUpCallNotification( + trigger: String, + callId: StreamCallId, + ): Notification? { + return getSettingUpCallNotification() + } } /** diff --git a/stream-video-android-core/src/main/kotlin/io/getstream/video/android/core/notifications/internal/NoOpNotificationHandler.kt b/stream-video-android-core/src/main/kotlin/io/getstream/video/android/core/notifications/internal/NoOpNotificationHandler.kt index 80b095a59a..f2b05a99da 100644 --- a/stream-video-android-core/src/main/kotlin/io/getstream/video/android/core/notifications/internal/NoOpNotificationHandler.kt +++ b/stream-video-android-core/src/main/kotlin/io/getstream/video/android/core/notifications/internal/NoOpNotificationHandler.kt @@ -115,7 +115,18 @@ internal object NoOpNotificationHandler : NotificationHandler { payload: Map, ): Notification? = null + @Deprecated( + "Use StreamSettingUpCallNotificationProvider.getSettingUpCallNotification(trigger,callId)", + replaceWith = ReplaceWith( + "StreamSettingUpCallNotificationProvider.getSettingUpCallNotification(trigger,callId)", + ), + level = DeprecationLevel.WARNING, + ) override fun getSettingUpCallNotification(): Notification? = null + override fun getSettingUpCallNotification( + trigger: String, + callId: StreamCallId, + ): Notification? = null @Deprecated( level = DeprecationLevel.ERROR, diff --git a/stream-video-android-core/src/main/kotlin/io/getstream/video/android/core/notifications/internal/service/CallService.kt b/stream-video-android-core/src/main/kotlin/io/getstream/video/android/core/notifications/internal/service/CallService.kt index 330183b448..1f7f485e66 100644 --- a/stream-video-android-core/src/main/kotlin/io/getstream/video/android/core/notifications/internal/service/CallService.kt +++ b/stream-video-android-core/src/main/kotlin/io/getstream/video/android/core/notifications/internal/service/CallService.kt @@ -216,7 +216,12 @@ internal open class CallService : Service() { * Mandatory, if not called then it will throw exception if we directly decide to stop the service. * For example: it will stop the service if [verifyPermissions] is false */ - promoteToFgServiceIfNoActiveCall(params.streamVideo, notificationId, params.trigger) + promoteToFgServiceIfNoActiveCall( + params.streamVideo, + notificationId, + params.trigger, + params.callId, + ) val call = params.streamVideo.call(params.callId.type, params.callId.id) // Rendering incoming call does not need audio/video permissions @@ -654,8 +659,9 @@ internal open class CallService : Service() { videoClient: StreamVideoClient, notificationId: Int, trigger: String, + callId: StreamCallId, ) { - videoClient.getSettingUpCallNotification()?.let { notification -> + videoClient.getSettingUpCallNotification(trigger, callId)?.let { notification -> startForegroundWithServiceType( notificationId, notification,