From afa3b44e8623f235472b3dc536f08b554ebe58f8 Mon Sep 17 00:00:00 2001 From: Liviu Timar <65943217+liviu-timar@users.noreply.github.com> Date: Wed, 8 Nov 2023 18:22:20 +0200 Subject: [PATCH 1/3] Add and handle new call.cancelled notification type --- .../io/getstream/video/android/DirectCallActivity.kt | 2 +- .../core/notifications/DefaultNotificationHandler.kt | 4 ++++ .../android/core/notifications/NotificationHandler.kt | 1 + .../core/notifications/internal/NoOpNotificationHandler.kt | 1 + .../core/notifications/internal/VideoPushDelegate.kt | 7 +++++++ 5 files changed, 14 insertions(+), 1 deletion(-) diff --git a/demo-app/src/main/kotlin/io/getstream/video/android/DirectCallActivity.kt b/demo-app/src/main/kotlin/io/getstream/video/android/DirectCallActivity.kt index c2d0393b34..473f1fadd1 100644 --- a/demo-app/src/main/kotlin/io/getstream/video/android/DirectCallActivity.kt +++ b/demo-app/src/main/kotlin/io/getstream/video/android/DirectCallActivity.kt @@ -76,7 +76,7 @@ class DirectCallActivity : ComponentActivity() { val call = StreamVideo.instance().call(type, id) // Get list of members - val members: List = intent.getStringArrayExtra(EXTRA_MEMBERS_ARRAY)?.asList() ?: emptyList() + val members: List = listOf("XPU1WRE9") // You must add yourself as member too val membersWithMe = members.toMutableList().apply { add(call.user.id) } 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 8acb208b7b..9c7d0902cf 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 @@ -152,6 +152,10 @@ public open class DefaultNotificationHandler( .build() } + override fun onCallCancelled(callId: StreamCallId) { + notificationManager.cancel(INCOMING_CALL_NOTIFICATION_ID) + } + private fun maybeCreateChannel(channelId: String, context: Context) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { val channel = NotificationChannel( diff --git a/stream-video-android-core/src/main/kotlin/io/getstream/video/android/core/notifications/NotificationHandler.kt b/stream-video-android-core/src/main/kotlin/io/getstream/video/android/core/notifications/NotificationHandler.kt index d8a16935b4..030338f7ef 100644 --- a/stream-video-android-core/src/main/kotlin/io/getstream/video/android/core/notifications/NotificationHandler.kt +++ b/stream-video-android-core/src/main/kotlin/io/getstream/video/android/core/notifications/NotificationHandler.kt @@ -25,6 +25,7 @@ public interface NotificationHandler : NotificationPermissionHandler { fun onNotification(callId: StreamCallId, callDisplayName: String) fun onLiveCall(callId: StreamCallId, callDisplayName: String) fun getOngoingCallNotification(callId: StreamCallId): Notification? + fun onCallCancelled(callId: StreamCallId) companion object { const val ACTION_NOTIFICATION = "io.getstream.video.android.action.NOTIFICATION" 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 1ad0860482..dcaf08323d 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 @@ -25,6 +25,7 @@ internal object NoOpNotificationHandler : NotificationHandler { override fun onNotification(callId: StreamCallId, callDisplayName: String) { /* NoOp */ } override fun onLiveCall(callId: StreamCallId, callDisplayName: String) { /* NoOp */ } override fun getOngoingCallNotification(callId: StreamCallId): Notification? = null + override fun onCallCancelled(callId: StreamCallId) { /* NoOp */ } override fun onPermissionDenied() { /* NoOp */ } override fun onPermissionGranted() { /* NoOp */ } override fun onPermissionRationale() { /* NoOp */ } diff --git a/stream-video-android-core/src/main/kotlin/io/getstream/video/android/core/notifications/internal/VideoPushDelegate.kt b/stream-video-android-core/src/main/kotlin/io/getstream/video/android/core/notifications/internal/VideoPushDelegate.kt index 6406d07880..13d72702e1 100644 --- a/stream-video-android-core/src/main/kotlin/io/getstream/video/android/core/notifications/internal/VideoPushDelegate.kt +++ b/stream-video-android-core/src/main/kotlin/io/getstream/video/android/core/notifications/internal/VideoPushDelegate.kt @@ -59,6 +59,7 @@ internal class VideoPushDelegate( KEY_TYPE_RING -> handleRingType(callId, payload) KEY_TYPE_NOTIFICATION -> handleNotificationType(callId, payload) KEY_TYPE_LIVE_STARTED -> handleLiveStartedType(callId, payload) + KEY_TYPE_CANCELLED -> handleCallCancelledType(callId, payload) } } } @@ -79,6 +80,10 @@ internal class VideoPushDelegate( getStreamVideo("live-started-notification")?.onLiveCall(callId, callDisplayName) } + private fun handleCallCancelledType(callId: StreamCallId, payload: Map) { + getStreamVideo("call-cancelled-notification")?.onCallCancelled(callId) + } + /** * Register a push device in our servers. * @@ -135,6 +140,7 @@ internal class VideoPushDelegate( KEY_TYPE_RING -> isValidRingType() KEY_TYPE_NOTIFICATION -> isValidNotificationType() KEY_TYPE_LIVE_STARTED -> isValidLiveStarted() + KEY_TYPE_CANCELLED -> true else -> false } @@ -180,6 +186,7 @@ internal class VideoPushDelegate( private const val KEY_TYPE_RING = "call.ring" private const val KEY_TYPE_NOTIFICATION = "call.notification" private const val KEY_TYPE_LIVE_STARTED = "call.live_started" + private const val KEY_TYPE_CANCELLED = "call.cancelled" private const val KEY_CALL_CID = "call_cid" private const val KEY_CALL_DISPLAY_NAME = "call_display_name" private const val KEY_CREATED_BY_DISPLAY_NAME = "created_by_display_name" From 476793aa802a5e93e6501ad49e27edb9ce09353d Mon Sep 17 00:00:00 2001 From: Liviu Timar <65943217+liviu-timar@users.noreply.github.com> Date: Thu, 9 Nov 2023 11:23:15 +0200 Subject: [PATCH 2/3] Rename ring to direct call in VideoPushDelegate --- .../internal/VideoPushDelegate.kt | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/stream-video-android-core/src/main/kotlin/io/getstream/video/android/core/notifications/internal/VideoPushDelegate.kt b/stream-video-android-core/src/main/kotlin/io/getstream/video/android/core/notifications/internal/VideoPushDelegate.kt index 13d72702e1..cb63636a3b 100644 --- a/stream-video-android-core/src/main/kotlin/io/getstream/video/android/core/notifications/internal/VideoPushDelegate.kt +++ b/stream-video-android-core/src/main/kotlin/io/getstream/video/android/core/notifications/internal/VideoPushDelegate.kt @@ -56,16 +56,16 @@ internal class VideoPushDelegate( .let { StreamCallId(it.first, it.second) } CoroutineScope(DispatcherProvider.IO).launch { when (payload[KEY_TYPE]) { - KEY_TYPE_RING -> handleRingType(callId, payload) + KEY_TYPE_DIRECT_CALL -> handleDirectCallType(callId, payload) KEY_TYPE_NOTIFICATION -> handleNotificationType(callId, payload) KEY_TYPE_LIVE_STARTED -> handleLiveStartedType(callId, payload) - KEY_TYPE_CANCELLED -> handleCallCancelledType(callId, payload) + KEY_TYPE_DIRECT_CALL_CANCELLED -> handleDirectCallCancelledType(callId, payload) } } } } - private suspend fun handleRingType(callId: StreamCallId, payload: Map) { + private suspend fun handleDirectCallType(callId: StreamCallId, payload: Map) { val callDisplayName = (payload[KEY_CREATED_BY_DISPLAY_NAME] as String).ifEmpty { DEFAULT_CALL_TEXT } getStreamVideo("ring-type-notification")?.onRingingCall(callId, callDisplayName) } @@ -80,7 +80,7 @@ internal class VideoPushDelegate( getStreamVideo("live-started-notification")?.onLiveCall(callId, callDisplayName) } - private fun handleCallCancelledType(callId: StreamCallId, payload: Map) { + private fun handleDirectCallCancelledType(callId: StreamCallId, payload: Map) { getStreamVideo("call-cancelled-notification")?.onCallCancelled(callId) } @@ -137,17 +137,17 @@ internal class VideoPushDelegate( * Verify if the map contains a known type. */ private fun Map.containsKnownType(): Boolean = when (this[KEY_TYPE]) { - KEY_TYPE_RING -> isValidRingType() + KEY_TYPE_DIRECT_CALL -> isValidDirectCallType() KEY_TYPE_NOTIFICATION -> isValidNotificationType() KEY_TYPE_LIVE_STARTED -> isValidLiveStarted() - KEY_TYPE_CANCELLED -> true + KEY_TYPE_DIRECT_CALL_CANCELLED -> true else -> false } /** * Verify if the map contains all keys/values for a Ring Type. */ - private fun Map.isValidRingType(): Boolean = + private fun Map.isValidDirectCallType(): Boolean = // TODO: KEY_CALL_DISPLAY_NAME can be empty. Are there any other important key/values? // !(this[KEY_CALL_DISPLAY_NAME] as? String).isNullOrBlank() true @@ -183,10 +183,10 @@ internal class VideoPushDelegate( private companion object { private const val KEY_SENDER = "sender" private const val KEY_TYPE = "type" - private const val KEY_TYPE_RING = "call.ring" + private const val KEY_TYPE_DIRECT_CALL = "call.ring" private const val KEY_TYPE_NOTIFICATION = "call.notification" private const val KEY_TYPE_LIVE_STARTED = "call.live_started" - private const val KEY_TYPE_CANCELLED = "call.cancelled" + private const val KEY_TYPE_DIRECT_CALL_CANCELLED = "call.direct_call_cancelled" private const val KEY_CALL_CID = "call_cid" private const val KEY_CALL_DISPLAY_NAME = "call_display_name" private const val KEY_CREATED_BY_DISPLAY_NAME = "created_by_display_name" From 66b1b3274b0141c3ed92929880bb7ef4c58c5ffc Mon Sep 17 00:00:00 2001 From: Liviu Timar <65943217+liviu-timar@users.noreply.github.com> Date: Thu, 9 Nov 2023 11:25:26 +0200 Subject: [PATCH 3/3] Clean up --- .../kotlin/io/getstream/video/android/DirectCallActivity.kt | 2 +- .../core/notifications/internal/VideoPushDelegate.kt | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/demo-app/src/main/kotlin/io/getstream/video/android/DirectCallActivity.kt b/demo-app/src/main/kotlin/io/getstream/video/android/DirectCallActivity.kt index 473f1fadd1..c2d0393b34 100644 --- a/demo-app/src/main/kotlin/io/getstream/video/android/DirectCallActivity.kt +++ b/demo-app/src/main/kotlin/io/getstream/video/android/DirectCallActivity.kt @@ -76,7 +76,7 @@ class DirectCallActivity : ComponentActivity() { val call = StreamVideo.instance().call(type, id) // Get list of members - val members: List = listOf("XPU1WRE9") + val members: List = intent.getStringArrayExtra(EXTRA_MEMBERS_ARRAY)?.asList() ?: emptyList() // You must add yourself as member too val membersWithMe = members.toMutableList().apply { add(call.user.id) } diff --git a/stream-video-android-core/src/main/kotlin/io/getstream/video/android/core/notifications/internal/VideoPushDelegate.kt b/stream-video-android-core/src/main/kotlin/io/getstream/video/android/core/notifications/internal/VideoPushDelegate.kt index cb63636a3b..247c8d9391 100644 --- a/stream-video-android-core/src/main/kotlin/io/getstream/video/android/core/notifications/internal/VideoPushDelegate.kt +++ b/stream-video-android-core/src/main/kotlin/io/getstream/video/android/core/notifications/internal/VideoPushDelegate.kt @@ -65,17 +65,17 @@ internal class VideoPushDelegate( } } - private suspend fun handleDirectCallType(callId: StreamCallId, payload: Map) { + private fun handleDirectCallType(callId: StreamCallId, payload: Map) { val callDisplayName = (payload[KEY_CREATED_BY_DISPLAY_NAME] as String).ifEmpty { DEFAULT_CALL_TEXT } getStreamVideo("ring-type-notification")?.onRingingCall(callId, callDisplayName) } - private suspend fun handleNotificationType(callId: StreamCallId, payload: Map) { + private fun handleNotificationType(callId: StreamCallId, payload: Map) { val callDisplayName = (payload[KEY_CREATED_BY_DISPLAY_NAME] as String).ifEmpty { DEFAULT_CALL_TEXT } getStreamVideo("generic-notification")?.onNotification(callId, callDisplayName) } - private suspend fun handleLiveStartedType(callId: StreamCallId, payload: Map) { + private fun handleLiveStartedType(callId: StreamCallId, payload: Map) { val callDisplayName = (payload[KEY_CREATED_BY_DISPLAY_NAME] as String).ifEmpty { DEFAULT_CALL_TEXT } getStreamVideo("live-started-notification")?.onLiveCall(callId, callDisplayName) }