CallActivity.kt
3.8 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
package io.livekit.android.sample
import android.media.AudioManager
import android.os.Bundle
import android.os.Parcelable
import androidx.appcompat.app.AppCompatActivity
import com.github.ajalt.timberkt.Timber
import com.google.android.material.tabs.TabLayoutMediator
import com.snakydesign.livedataextensions.combineLatest
import com.xwray.groupie.GroupieAdapter
import io.livekit.android.room.track.LocalVideoTrack
import io.livekit.android.sample.databinding.CallActivityBinding
import kotlinx.parcelize.Parcelize
class CallActivity : AppCompatActivity() {
val viewModel: CallViewModel by viewModelByFactory {
val args = intent.getParcelableExtra<BundleArgs>(KEY_ARGS)
?: throw NullPointerException("args is null!")
CallViewModel(args.url, args.token, application)
}
lateinit var binding: CallActivityBinding
var tabLayoutMediator: TabLayoutMediator? = null
val focusChangeListener = AudioManager.OnAudioFocusChangeListener {}
private var previousSpeakerphoneOn = true
private var previousMicrophoneMute = false
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = CallActivityBinding.inflate(layoutInflater)
setContentView(binding.root)
// Viewpager setup
val adapter = GroupieAdapter()
binding.viewPager.apply {
this.adapter = adapter
}
combineLatest(
viewModel.room,
viewModel.remoteParticipants
) { room, participants -> room to participants }
.observe(this) {
tabLayoutMediator?.detach()
tabLayoutMediator = null
val (room, participants) = it
val items = participants.map { participant -> ParticipantItem(room, participant) }
adapter.update(items)
tabLayoutMediator =
TabLayoutMediator(binding.tabs, binding.viewPager) { tab, position ->
tab.text = participants[position].identity
}
tabLayoutMediator?.attach()
}
viewModel.room.observe(this) { room ->
room.initVideoRenderer(binding.pipVideoView)
val videoTrack = room.localParticipant.videoTracks.values
.firstOrNull()
?.track as? LocalVideoTrack
videoTrack?.let {
it.addRenderer(binding.pipVideoView)
}
}
val audioManager = getSystemService(AUDIO_SERVICE) as AudioManager
with(audioManager) {
previousSpeakerphoneOn = isSpeakerphoneOn
previousMicrophoneMute = isMicrophoneMute
isSpeakerphoneOn = true
isMicrophoneMute = false
mode = AudioManager.MODE_IN_COMMUNICATION
}
val result = audioManager.requestAudioFocus(
focusChangeListener,
AudioManager.STREAM_VOICE_CALL,
AudioManager.AUDIOFOCUS_GAIN,
)
if (result == AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {
Timber.v { "Audio focus request granted for VOICE_CALL streams" }
} else {
Timber.v { "Audio focus request failed" }
}
}
override fun onDestroy() {
super.onDestroy()
binding.pipVideoView.release()
val audioManager = getSystemService(AUDIO_SERVICE) as AudioManager
with(audioManager) {
isSpeakerphoneOn = previousSpeakerphoneOn
isMicrophoneMute = previousMicrophoneMute
abandonAudioFocus(focusChangeListener)
mode = AudioManager.MODE_NORMAL
}
}
companion object {
const val KEY_ARGS = "args"
}
@Parcelize
data class BundleArgs(val url: String, val token: String) : Parcelable
}