Skip to content

Commit

Permalink
update rtc to 4.3.0
Browse files Browse the repository at this point in the history
  • Loading branch information
AderanFeng committed Apr 12, 2024
1 parent d073da7 commit 43d63f4
Show file tree
Hide file tree
Showing 9 changed files with 230 additions and 138 deletions.
2 changes: 1 addition & 1 deletion app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -273,7 +273,7 @@ dependencies {
implementation "com.github.netless-io:sync-player-android:1.2.1"
}

implementation 'io.agora.rtc:full-sdk:3.7.2.1'
implementation 'io.agora.rtc:full-sdk:4.3.0'
implementation 'com.github.agorabuilder:rtm-sdk:1.4.10'

// Exoplayer
Expand Down
82 changes: 60 additions & 22 deletions app/src/main/java/io/agora/flat/common/rtc/AgoraRtc.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,13 @@ import io.agora.flat.data.AppEnv
import io.agora.flat.di.interfaces.Logger
import io.agora.flat.di.interfaces.RtcApi
import io.agora.flat.di.interfaces.StartupInitializer
import io.agora.rtc.Constants
import io.agora.rtc.IRtcEngineEventHandler
import io.agora.rtc.RtcEngine
import io.agora.rtc.models.ChannelMediaOptions
import io.agora.rtc.video.VideoCanvas
import io.agora.rtc.video.VideoEncoderConfiguration
import io.agora.rtc2.ChannelMediaOptions
import io.agora.rtc2.Constants
import io.agora.rtc2.IRtcEngineEventHandler
import io.agora.rtc2.RtcEngine
import io.agora.rtc2.RtcEngineConfig
import io.agora.rtc2.video.VideoCanvas
import io.agora.rtc2.video.VideoEncoderConfiguration
import kotlinx.coroutines.channels.awaitClose
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.callbackFlow
Expand All @@ -20,11 +21,17 @@ import javax.inject.Singleton
@Singleton
class AgoraRtc @Inject constructor(val appEnv: AppEnv, val logger: Logger) : RtcApi, StartupInitializer {
private lateinit var rtcEngine: RtcEngine
private val mHandler: RTCEventHandler = RTCEventHandler()
private val eventHandler: RTCEventHandler = RTCEventHandler()
private var currentUid = 0

override fun init(context: Context) {
try {
rtcEngine = RtcEngine.create(context, appEnv.agoraAppId, mHandler)
val config = RtcEngineConfig().apply {
mContext = context
mAppId = appEnv.agoraAppId
mEventHandler = eventHandler
}
rtcEngine = RtcEngine.create(config)
// rtcEngine.setLogFile(FileUtil.initializeLogFile(this))
} catch (e: Exception) {
e.printStackTrace()
Expand All @@ -44,21 +51,30 @@ class AgoraRtc @Inject constructor(val appEnv: AppEnv, val logger: Logger) : Rtc
)
)
rtcEngine.adjustRecordingSignalVolume(200)
rtcEngine.setChannelProfile(Constants.CHANNEL_PROFILE_COMMUNICATION)
}

fun rtcEngine(): RtcEngine {
return rtcEngine
}

override fun joinChannel(options: RtcJoinOptions): Int {
val channelMediaOptions = ChannelMediaOptions()
channelMediaOptions.publishLocalVideo = options.videoOpen
channelMediaOptions.publishLocalAudio = options.audioOpen
return rtcEngine.joinChannel(options.token, options.channel, "{}", options.uid, channelMediaOptions)
currentUid = options.uid
logger.i("[RTC] create media options by state: video=${options.videoOpen}, audio=${options.audioOpen}")
val mediaOptions = ChannelMediaOptions().apply {
clientRoleType =
if (options.videoOpen || options.audioOpen) Constants.CLIENT_ROLE_BROADCASTER else Constants.CLIENT_ROLE_AUDIENCE
publishCameraTrack = options.videoOpen
publishMicrophoneTrack = options.audioOpen
autoSubscribeAudio = true
autoSubscribeVideo = true
}
return rtcEngine.joinChannel(options.token, options.channel, options.uid, mediaOptions)
}

