Skip to content

Commit cf7b3fb

Browse files
Merge branch 'develop' into feat/pin-sfu-id-local-dev
2 parents 8e66fbf + 693f242 commit cf7b3fb

3 files changed

Lines changed: 92 additions & 20 deletions

File tree

stream-video-android-ui-compose/src/main/kotlin/io/getstream/video/android/compose/permission/CallPermissions.kt

Lines changed: 19 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
package io.getstream.video.android.compose.permission
1818

19+
import android.content.Context
1920
import android.os.Build
2021
import androidx.compose.runtime.Composable
2122
import androidx.compose.runtime.LaunchedEffect
@@ -35,14 +36,15 @@ import io.getstream.video.android.core.notifications.internal.telecom.TelecomPer
3536
*
3637
* - android.Manifest.permission.CAMERA
3738
* - android.Manifest.permission.RECORD_AUDIO
39+
* - android.Manifest.permission.BLUETOOTH_CONNECT on Android 12 and above
3840
*
3941
* You can request those permissions by invoking `launchPermissionRequest()` method.
4042
*/
4143
@OptIn(ExperimentalPermissionsApi::class)
4244
@Composable
4345
public fun rememberCallPermissionsState(
4446
call: Call,
45-
permissions: List<String> = getPermissions(),
47+
permissions: List<String> = getDefaultPermissionList(isVideoCall = true),
4648
onPermissionsResult: ((Map<String, Boolean>) -> Unit)? = null,
4749
onAllPermissionsGranted: (suspend () -> Unit)? = null,
4850
): VideoPermissionsState {
@@ -86,8 +88,16 @@ public fun rememberCallPermissionsState(
8688
}
8789

8890
@Composable
89-
private fun getPermissions(): List<String> {
90-
val context = LocalContext.current
91+
internal fun getDefaultPermissionList(isVideoCall: Boolean): List<String> =
92+
getDefaultPermissionList(
93+
context = LocalContext.current,
94+
isVideoCall = isVideoCall,
95+
)
96+
97+
internal fun getDefaultPermissionList(
98+
context: Context,
99+
isVideoCall: Boolean,
100+
): List<String> {
91101
val permissionsList = mutableListOf<String>()
92102
val telecomPermissions = TelecomPermissions()
93103

@@ -100,19 +110,13 @@ private fun getPermissions(): List<String> {
100110
}
101111
}
102112

103-
permissionsList.addAll(
104-
mutableListOf(
105-
android.Manifest.permission.CAMERA,
106-
android.Manifest.permission.RECORD_AUDIO,
107-
),
108-
)
113+
if (isVideoCall) {
114+
permissionsList.add(android.Manifest.permission.CAMERA)
115+
}
116+
permissionsList.add(android.Manifest.permission.RECORD_AUDIO)
109117

110118
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
111-
permissionsList.addAll(
112-
mutableListOf(
113-
android.Manifest.permission.BLUETOOTH_CONNECT,
114-
),
115-
)
119+
permissionsList.add(android.Manifest.permission.BLUETOOTH_CONNECT)
116120
}
117121
return permissionsList
118122
}
@@ -122,6 +126,7 @@ private fun getPermissions(): List<String> {
122126
*
123127
* - android.Manifest.permission.CAMERA
124128
* - android.Manifest.permission.RECORD_AUDIO
129+
* - android.Manifest.permission.BLUETOOTH_CONNECT on Android 12 and above
125130
*/
126131
@Composable
127132
public fun LaunchCallPermissions(

stream-video-android-ui-compose/src/main/kotlin/io/getstream/video/android/compose/ui/components/call/activecall/AudioCallContent.kt

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ import androidx.compose.ui.unit.Dp
3737
import androidx.compose.ui.unit.dp
3838
import androidx.lifecycle.compose.collectAsStateWithLifecycle
3939
import io.getstream.video.android.compose.permission.VideoPermissionsState
40+
import io.getstream.video.android.compose.permission.getDefaultPermissionList
4041
import io.getstream.video.android.compose.permission.rememberCallPermissionsState
4142
import io.getstream.video.android.compose.theme.AudioOnlyCallControlsContentParams
4243
import io.getstream.video.android.compose.theme.AudioOnlyCallDetailsContentParams
@@ -84,9 +85,7 @@ public fun AudioCallContent(
8485
isMicrophoneEnabled: Boolean,
8586
permissions: VideoPermissionsState = rememberCallPermissionsState(
8687
call = call,
87-
permissions = listOf(
88-
android.Manifest.permission.RECORD_AUDIO,
89-
),
88+
permissions = getDefaultPermissionList(isVideoCall = false),
9089
),
9190
onCallAction: (CallAction) -> Unit = { action: CallAction ->
9291
DefaultOnCallActionHandler.onCallAction(call, action)
@@ -165,9 +164,7 @@ public fun AudioOnlyCallContent(
165164
isMicrophoneEnabled: Boolean,
166165
permissions: VideoPermissionsState = rememberCallPermissionsState(
167166
call = call,
168-
permissions = listOf(
169-
android.Manifest.permission.RECORD_AUDIO,
170-
),
167+
permissions = getDefaultPermissionList(isVideoCall = false),
171168
),
172169
isShowingHeader: Boolean = true,
173170
headerContent: (@Composable ColumnScope.() -> Unit)? = null,
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
/*
2+
* Copyright (c) 2014-2026 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.compose.permission
18+
19+
import android.Manifest
20+
import android.os.Build
21+
import com.google.common.truth.Truth.assertThat
22+
import org.junit.Test
23+
import org.junit.runner.RunWith
24+
import org.robolectric.RobolectricTestRunner
25+
import org.robolectric.RuntimeEnvironment
26+
import org.robolectric.annotation.Config
27+
28+
@RunWith(RobolectricTestRunner::class)
29+
internal class CallPermissionsTest {
30+
31+
@Test
32+
@Config(sdk = [Build.VERSION_CODES.S])
33+
fun `audio calls request bluetooth connect permission on Android 12`() {
34+
val permissions = getDefaultPermissionList(
35+
context = RuntimeEnvironment.getApplication(),
36+
isVideoCall = false,
37+
)
38+
39+
assertThat(permissions).containsExactly(
40+
Manifest.permission.RECORD_AUDIO,
41+
Manifest.permission.BLUETOOTH_CONNECT,
42+
).inOrder()
43+
}
44+
45+
@Test
46+
@Config(sdk = [Build.VERSION_CODES.R])
47+
fun `audio calls do not request bluetooth connect permission before Android 12`() {
48+
val permissions = getDefaultPermissionList(
49+
context = RuntimeEnvironment.getApplication(),
50+
isVideoCall = false,
51+
)
52+
53+
assertThat(permissions).containsExactly(Manifest.permission.RECORD_AUDIO)
54+
}
55+
56+
@Test
57+
@Config(sdk = [Build.VERSION_CODES.S])
58+
fun `video calls retain camera and audio permissions`() {
59+
val permissions = getDefaultPermissionList(
60+
context = RuntimeEnvironment.getApplication(),
61+
isVideoCall = true,
62+
)
63+
64+
assertThat(permissions).containsExactly(
65+
Manifest.permission.CAMERA,
66+
Manifest.permission.RECORD_AUDIO,
67+
Manifest.permission.BLUETOOTH_CONNECT,
68+
).inOrder()
69+
}
70+
}

0 commit comments

Comments
 (0)