davidliu
Committed by GitHub

Permissions cleanup (#12)

* bringing in audio/video perms into sdk and documentation

* Update README.md
@@ -67,6 +67,11 @@ class MainActivity : AppCompatActivity(), RoomListener { @@ -67,6 +67,11 @@ class MainActivity : AppCompatActivity(), RoomListener {
67 } 67 }
68 ``` 68 ```
69 69
  70 +### Permissions
  71 +
  72 +LiveKit relies on the `RECORD_AUDIO` and `CAMERA` permissions to use the microphone and camera.
  73 +These permission must be requested at runtime. Reference the [sample app](https://github.com/livekit/client-sdk-android/blob/4e76e36e0d9f895c718bd41809ab5ff6c57aabd4/sample-app-compose/src/main/java/io/livekit/android/composesample/MainActivity.kt#L134) for an example.
  74 +
70 ## Dev Environment 75 ## Dev Environment
71 76
72 To develop the Android SDK itself, you'll need: 77 To develop the Android SDK itself, you'll need:
@@ -51,7 +51,7 @@ ext { @@ -51,7 +51,7 @@ ext {
51 minVersion : 21, 51 minVersion : 21,
52 ] 52 ]
53 versions = [ 53 versions = [
54 - androidx_core : "1.2.0", 54 + androidx_core : "1.6.0",
55 androidx_lifecycle: "2.3.1", 55 androidx_lifecycle: "2.3.1",
56 dagger : "2.27", 56 dagger : "2.27",
57 groupie : "2.9.0", 57 groupie : "2.9.0",
@@ -101,6 +101,8 @@ dependencies { @@ -101,6 +101,8 @@ dependencies {
101 implementation 'org.jetbrains.kotlinx:kotlinx-serialization-json:1.1.0' 101 implementation 'org.jetbrains.kotlinx:kotlinx-serialization-json:1.1.0'
102 api 'com.github.webrtc-sdk:android:92.4515.01' 102 api 'com.github.webrtc-sdk:android:92.4515.01'
103 api "com.squareup.okhttp3:okhttp:4.9.0" 103 api "com.squareup.okhttp3:okhttp:4.9.0"
  104 + implementation "androidx.annotation:annotation:1.2.0"
  105 + implementation "androidx.core:core:${versions.androidx_core}"
104 implementation "com.google.protobuf:protobuf-java:${versions.protobuf}" 106 implementation "com.google.protobuf:protobuf-java:${versions.protobuf}"
105 implementation "com.google.protobuf:protobuf-java-util:${versions.protobuf}" 107 implementation "com.google.protobuf:protobuf-java-util:${versions.protobuf}"
106 108
@@ -3,4 +3,7 @@ @@ -3,4 +3,7 @@
3 3
4 <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> 4 <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
5 <uses-permission android:name="android.permission.INTERNET" /> 5 <uses-permission android:name="android.permission.INTERNET" />
  6 + <uses-permission android:name="android.permission.RECORD_AUDIO" />
  7 + <uses-permission android:name="android.permission.CAMERA" />
  8 +
6 </manifest> 9 </manifest>
1 package io.livekit.android.room.participant 1 package io.livekit.android.room.participant
2 2
  3 +import android.Manifest
3 import android.content.Context 4 import android.content.Context
4 import android.media.MediaCodecInfo 5 import android.media.MediaCodecInfo
  6 +import androidx.annotation.RequiresPermission
5 import com.google.protobuf.ByteString 7 import com.google.protobuf.ByteString
6 import dagger.assisted.Assisted 8 import dagger.assisted.Assisted
7 import dagger.assisted.AssistedFactory 9 import dagger.assisted.AssistedFactory
@@ -32,6 +34,11 @@ internal constructor( @@ -32,6 +34,11 @@ internal constructor(
32 private val localTrackPublications 34 private val localTrackPublications
33 get() = tracks.values.toList() 35 get() = tracks.values.toList()
34 36
  37 + /**
  38 + * Creates an audio track, recording audio through the microphone with the given [options].
  39 + *
  40 + * @exception SecurityException will be thrown if [Manifest.permission.RECORD_AUDIO] permission is missing.
  41 + */
35 fun createAudioTrack( 42 fun createAudioTrack(
36 name: String = "", 43 name: String = "",
37 options: LocalAudioTrackOptions = LocalAudioTrackOptions(), 44 options: LocalAudioTrackOptions = LocalAudioTrackOptions(),
@@ -45,9 +52,14 @@ internal constructor( @@ -45,9 +52,14 @@ internal constructor(
45 MediaConstraints.KeyValuePair("googTypingNoiseDetection", options.typingNoiseDetection.toString()), 52 MediaConstraints.KeyValuePair("googTypingNoiseDetection", options.typingNoiseDetection.toString()),
46 ) 53 )
47 audioConstraints.optional.addAll(items) 54 audioConstraints.optional.addAll(items)
48 - return LocalAudioTrack.createTrack(peerConnectionFactory, audioConstraints, name) 55 + return LocalAudioTrack.createTrack(context, peerConnectionFactory, audioConstraints, name)
49 } 56 }
50 57
  58 + /**
  59 + * Creates a video track, recording video through the camera with the given [options].
  60 + *
  61 + * @exception SecurityException will be thrown if [Manifest.permission.CAMERA] permission is missing.
  62 + */
51 fun createVideoTrack( 63 fun createVideoTrack(
52 name: String = "", 64 name: String = "",
53 options: LocalVideoTrackOptions = LocalVideoTrackOptions(), 65 options: LocalVideoTrackOptions = LocalVideoTrackOptions(),
1 package io.livekit.android.room.track 1 package io.livekit.android.room.track
2 2
  3 +import android.Manifest
  4 +import android.content.Context
  5 +import android.content.pm.PackageManager
  6 +import androidx.core.content.ContextCompat
3 import org.webrtc.MediaConstraints 7 import org.webrtc.MediaConstraints
4 import org.webrtc.PeerConnectionFactory 8 import org.webrtc.PeerConnectionFactory
5 import org.webrtc.RtpSender 9 import org.webrtc.RtpSender
@@ -27,10 +31,17 @@ class LocalAudioTrack( @@ -27,10 +31,17 @@ class LocalAudioTrack(
27 31
28 companion object { 32 companion object {
29 internal fun createTrack( 33 internal fun createTrack(
  34 + context: Context,
30 factory: PeerConnectionFactory, 35 factory: PeerConnectionFactory,
31 audioConstraints: MediaConstraints = MediaConstraints(), 36 audioConstraints: MediaConstraints = MediaConstraints(),
32 name: String = "" 37 name: String = ""
33 ): LocalAudioTrack { 38 ): LocalAudioTrack {
  39 + if (ContextCompat.checkSelfPermission(context, Manifest.permission.RECORD_AUDIO) !=
  40 + PackageManager.PERMISSION_GRANTED
  41 + ) {
  42 + throw SecurityException("Record audio permissions are required to create an audio track.")
  43 + }
  44 +
34 val audioSource = factory.createAudioSource(audioConstraints) 45 val audioSource = factory.createAudioSource(audioConstraints)
35 val rtcAudioTrack = 46 val rtcAudioTrack =
36 factory.createAudioTrack(UUID.randomUUID().toString(), audioSource) 47 factory.createAudioTrack(UUID.randomUUID().toString(), audioSource)
1 package io.livekit.android.room.track 1 package io.livekit.android.room.track
2 2
  3 +import android.Manifest
3 import android.content.Context 4 import android.content.Context
  5 +import android.content.pm.PackageManager
  6 +import androidx.core.content.ContextCompat
4 import io.livekit.android.util.LKLog 7 import io.livekit.android.util.LKLog
5 import org.webrtc.* 8 import org.webrtc.*
6 import java.util.* 9 import java.util.*
@@ -83,6 +86,7 @@ class LocalVideoTrack( @@ -83,6 +86,7 @@ class LocalVideoTrack(
83 } 86 }
84 87
85 companion object { 88 companion object {
  89 +
86 internal fun createTrack( 90 internal fun createTrack(
87 peerConnectionFactory: PeerConnectionFactory, 91 peerConnectionFactory: PeerConnectionFactory,
88 context: Context, 92 context: Context,
@@ -90,6 +94,13 @@ class LocalVideoTrack( @@ -90,6 +94,13 @@ class LocalVideoTrack(
90 options: LocalVideoTrackOptions, 94 options: LocalVideoTrackOptions,
91 rootEglBase: EglBase, 95 rootEglBase: EglBase,
92 ): LocalVideoTrack { 96 ): LocalVideoTrack {
  97 +
  98 + if (ContextCompat.checkSelfPermission(context, Manifest.permission.CAMERA) !=
  99 + PackageManager.PERMISSION_GRANTED
  100 + ) {
  101 + throw SecurityException("Camera permissions are required to create a camera video track.")
  102 + }
  103 +
93 val source = peerConnectionFactory.createVideoSource(options.isScreencast) 104 val source = peerConnectionFactory.createVideoSource(options.isScreencast)
94 val capturer = createVideoCapturer(context, options.position) ?: TODO() 105 val capturer = createVideoCapturer(context, options.position) ?: TODO()
95 capturer.initialize( 106 capturer.initialize(
@@ -52,7 +52,7 @@ dependencies { @@ -52,7 +52,7 @@ dependencies {
52 implementation fileTree(dir: 'libs', include: ['*.jar']) 52 implementation fileTree(dir: 'libs', include: ['*.jar'])
53 implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" 53 implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
54 implementation deps.kotlinx_coroutines 54 implementation deps.kotlinx_coroutines
55 - implementation 'androidx.core:core-ktx:1.6.0' 55 + implementation "androidx.core:core-ktx:${versions.androidx_core}"
56 implementation 'androidx.appcompat:appcompat:1.3.1' 56 implementation 'androidx.appcompat:appcompat:1.3.1'
57 implementation 'com.google.android.material:material:1.4.0' 57 implementation 'com.google.android.material:material:1.4.0'
58 implementation "androidx.compose.ui:ui:$compose_version" 58 implementation "androidx.compose.ui:ui:$compose_version"
@@ -5,8 +5,6 @@ @@ -5,8 +5,6 @@
5 <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> 5 <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
6 <uses-permission android:name="android.permission.INTERNET" /> 6 <uses-permission android:name="android.permission.INTERNET" />
7 <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" /> 7 <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
8 - <uses-permission android:name="android.permission.RECORD_AUDIO" />  
9 - <uses-permission android:name="android.permission.CAMERA" />  
10 8
11 <application 9 <application
12 android:allowBackup="true" 10 android:allowBackup="true"
@@ -38,7 +38,7 @@ dependencies { @@ -38,7 +38,7 @@ dependencies {
38 implementation deps.kotlinx_coroutines 38 implementation deps.kotlinx_coroutines
39 implementation 'com.google.android.material:material:1.3.0' 39 implementation 'com.google.android.material:material:1.3.0'
40 implementation 'androidx.appcompat:appcompat:1.2.0' 40 implementation 'androidx.appcompat:appcompat:1.2.0'
41 - implementation 'androidx.core:core-ktx:1.3.2' 41 + implementation "androidx.core:core-ktx:${versions.androidx_core}"
42 implementation "androidx.activity:activity-ktx:1.2.2" 42 implementation "androidx.activity:activity-ktx:1.2.2"
43 implementation 'androidx.fragment:fragment-ktx:1.3.2' 43 implementation 'androidx.fragment:fragment-ktx:1.3.2'
44 implementation 'androidx.preference:preference:1.1.1' 44 implementation 'androidx.preference:preference:1.1.1'
@@ -4,8 +4,6 @@ @@ -4,8 +4,6 @@
4 <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> 4 <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
5 <uses-permission android:name="android.permission.INTERNET" /> 5 <uses-permission android:name="android.permission.INTERNET" />
6 <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" /> 6 <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
7 - <uses-permission android:name="android.permission.RECORD_AUDIO" />  
8 - <uses-permission android:name="android.permission.CAMERA" />  
9 7
10 <application 8 <application
11 android:name=".SampleApplication" 9 android:name=".SampleApplication"