Skip to content

Commit 921c7c8

Browse files
Merge branch 'refs/heads/develop'
2 parents bf571cb + 9d169cc commit 921c7c8

35 files changed

+580
-114
lines changed

buildSrc/src/main/kotlin/io/getstream/video/android/Configuration.kt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,11 @@ object Configuration {
66
const val minSdk = 24
77
const val majorVersion = 1
88
const val minorVersion = 0
9-
const val patchVersion = 15
9+
const val patchVersion = 16
1010
const val versionName = "$majorVersion.$minorVersion.$patchVersion"
1111
const val versionCode = 39
1212
const val snapshotVersionName = "$majorVersion.$minorVersion.${patchVersion + 1}-SNAPSHOT"
1313
const val artifactGroup = "io.getstream"
14-
const val streamVideoCallGooglePlayVersion = "1.1.8"
15-
const val streamWebRtcVersionName = "1.1.1"
14+
const val streamVideoCallGooglePlayVersion = "1.1.9"
15+
const val streamWebRtcVersionName = "1.2.1"
1616
}

demo-app/build.gradle.kts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,9 @@ dependencies {
208208
implementation(project(":stream-video-android-filters-video"))
209209
compileOnly(project(":stream-video-android-previewdata"))
210210

211+
// Noise Cancellation
212+
implementation(libs.stream.video.android.noise.cancellation)
213+
211214
// Stream Chat SDK
212215
implementation(libs.stream.chat.compose)
213216
implementation(libs.stream.chat.offline)

demo-app/src/main/AndroidManifest.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
android:allowBackup="true"
3030
android:icon="@mipmap/ic_launcher"
3131
android:label="@string/app_name"
32+
android:networkSecurityConfig="@xml/network_security_config"
3233
android:roundIcon="@mipmap/ic_launcher_round"
3334
android:supportsRtl="true"
3435
android:theme="@style/Dogfooding"

demo-app/src/main/kotlin/io/getstream/video/android/ui/call/CallScreen.kt

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ import io.getstream.video.android.compose.ui.components.call.renderer.copy
9494
import io.getstream.video.android.core.Call
9595
import io.getstream.video.android.core.RealtimeConnection
9696
import io.getstream.video.android.core.call.state.ChooseLayout
97+
import io.getstream.video.android.core.utils.isEnabled
9798
import io.getstream.video.android.filters.video.BlurredBackgroundVideoFilter
9899
import io.getstream.video.android.filters.video.VirtualBackgroundVideoFilter
99100
import io.getstream.video.android.mock.StreamPreviewDataUtils
@@ -458,10 +459,17 @@ fun CallScreen(
458459
}
459460

460461
if (isShowingSettingMenu) {
462+
var isNoiseCancellationEnabled by remember {
463+
mutableStateOf(call.isAudioProcessingEnabled())
464+
}
465+
val settings by call.state.settings.collectAsStateWithLifecycle()
466+
val noiseCancellationFeatureEnabled = settings?.audio?.noiseCancellation?.isEnabled == true
461467
SettingsMenu(
462468
call = call,
463469
selectedVideoFilter = selectedVideoFilter,
464470
showDebugOptions = showDebugOptions,
471+
noiseCancellationFeatureEnabled = noiseCancellationFeatureEnabled,
472+
noiseCancellationEnabled = isNoiseCancellationEnabled,
465473
onDismissed = { isShowingSettingMenu = false },
466474
onSelectVideoFilter = { filterIndex ->
467475
selectedVideoFilter = filterIndex
@@ -482,6 +490,9 @@ fun CallScreen(
482490
isShowingSettingMenu = false
483491
isShowingFeedbackDialog = true
484492
},
493+
onNoiseCancellation = {
494+
isNoiseCancellationEnabled = call.toggleAudioProcessing()
495+
},
485496
) {
486497
isShowingStats = true
487498
isShowingSettingMenu = false

demo-app/src/main/kotlin/io/getstream/video/android/ui/join/CallJoinViewModel.kt

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -20,23 +20,25 @@ import androidx.lifecycle.ViewModel
2020
import androidx.lifecycle.viewModelScope
2121
import com.google.android.gms.auth.api.signin.GoogleSignInClient
2222
import dagger.hilt.android.lifecycle.HiltViewModel
23+
import io.getstream.android.push.PushProvider
2324
import io.getstream.chat.android.client.ChatClient
2425
import io.getstream.video.android.core.Call
2526
import io.getstream.video.android.core.StreamVideo
2627
import io.getstream.video.android.datastore.delegate.StreamUserDataStore
28+
import io.getstream.video.android.model.Device
2729
import io.getstream.video.android.model.User
2830
import io.getstream.video.android.model.mapper.isValidCallCid
2931
import io.getstream.video.android.model.mapper.toTypeAndId
3032
import io.getstream.video.android.util.NetworkMonitor
3133
import io.getstream.video.android.util.StreamVideoInitHelper
32-
import kotlinx.coroutines.delay
34+
import io.getstream.video.android.util.fcmToken
3335
import kotlinx.coroutines.flow.Flow
3436
import kotlinx.coroutines.flow.MutableSharedFlow
37+
import kotlinx.coroutines.flow.MutableStateFlow
3538
import kotlinx.coroutines.flow.SharedFlow
3639
import kotlinx.coroutines.flow.SharingStarted
3740
import kotlinx.coroutines.flow.flatMapLatest
3841
import kotlinx.coroutines.flow.flowOf
39-
import kotlinx.coroutines.flow.map
4042
import kotlinx.coroutines.flow.shareIn
4143
import kotlinx.coroutines.launch
4244
import java.util.UUID
@@ -49,7 +51,7 @@ class CallJoinViewModel @Inject constructor(
4951
networkMonitor: NetworkMonitor,
5052
) : ViewModel() {
5153
val user: Flow<User?> = dataStore.user
52-
val isLoggedOut = dataStore.user.map { it == null }
54+
val isLoggedOut = MutableStateFlow(false)
5355
var autoLogInAfterLogOut = true
5456
val isNetworkAvailable = networkMonitor.isNetworkAvailable
5557

@@ -101,12 +103,26 @@ class CallJoinViewModel @Inject constructor(
101103

102104
fun logOut() {
103105
viewModelScope.launch {
104-
googleSignInClient.signOut()
105-
dataStore.clear()
106-
StreamVideo.instance().logOut()
107106
ChatClient.instance().disconnect(true).enqueue()
108-
delay(200)
107+
dataStore.clear() // Demo App DataStore
108+
googleSignInClient.signOut()
109+
110+
StreamVideo.instanceOrNull()?.let { streamVideo ->
111+
fcmToken?.let { fcmToken ->
112+
streamVideo.deleteDevice(
113+
Device(
114+
id = fcmToken,
115+
pushProvider = PushProvider.FIREBASE.key,
116+
pushProviderName = "firebase",
117+
),
118+
)
119+
}
120+
streamVideo.logOut()
121+
}
122+
109123
StreamVideo.removeClient()
124+
125+
isLoggedOut.value = true
110126
}
111127
}
112128
}

demo-app/src/main/kotlin/io/getstream/video/android/ui/lobby/CallLobbyViewModel.kt

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import io.getstream.chat.android.client.ChatClient
2626
import io.getstream.video.android.core.Call
2727
import io.getstream.video.android.core.DeviceStatus
2828
import io.getstream.video.android.core.StreamVideo
29+
import io.getstream.video.android.core.utils.isAutoOn
2930
import io.getstream.video.android.datastore.delegate.StreamUserDataStore
3031
import io.getstream.video.android.model.StreamCallId
3132
import io.getstream.video.android.model.User
@@ -116,7 +117,7 @@ class CallLobbyViewModel @Inject constructor(
116117
// based on it
117118
val settings = call.state.settings.first { it != null }
118119

119-
val enabled = when (call.camera.status.first()) {
120+
val isCameraEnabled = when (call.camera.status.first()) {
120121
is DeviceStatus.NotSelected -> {
121122
settings?.video?.cameraDefaultOn ?: false
122123
}
@@ -131,7 +132,10 @@ class CallLobbyViewModel @Inject constructor(
131132
}
132133

133134
// enable/disable camera capture (no preview would be visible otherwise)
134-
call.camera.setEnabled(enabled)
135+
call.camera.setEnabled(isCameraEnabled)
136+
137+
val isNoiseCancellationEnabled = settings?.audio?.noiseCancellation?.isAutoOn ?: false
138+
call.setAudioProcessingEnabled(isNoiseCancellationEnabled)
135139
}
136140
}
137141

demo-app/src/main/kotlin/io/getstream/video/android/ui/menu/MenuDefinitions.kt

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ import androidx.compose.material.icons.filled.HeadsetMic
3030
import androidx.compose.material.icons.filled.PortableWifiOff
3131
import androidx.compose.material.icons.filled.RestartAlt
3232
import androidx.compose.material.icons.filled.SettingsVoice
33+
import androidx.compose.material.icons.filled.SpatialAudioOff
3334
import androidx.compose.material.icons.filled.SpeakerPhone
3435
import androidx.compose.material.icons.filled.SwitchLeft
3536
import androidx.compose.material.icons.filled.VideoFile
@@ -46,6 +47,8 @@ import io.getstream.video.android.ui.menu.base.SubMenuItem
4647
*/
4748
fun defaultStreamMenu(
4849
showDebugOptions: Boolean = false,
50+
noiseCancellationFeatureEnabled: Boolean = false,
51+
noiseCancellationEnabled: Boolean = false,
4952
codecList: List<MediaCodecInfo>,
5053
onCodecSelected: (MediaCodecInfo) -> Unit,
5154
isScreenShareEnabled: Boolean,
@@ -57,6 +60,7 @@ fun defaultStreamMenu(
5760
onKillSfuWsClick: () -> Unit,
5861
onSwitchSfuClick: () -> Unit,
5962
onShowFeedback: () -> Unit,
63+
onNoiseCancellation: () -> Unit,
6064
onDeviceSelected: (StreamAudioDevice) -> Unit,
6165
availableDevices: List<StreamAudioDevice>,
6266
loadRecordings: suspend () -> List<MenuItem>,
@@ -108,6 +112,16 @@ fun defaultStreamMenu(
108112
action = onToggleScreenShare,
109113
),
110114
)
115+
if (noiseCancellationFeatureEnabled) {
116+
add(
117+
ActionMenuItem(
118+
title = "Noise cancellation",
119+
icon = Icons.Default.SpatialAudioOff,
120+
highlight = noiseCancellationEnabled,
121+
action = onNoiseCancellation,
122+
),
123+
)
124+
}
111125
if (showDebugOptions) {
112126
add(
113127
SubMenuItem(

demo-app/src/main/kotlin/io/getstream/video/android/ui/menu/SettingsMenu.kt

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ import com.google.accompanist.permissions.PermissionStatus
5151
import com.google.accompanist.permissions.rememberPermissionState
5252
import io.getstream.video.android.compose.theme.VideoTheme
5353
import io.getstream.video.android.core.Call
54-
import io.getstream.video.android.core.call.audio.AudioFilter
54+
import io.getstream.video.android.core.call.audio.InputAudioFilter
5555
import io.getstream.video.android.core.mapper.ReactionMapper
5656
import io.getstream.video.android.tooling.extensions.toPx
5757
import io.getstream.video.android.ui.call.ReactionsMenu
@@ -68,9 +68,12 @@ internal fun SettingsMenu(
6868
call: Call,
6969
selectedVideoFilter: Int,
7070
showDebugOptions: Boolean,
71+
noiseCancellationFeatureEnabled: Boolean,
72+
noiseCancellationEnabled: Boolean,
7173
onDismissed: () -> Unit,
7274
onSelectVideoFilter: (Int) -> Unit,
7375
onShowFeedback: () -> Unit,
76+
onNoiseCancellation: () -> Unit,
7477
onShowCallStats: () -> Unit,
7578
) {
7679
val context = LocalContext.current
@@ -104,7 +107,7 @@ internal fun SettingsMenu(
104107

105108
val onToggleAudioFilterClick: () -> Unit = {
106109
if (call.audioFilter == null) {
107-
call.audioFilter = object : AudioFilter {
110+
call.audioFilter = object : InputAudioFilter {
108111
override fun applyFilter(
109112
audioFormat: Int,
110113
channelCount: Int,
@@ -206,6 +209,8 @@ internal fun SettingsMenu(
206209
},
207210
items = defaultStreamMenu(
208211
showDebugOptions = showDebugOptions,
212+
noiseCancellationFeatureEnabled = noiseCancellationFeatureEnabled,
213+
noiseCancellationEnabled = noiseCancellationEnabled,
209214
codecList = codecInfos,
210215
availableDevices = availableDevices,
211216
onDeviceSelected = {
@@ -223,6 +228,7 @@ internal fun SettingsMenu(
223228
onToggleAudioFilterClick = onToggleAudioFilterClick,
224229
onSwitchSfuClick = onSwitchSfuClick,
225230
onShowCallStats = onShowCallStats,
231+
onNoiseCancellation = onNoiseCancellation,
226232
isScreenShareEnabled = isScreenSharing,
227233
loadRecordings = onLoadRecordings,
228234
),
@@ -284,6 +290,7 @@ private fun SettingsMenuPreview() {
284290
availableDevices = emptyList(),
285291
onDeviceSelected = {},
286292
onShowFeedback = {},
293+
onNoiseCancellation = {},
287294
loadRecordings = { emptyList() },
288295
),
289296
)

demo-app/src/main/kotlin/io/getstream/video/android/ui/menu/base/DynamicMenu.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,7 @@ private fun DynamicMenuPreview() {
222222
availableDevices = emptyList(),
223223
onDeviceSelected = {},
224224
onShowFeedback = {},
225+
onNoiseCancellation = {},
225226
loadRecordings = { emptyList() },
226227
),
227228
)
@@ -248,6 +249,7 @@ private fun DynamicMenuDebugOptionPreview() {
248249
availableDevices = emptyList(),
249250
onDeviceSelected = {},
250251
onShowFeedback = {},
252+
onNoiseCancellation = {},
251253
loadRecordings = { emptyList() },
252254
),
253255
)
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
/*
2+
* Copyright (c) 2014-2024 Stream.io Inc. All rights reserved.
3+
*
4+
* Licensed under the Stream License;
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://github.com/GetStream/stream-video-android/blob/main/LICENSE
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package io.getstream.video.android.util
18+
19+
import android.util.Log
20+
import com.google.firebase.messaging.FirebaseMessaging
21+
import kotlinx.coroutines.runBlocking
22+
import kotlinx.coroutines.tasks.await
23+
24+
val fcmToken: String?
25+
get() = runBlocking {
26+
try {
27+
FirebaseMessaging.getInstance().token.await()
28+
} catch (e: Exception) {
29+
Log.e("FCM Token", "Failed to retrieve FCM token", e)
30+
null
31+
}
32+
}

0 commit comments

Comments
 (0)