Skip to content

Commit

Permalink
add classroom network status
Browse files Browse the repository at this point in the history
  • Loading branch information
AderanFeng committed Feb 22, 2024
1 parent 41c92f1 commit 909e9bc
Show file tree
Hide file tree
Showing 11 changed files with 151 additions and 3 deletions.
22 changes: 22 additions & 0 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,6 +5,7 @@ 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
Expand Down Expand Up @@ -106,11 +107,32 @@ class AgoraRtc @Inject constructor(val appEnv: AppEnv, val logger: Logger) : Rtc
}
trySend(RtcEvent.VolumeIndication(info, totalVolume))
}

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

override fun onRtcStats(stats: IRtcEngineEventHandler.RtcStats) {
trySend(RtcEvent.LastmileDelay(stats.lastmileDelay))
}
}
mHandler.addListener(listener)
awaitClose {
logger.i("[RTC] rtc event flow closed")
mHandler.removeListener(listener)
}
}

companion object {
internal fun getOverallQuality(txQuality: Int, rxQuality: Int): NetworkQuality {
return when (maxOf(txQuality, rxQuality)) {
Constants.QUALITY_UNKNOWN -> NetworkQuality.Unknown
Constants.QUALITY_EXCELLENT -> NetworkQuality.Excellent
Constants.QUALITY_GOOD -> NetworkQuality.Good
else -> NetworkQuality.Bad
}
}
}
}
6 changes: 3 additions & 3 deletions app/src/main/java/io/agora/flat/common/rtc/Misc.kt
Original file line number Diff line number Diff line change
Expand Up @@ -105,11 +105,11 @@ internal interface RTCEventListener {

fun onLastmileQuality(quality: Int) {}

fun onLastmileProbeResult(result: IRtcEngineEventHandler.LastmileProbeResult?) {}
fun onLastmileProbeResult(result: IRtcEngineEventHandler.LastmileProbeResult) {}

fun onLocalVideoStats(stats: IRtcEngineEventHandler.LocalVideoStats?) {}
fun onLocalVideoStats(stats: IRtcEngineEventHandler.LocalVideoStats) {}

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

fun onNetworkQuality(uid: Int, txQuality: Int, rxQuality: Int) {}

Expand Down
13 changes: 13 additions & 0 deletions app/src/main/java/io/agora/flat/common/rtc/RtcEvent.kt
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,23 @@ data class AudioVolumeInfo(
val vad: Int,
)


enum class NetworkQuality {
Excellent,
Good,
Bad,
Unknown
}

sealed class RtcEvent {
data class UserOffline(val uid: Int, val reason: Int) : RtcEvent()

data class UserJoined(val uid: Int, val elapsed: Int) : RtcEvent()

class VolumeIndication(val speakers: List<AudioVolumeInfo>, val totalVolume: Int) : RtcEvent()

class NetworkStatus(val quality: NetworkQuality) : RtcEvent()

class LastmileDelay(val delay: Int) : RtcEvent()

}
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,8 @@ class ClassRoomViewModel @Inject constructor(

val classroomEvent get() = eventbus.events.filterIsInstance<ClassroomEvent>()

val rtcEvent get() = rtcApi.observeRtcEvent()

val teacher = userManager.observeUsers().map { it.firstOrNull { user -> user.isOwner } }
val students = userManager.observeUsers().map {
it.filter { user -> !user.isOwner && (user.isJoined || user.isOnStage) }
Expand Down
32 changes: 32 additions & 0 deletions app/src/main/java/io/agora/flat/ui/activity/play/ExtComponent.kt
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import android.os.Build
import android.os.Bundle
import android.widget.FrameLayout
import androidx.activity.viewModels
import androidx.core.content.ContextCompat
import androidx.core.view.isVisible
import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.lifecycleScope
Expand All @@ -14,6 +15,8 @@ import coil.load
import io.agora.flat.Constants
import io.agora.flat.R
import io.agora.flat.common.error.FlatErrorHandler
import io.agora.flat.common.rtc.NetworkQuality
import io.agora.flat.common.rtc.RtcEvent
import io.agora.flat.data.model.RoomStatus
import io.agora.flat.databinding.ComponentExtensionBinding
import io.agora.flat.databinding.ComponentRoomStateBinding
Expand All @@ -27,6 +30,7 @@ import io.agora.flat.util.delayAndFinish
import io.agora.flat.util.isDarkMode
import io.agora.flat.util.showToast
import kotlinx.coroutines.flow.filterNotNull
import kotlinx.coroutines.launch

/**
* display common loading, toast, dialog, global layout change.
Expand Down Expand Up @@ -98,6 +102,34 @@ class ExtComponent(
}
}
}

lifecycleScope.launchWhenResumed {
classRoomViewModel.rtcEvent.collect { event ->
when (event) {
is RtcEvent.NetworkStatus -> {
when (event.quality) {
NetworkQuality.Unknown, NetworkQuality.Excellent -> {
roomStateBinding.networkStateIcon.setColorFilter(ContextCompat.getColor(activity, R.color.flat_green_6))
}
NetworkQuality.Good -> {
roomStateBinding.networkStateIcon.setColorFilter(ContextCompat.getColor(activity, R.color.flat_yellow_6))
}
NetworkQuality.Bad-> {
roomStateBinding.networkStateIcon.setColorFilter(ContextCompat.getColor(activity, R.color.flat_red_6))
}
}
}

is RtcEvent.LastmileDelay -> {
roomStateBinding.networkDelay.text = activity.getString(R.string.room_class_network_delay, event.delay)
}

else -> {

}
}
}
}
}

private fun handleErrorMessage(error: UiMessage) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,9 @@ class RtcComponent(
is RtcEvent.VolumeIndication -> {
adapter.updateVolume(event.speakers)
}
else -> {

}
}
}
}
Expand Down
10 changes: 10 additions & 0 deletions app/src/main/res/drawable/ic_network_status.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="#44AD00"
android:fillType="evenOdd"
android:pathData="M4.653,4.195C4.913,3.935 5.335,3.935 5.596,4.195C5.856,4.456 5.856,4.878 5.596,5.138C1.69,9.043 1.69,15.375 5.596,19.28C5.856,19.541 5.856,19.963 5.596,20.223C5.335,20.483 4.913,20.483 4.653,20.223C0.227,15.797 0.227,8.621 4.653,4.195ZM19.738,4.195C19.998,3.935 20.42,3.935 20.681,4.195C25.107,8.621 25.107,15.797 20.681,20.223C20.42,20.483 19.998,20.483 19.738,20.223C19.477,19.963 19.477,19.541 19.738,19.28C23.643,15.375 23.643,9.043 19.738,5.138C19.477,4.878 19.477,4.456 19.738,4.195ZM12.666,14.876C14.139,14.876 15.333,13.682 15.333,12.209C15.333,10.736 14.139,9.542 12.666,9.542C11.193,9.542 10,10.736 10,12.209C10,13.682 11.193,14.876 12.666,14.876ZM7.481,6.081C7.22,5.821 6.798,5.821 6.538,6.081C3.153,9.465 3.153,14.953 6.538,18.337C6.798,18.598 7.22,18.598 7.481,18.337C7.741,18.077 7.741,17.655 7.481,17.395C4.617,14.531 4.617,9.888 7.481,7.024C7.741,6.763 7.741,6.341 7.481,6.081ZM18.795,6.081C18.534,5.821 18.112,5.821 17.852,6.081C17.591,6.341 17.591,6.763 17.852,7.024C20.716,9.888 20.716,14.531 17.852,17.395C17.591,17.655 17.591,18.077 17.852,18.337C18.112,18.598 18.534,18.598 18.795,18.337C22.179,14.953 22.179,9.465 18.795,6.081ZM8.423,7.966C8.684,7.706 9.106,7.706 9.366,7.966C9.626,8.227 9.626,8.649 9.366,8.909C7.544,10.732 7.544,13.686 9.366,15.509C9.626,15.769 9.626,16.191 9.366,16.452C9.106,16.712 8.684,16.712 8.423,16.452C6.08,14.109 6.08,10.31 8.423,7.966ZM15.966,7.966C16.226,7.706 16.649,7.706 16.909,7.966C19.252,10.31 19.252,14.109 16.909,16.452C16.649,16.712 16.226,16.712 15.966,16.452C15.706,16.191 15.706,15.769 15.966,15.509C17.789,13.686 17.789,10.732 15.966,8.909C15.706,8.649 15.706,8.227 15.966,7.966Z" />
</vector>
42 changes: 42 additions & 0 deletions app/src/main/res/layout/component_room_state.xml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,48 @@
android:layout_width="16dp"
android:layout_height="0dp" />

<TextView
android:id="@+id/network_delay"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:maxLines="1"
android:textSize="12sp"
tools:text="@string/room_class_network_delay" />

<Space
android:layout_width="24dp"
android:layout_height="0dp" />

<LinearLayout
android:id="@+id/network_state_layout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal">

<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:maxLines="1"
android:textSize="12sp"
android:text="@string/room_class_network_status" />

<Space
android:layout_width="4dp"
android:layout_height="0dp" />

<ImageView
android:id="@+id/network_state_icon"
android:layout_width="18dp"
android:layout_height="18dp"
android:src="@drawable/ic_network_status" />
</LinearLayout>

<Space
android:layout_width="24dp"
android:layout_height="0dp" />

<io.agora.flat.ui.view.TimeStateLayout
android:id="@+id/time_state_layout"
android:layout_width="wrap_content"
Expand Down
3 changes: 3 additions & 0 deletions app/src/main/res/values-zh/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,9 @@
<string name="room_class_time_started_format">开始上课: %1$s</string>
<string name="room_class_time_left_format">剩余时间: %1$s</string>
<string name="room_class_time_ended">房间已经结束</string>

<string name="room_class_network_status">网络:</string>
<string name="room_class_network_delay">延迟: %1$dms</string>

<string name="cloud_storage">云盘</string>
<string name="cloud_storage_usage_format">已使用 %1$s</string>
Expand Down
3 changes: 3 additions & 0 deletions app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,9 @@
<string name="room_class_time_left_format">Time Left: %1$s</string>
<string name="room_class_time_ended">Ended</string>

<string name="room_class_network_status">Network:</string>
<string name="room_class_network_delay">Latency: %1$dms</string>

<string name="cloud_storage">Cloud Storage</string>
<string name="cloud_storage_usage_format">%1$s used</string>
<string name="cloud_storage_upload_image">Photos</string>
Expand Down
18 changes: 18 additions & 0 deletions app/src/test/java/io/agora/flat/common/rtc/AgoraRtcTest.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package io.agora.flat.common.rtc

import org.junit.Test

class AgoraRtcTest {
@Test
fun getOverallQuality() {
assert(AgoraRtc.getOverallQuality(0, 0) == NetworkQuality.Unknown)
assert(AgoraRtc.getOverallQuality(1, 0) == NetworkQuality.Excellent)
assert(AgoraRtc.getOverallQuality(2, 0) == NetworkQuality.Good)
assert(AgoraRtc.getOverallQuality(3, 0) == NetworkQuality.Bad)
assert(AgoraRtc.getOverallQuality(0, 1) == NetworkQuality.Excellent)
assert(AgoraRtc.getOverallQuality(0, 2) == NetworkQuality.Good)
assert(AgoraRtc.getOverallQuality(0, 3) == NetworkQuality.Bad)
assert(AgoraRtc.getOverallQuality(1, 2) == NetworkQuality.Good)
assert(AgoraRtc.getOverallQuality(2, 3) == NetworkQuality.Bad)
}
}

0 comments on commit 909e9bc

Please sign in to comment.