override fun leaveChannel() {
rtcEngine.leaveChannel()
override fun leaveChannel(): Int {
currentUid = 0
return rtcEngine.leaveChannel()
}

override fun enableLocalVideo(enabled: Boolean) {
Expand All @@ -78,9 +94,12 @@ class AgoraRtc @Inject constructor(val appEnv: AppEnv, val logger: Logger) : Rtc
}

override fun updateLocalStream(audio: Boolean, video: Boolean) {
// 使用 enableLocalAudio 关闭或开启本地采集后,本地听远端播放会有短暂中断。
rtcEngine.muteLocalAudioStream(!audio)
rtcEngine.muteLocalVideoStream(!video)
val mediaOptions = ChannelMediaOptions().apply {
clientRoleType = if (audio || video) Constants.CLIENT_ROLE_BROADCASTER else Constants.CLIENT_ROLE_AUDIENCE
publishCameraTrack = video
publishMicrophoneTrack = audio
}
rtcEngine.updateChannelMediaOptions(mediaOptions)
}

override fun updateRemoteStream(rtcUid: Int, audio: Boolean, video: Boolean) {
Expand All @@ -99,8 +118,7 @@ class AgoraRtc @Inject constructor(val appEnv: AppEnv, val logger: Logger) : Rtc
}

override fun onAudioVolumeIndication(
speakers: Array<out IRtcEngineEventHandler.AudioVolumeInfo>,
totalVolume: Int
speakers: Array<out IRtcEngineEventHandler.AudioVolumeInfo>, totalVolume: Int
) {
val info = speakers.map {
AudioVolumeInfo(uid = it.uid, volume = it.volume, vad = it.vad)
Expand All @@ -109,19 +127,39 @@ class AgoraRtc @Inject constructor(val appEnv: AppEnv, val logger: Logger) : Rtc
}

override fun onNetworkQuality(uid: Int, txQuality: Int, rxQuality: Int) {
if (uid == 0) {
if (uid == currentUid) {
trySend(RtcEvent.NetworkStatus(getOverallQuality(txQuality, rxQuality)))
}
}

override fun onRtcStats(stats: IRtcEngineEventHandler.RtcStats) {
trySend(RtcEvent.LastmileDelay(stats.lastmileDelay))
}

override fun onPermissionError(permission: Int) {
logger.e("[RTC] permission error: $permission")
}

override fun onRemoteAudioStateChanged(uid: Int, state: Int, reason: Int, elapsed: Int) {
logger.i("[RTC] remote audio state changed: $uid, $state, $reason, $elapsed")
}

override fun onRemoteVideoStateChanged(uid: Int, state: Int, reason: Int, elapsed: Int) {
logger.i("[RTC] remote video state changed: $uid, $state, $reason, $elapsed")
}

override fun onUserMuteAudio(uid: Int, muted: Boolean) {
logger.i("[RTC] user mute audio: $uid, $muted")
}

override fun onUserMuteVideo(uid: Int, muted: Boolean) {
logger.i("[RTC] user mute video: $uid, $muted")
}
}
mHandler.addListener(listener)
eventHandler.addListener(listener)
awaitClose {
logger.i("[RTC] rtc event flow closed")
mHandler.removeListener(listener)
eventHandler.removeListener(listener)
}
}

Expand Down
60 changes: 56 additions & 4 deletions app/src/main/java/io/agora/flat/common/rtc/Misc.kt
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package io.agora.flat.common.rtc

import io.agora.rtc.IRtcEngineEventHandler
import io.agora.rtc2.Constants
import io.agora.rtc2.IRtcEngineEventHandler

internal class RTCEventHandler : IRtcEngineEventHandler() {
private val listeners = ArrayList<RTCEventListener>()
Expand All @@ -19,12 +20,22 @@ internal class RTCEventHandler : IRtcEngineEventHandler() {
}
}

override fun onRejoinChannelSuccess(channel: String, uid: Int, elapsed: Int) {
for (listener in listeners) {
listener.onRejoinChannelSuccess(channel, uid, elapsed)
}
}

override fun onLeaveChannel(stats: RtcStats) {
for (listener in listeners) {
listener.onLeaveChannel(stats)
}
}

override fun onConnectionStateChanged(state: Int, reason: Int) {
super.onConnectionStateChanged(state, reason)
}

override fun onFirstRemoteVideoDecoded(uid: Int, width: Int, height: Int, elapsed: Int) {
for (listener in listeners) {
listener.onFirstRemoteVideoDecoded(uid, width, height, elapsed)
Expand All @@ -43,7 +54,7 @@ internal class RTCEventHandler : IRtcEngineEventHandler() {
}
}

override fun onLocalVideoStats(stats: LocalVideoStats) {
override fun onLocalVideoStats(source: Constants.VideoSourceType, stats: LocalVideoStats) {
for (listener in listeners) {
listener.onLocalVideoStats(stats)
}
Expand Down Expand Up @@ -90,15 +101,47 @@ internal class RTCEventHandler : IRtcEngineEventHandler() {
listener.onAudioVolumeIndication(speakers, totalVolume)
}
}

override fun onPermissionError(permission: Int) {
for (listener in listeners) {
listener.onPermissionError(permission)
}
}

override fun onRemoteAudioStateChanged(uid: Int, state: Int, reason: Int, elapsed: Int) {
for (listener in listeners) {
listener.onRemoteAudioStateChanged(uid, state, reason, elapsed)
}
}

override fun onRemoteVideoStateChanged(uid: Int, state: Int, reason: Int, elapsed: Int) {
for (listener in listeners) {
listener.onRemoteVideoStateChanged(uid, state, reason, elapsed)
}
}

override fun onUserMuteAudio(uid: Int, muted: Boolean) {
for (listener in listeners) {
listener.onUserMuteAudio(uid, muted)
}
}

override fun onUserMuteVideo(uid: Int, muted: Boolean) {
for (listener in listeners) {
listener.onUserMuteVideo(uid, muted)
}
}
}

internal interface RTCEventListener {
fun onFirstRemoteVideoDecoded(uid: Int, width: Int, height: Int, elapsed: Int) {}

fun onLeaveChannel(stats: IRtcEngineEventHandler.RtcStats?) {}

fun onJoinChannelSuccess(channel: String?, uid: Int, elapsed: Int) {}

fun onRejoinChannelSuccess(channel: String, uid: Int, elapsed: Int) {}

fun onLeaveChannel(stats: IRtcEngineEventHandler.RtcStats?) {}

fun onUserOffline(uid: Int, reason: Int) {}

fun onUserJoined(uid: Int, elapsed: Int) {}
Expand All @@ -118,4 +161,13 @@ internal interface RTCEventListener {
fun onRemoteAudioStats(stats: IRtcEngineEventHandler.RemoteAudioStats) {}

fun onAudioVolumeIndication(speakers: Array<out IRtcEngineEventHandler.AudioVolumeInfo>, totalVolume: Int) {}
fun onPermissionError(permission: Int) {}

fun onRemoteAudioStateChanged(uid: Int, state: Int, reason: Int, elapsed: Int) {}

fun onRemoteVideoStateChanged(uid: Int, state: Int, reason: Int, elapsed: Int) {}

fun onUserMuteAudio(uid: Int, muted: Boolean) {}

fun onUserMuteVideo(uid: Int, muted: Boolean) {}
}
Original file line number Diff line number Diff line change
@@ -1,19 +1,20 @@
package io.agora.flat.ui.viewmodel
package io.agora.flat.common.rtc

import android.view.TextureView
import android.view.View
import android.widget.FrameLayout
import androidx.core.view.isVisible
import dagger.hilt.android.scopes.ActivityRetainedScoped
import io.agora.flat.di.interfaces.RtcApi
import io.agora.rtc.RtcEngine
import io.agora.rtc.video.VideoCanvas
import io.agora.rtc2.video.VideoCanvas
import io.agora.rtc2.RtcEngine
import javax.inject.Inject
import kotlin.collections.set

@ActivityRetainedScoped
class RtcVideoController @Inject constructor(private val rtcApi: RtcApi) {
private var textureMap = HashMap<Int, TextureView>()

var shareScreenContainer: FrameLayout? = null
var localUid: Int = 0
var shareScreenUid: Int = 0
Expand Down
4 changes: 2 additions & 2 deletions app/src/main/java/io/agora/flat/di/interfaces/RtcApi.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@ package io.agora.flat.di.interfaces

import io.agora.flat.common.rtc.RtcEvent
import io.agora.flat.common.rtc.RtcJoinOptions
import io.agora.rtc.video.VideoCanvas
import io.agora.rtc2.video.VideoCanvas
import kotlinx.coroutines.flow.Flow

interface RtcApi {
fun joinChannel(options: RtcJoinOptions): Int

fun leaveChannel()
fun leaveChannel(): Int

fun enableLocalVideo(enabled: Boolean)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ import io.agora.flat.ui.manager.RecordManager
import io.agora.flat.ui.manager.RoomErrorManager
import io.agora.flat.ui.manager.UserManager
import io.agora.flat.ui.viewmodel.ChatMessageManager
import io.agora.flat.ui.viewmodel.RtcVideoController
import io.agora.flat.common.rtc.RtcVideoController
import io.agora.flat.util.toInviteCodeDisplay
import kotlinx.coroutines.async
import kotlinx.coroutines.cancel
Expand Down Expand Up @@ -265,11 +265,19 @@ class ClassRoomViewModel @Inject constructor(
private fun joinRtc() {
logger.i("[RTC] start join rtc")
state.value?.run {
val rtcJoinOptions = RtcJoinOptions(
token = rtcToken,
channel = roomUUID,
uid = rtcUID,
audioOpen = audioOpen,
videoOpen = videoOpen
)
rtcVideoController.setupUid(uid = rtcUID, ssUid = rtcShareScreen.uid)
rtcApi.joinChannel(
RtcJoinOptions(rtcToken, roomUUID, rtcUID, audioOpen = audioOpen, videoOpen = videoOpen)
).also {
logger.i("[RTC] join rtc result: $it")
rtcApi.joinChannel(rtcJoinOptions).also { result ->
when (result) {
0 -> logger.i("[RTC] join rtc successful")
else -> logger.w("[RTC] join rtc error: $result")
}
}
}
}
Expand Down
Loading

0 comments on commit 43d63f4

Please sign in to comment.