MainActivity.kt
3.9 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
package io.livekit.android.sample.basic
import android.Manifest
import android.content.pm.PackageManager
import android.os.Build
import android.os.Bundle
import android.view.View
import android.widget.Toast
import androidx.activity.result.contract.ActivityResultContracts
import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.ContextCompat
import androidx.lifecycle.lifecycleScope
import io.livekit.android.LiveKit
import io.livekit.android.events.RoomEvent
import io.livekit.android.events.collect
import io.livekit.android.renderer.SurfaceViewRenderer
import io.livekit.android.room.Room
import io.livekit.android.room.track.VideoTrack
import kotlinx.coroutines.launch
class MainActivity : AppCompatActivity() {
lateinit var room: Room
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
// Create Room object.
room = LiveKit.create(applicationContext)
// Setup the video renderer
room.initVideoRenderer(findViewById<SurfaceViewRenderer>(R.id.renderer))
requestNeededPermissions { connectToRoom() }
}
private fun connectToRoom() {
val url = "wss://your_host"
val token = "your_token"
lifecycleScope.launch {
// Setup event handling.
launch {
room.events.collect { event ->
when (event) {
is RoomEvent.TrackSubscribed -> onTrackSubscribed(event)
else -> {}
}
}
}
// Connect to server.
room.connect(
url,
token,
)
// Turn on audio/video recording.
val localParticipant = room.localParticipant
localParticipant.setMicrophoneEnabled(true)
localParticipant.setCameraEnabled(true)
}
}
private fun onTrackSubscribed(event: RoomEvent.TrackSubscribed) {
val track = event.track
if (track is VideoTrack) {
attachVideo(track)
}
}
private fun attachVideo(videoTrack: VideoTrack) {
videoTrack.addRenderer(findViewById<SurfaceViewRenderer>(R.id.renderer))
findViewById<View>(R.id.progress).visibility = View.GONE
}
private fun requestNeededPermissions(onHasPermissions: () -> Unit) {
val requestPermissionLauncher =
registerForActivityResult(ActivityResultContracts.RequestMultiplePermissions()) { grants ->
var hasDenied = false
// Check if any permissions weren't granted.
for (grant in grants.entries) {
if (!grant.value) {
Toast.makeText(this, "Missing permission: ${grant.key}", Toast.LENGTH_SHORT).show()
hasDenied = true
}
}
if (!hasDenied) {
onHasPermissions()
}
}
// Assemble the needed permissions to request
val neededPermissions = listOf(Manifest.permission.RECORD_AUDIO, Manifest.permission.CAMERA)
.let { perms ->
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
// Need BLUETOOTH_CONNECT permission on API S+ to output to bluetooth devices.
perms + listOf(Manifest.permission.BLUETOOTH_CONNECT)
} else {
perms
}
}
.filter { ContextCompat.checkSelfPermission(this, it) == PackageManager.PERMISSION_DENIED }
.toTypedArray()
if (neededPermissions.isNotEmpty()) {
requestPermissionLauncher.launch(neededPermissions)
} else {
onHasPermissions()
}
}
override fun onDestroy() {
super.onDestroy()
room.disconnect()
}
}