Skip to content

Commit 2ffa7c7

Browse files
masonqiaoAbySwifter
authored andcommitted
[RoomKit] [Android] Support creating large rooms on mobile devices and support screen sharing
1 parent dd95bec commit 2ffa7c7

60 files changed

Lines changed: 2696 additions & 696 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

room/tuiroomkit/build.gradle

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -50,9 +50,9 @@ dependencies {
5050
api project(':atomic_x')
5151

5252
api 'com.google.android.material:material:1.12.0'
53-
54-
api rootProject.getProperties().containsKey("roomEngineSdk") ? rootProject.ext.roomEngineSdk : "io.trtc.uikit:rtc_room_engine:3.4.0.1335"
55-
api rootProject.getProperties().containsKey("liteavSdk") ? rootProject.ext.liteavSdk : "com.tencent.liteav:LiteAVSDK_Professional:12.8.0.19279"
56-
api rootProject.getProperties().containsKey("atomicxCoreSdk") ? rootProject.ext.atomicxCoreSdk : "io.trtc.uikit:atomicx-core:3.4.0.1335"
53+
54+
api rootProject.getProperties().containsKey("roomEngineSdk") ? rootProject.ext.roomEngineSdk : "io.trtc.uikit:rtc_room_engine:4.0.1.97"
55+
api rootProject.getProperties().containsKey("atomicxCoreSdk") ? rootProject.ext.atomicxCoreSdk : "io.trtc.uikit:atomicx-core:4.0.1.90"
56+
api rootProject.getProperties().containsKey("liteavSdk") ? rootProject.ext.liteavSdk : "com.tencent.liteav:LiteAVSDK_Professional:13.0.0.19676"
5757
api rootProject.getProperties().containsKey("imSdk") ? rootProject.ext.imSdk : "com.tencent.imsdk:imsdk-plus:8.7.7201"
5858
}

room/tuiroomkit/src/main/AndroidManifest.xml

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,32 @@
11
<?xml version="1.0" encoding="utf-8"?>
22
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
33

4+
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
5+
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_MEDIA_PROJECTION" />
6+
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_MEDIA_PLAYBACK" />
7+
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_MICROPHONE" />
8+
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_CAMERA" />
9+
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
10+
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
11+
12+
<uses-feature android:name="android.hardware.camera" />
13+
<uses-feature android:name="android.hardware.camera.autofocus" />
14+
15+
<uses-permission android:name="android.permission.CAMERA" />
16+
<uses-permission android:name="android.permission.INTERNET" />
17+
<uses-permission android:name="android.permission.RECORD_AUDIO" />
18+
419
<application>
520
<activity
621
android:name=".RoomHomeActivity"
722
android:exported="true"
823
android:screenOrientation="portrait" />
9-
24+
1025
<activity
1126
android:name=".RoomCreateActivity"
1227
android:exported="false"
1328
android:screenOrientation="portrait" />
14-
29+
1530
<activity
1631
android:name=".RoomJoinActivity"
1732
android:exported="false"

room/tuiroomkit/src/main/java/com/trtc/uikit/roomkit/barrage/BarrageStreamView.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ class BarrageStreamView @JvmOverloads constructor(
8686
}
8787

8888
override fun addObserver() {
89+
subscribeJob?.cancel()
8990
subscribeJob = scope.launch {
9091
launch {
9192
barrageStore?.barrageState?.messageList?.collect {

room/tuiroomkit/src/main/java/com/trtc/uikit/roomkit/base/error/ErrorLocalized.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,7 @@ object ErrorLocalized {
176176
USER_ALREADY_ON_SEAT(100210),
177177
SEAT_NOT_SUPPORT_LINK_MIC(100211),
178178
EMPTY_SEAT_LIST(100251),
179+
SPEAKER_SEAT_OCCUPIED(100253),
179180
METADATA_KEY_EXCEEDS_LIMIT(100500),
180181
METADATA_VALUE_SIZE_EXCEEDS_BYTE_LIMIT(100501),
181182
METADATA_TOTAL_VALUE_SIZE_EXCEEDS_BYTE_LIMIT(100502),
@@ -258,6 +259,7 @@ object ErrorLocalized {
258259
USER_ALREADY_ON_SEAT -> context.getString(R.string.roomkit_err_100210_user_already_on_seat)
259260
SEAT_NOT_SUPPORT_LINK_MIC -> context.getString(R.string.roomkit_err_100211_seat_not_supported)
260261
EMPTY_SEAT_LIST -> context.getString(R.string.roomkit_err_100251_seat_list_is_empty)
262+
SPEAKER_SEAT_OCCUPIED -> context.getString(R.string.roomkit_err_100253_speaker_seat_occupied)
261263
METADATA_KEY_EXCEEDS_LIMIT -> context.getString(R.string.roomkit_err_100500_room_metadata_key_limit)
262264
METADATA_VALUE_SIZE_EXCEEDS_BYTE_LIMIT -> context.getString(R.string.roomkit_err_100501_room_metadata_value_limit)
263265
METADATA_TOTAL_VALUE_SIZE_EXCEEDS_BYTE_LIMIT -> context.getString(R.string.roomkit_err_100502_room_metadata_total_limit)

room/tuiroomkit/src/main/java/com/trtc/uikit/roomkit/base/operator/DeviceOperator.kt

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,13 @@ package com.trtc.uikit.roomkit.base.operator
22

33
import android.Manifest
44
import android.content.Context
5+
import android.content.Intent
6+
import android.os.Build
7+
import android.provider.Settings
8+
import androidx.core.net.toUri
59
import com.trtc.uikit.roomkit.R
610
import com.trtc.uikit.roomkit.base.error.ErrorLocalized
11+
import com.trtc.uikit.roomkit.base.log.RoomKitLogger
712
import io.trtc.tuikit.atomicx.common.permission.PermissionCallback
813
import io.trtc.tuikit.atomicx.common.permission.PermissionRequester
914
import io.trtc.tuikit.atomicxcore.api.CompletionHandler
@@ -24,8 +29,8 @@ class DeviceOperator(context: Context) {
2429
CAMERA,
2530
}
2631

32+
private val logger = RoomKitLogger.getLogger("DeviceOperator")
2733
private val contextRef = WeakReference(context)
28-
2934
private val deviceStore = DeviceStore.shared()
3035

3136
suspend fun unmuteMicrophone(participantStore: RoomParticipantStore?) {
@@ -57,6 +62,19 @@ class DeviceOperator(context: Context) {
5762
deviceStore.closeLocalCamera()
5863
}
5964

65+
fun startScreenShare() {
66+
val context = contextRef.get() ?: return
67+
if (!checkDrawOverlaysPermission(context)) {
68+
requestDrawOverlaysPermission(context)
69+
return
70+
}
71+
deviceStore.startScreenShare()
72+
}
73+
74+
fun stopScreenShare() {
75+
deviceStore.stopScreenShare()
76+
}
77+
6078
suspend fun requestPermission(type: DeviceOperatorType): Boolean {
6179
val context = contextRef.get() ?: return false
6280
val appName = context.packageManager.getApplicationLabel(context.applicationInfo).toString()
@@ -67,6 +85,7 @@ class DeviceOperator(context: Context) {
6785
context.getString(R.string.roomkit_permission_microphone),
6886
context.getString(R.string.roomkit_permission_mic_reason)
6987
)
88+
7089
DeviceOperatorType.CAMERA -> Triple(
7190
Manifest.permission.CAMERA,
7291
context.getString(R.string.roomkit_permission_camera),
@@ -131,4 +150,27 @@ class DeviceOperator(context: Context) {
131150
}
132151
}
133152
}
153+
154+
private fun checkDrawOverlaysPermission(context: Context): Boolean {
155+
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
156+
Settings.canDrawOverlays(context)
157+
} else {
158+
true
159+
}
160+
}
161+
162+
private fun requestDrawOverlaysPermission(context: Context) {
163+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
164+
val intent = Intent(
165+
Settings.ACTION_MANAGE_OVERLAY_PERMISSION,
166+
"package:${context.packageName}".toUri()
167+
)
168+
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
169+
if (intent.resolveActivity(context.packageManager) != null) {
170+
context.startActivity(intent)
171+
} else {
172+
logger.error("No activity found to handle overlay permission request")
173+
}
174+
}
175+
}
134176
}

room/tuiroomkit/src/main/java/com/trtc/uikit/roomkit/base/ui/RoomActionSheetDialog.kt

Lines changed: 36 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ class RoomActionSheetDialog private constructor(
2323
private val builder: Builder
2424
) : BottomSheetDialog(context, R.style.RoomKitBottomDialog) {
2525

26+
private lateinit var rootView: View
27+
private lateinit var topDivideView: View
2628
private lateinit var tvTips: TextView
2729
private lateinit var llActions: LinearLayout
2830
private lateinit var dragIndicator: View
@@ -31,6 +33,8 @@ class RoomActionSheetDialog private constructor(
3133
super.onCreate(savedInstanceState)
3234
setContentView(R.layout.roomkit_dialog_action_sheet)
3335

36+
rootView = findViewById(R.id.cl_root)!!
37+
topDivideView = findViewById(R.id.view_divider_top)!!
3438
tvTips = findViewById(R.id.tv_tips)!!
3539
llActions = findViewById(R.id.ll_actions)!!
3640
dragIndicator = findViewById(R.id.drag_indicator)!!
@@ -43,10 +47,12 @@ class RoomActionSheetDialog private constructor(
4347
if (builder.tipsText.isNotEmpty()) {
4448
tvTips.text = builder.tipsText
4549
tvTips.visibility = View.VISIBLE
50+
topDivideView.visibility = View.VISIBLE
4651
} else {
4752
tvTips.visibility = View.GONE
53+
topDivideView.visibility = View.GONE
4854
}
49-
55+
rootView.setBackgroundResource(builder.backgroundRes ?: R.drawable.roomkit_bg_bottom_sheet_dialog)
5056
builder.actions.forEachIndexed { index, action ->
5157
if (index > 0) {
5258
addDivider()
@@ -64,7 +70,12 @@ class RoomActionSheetDialog private constructor(
6470
LinearLayout.LayoutParams.MATCH_PARENT,
6571
context.resources.getDimensionPixelSize(R.dimen.roomkit_divider_height)
6672
)
67-
setBackgroundResource(R.color.roomkit_color_action_sheet_divider)
73+
setBackgroundColor(
74+
ContextCompat.getColor(
75+
context,
76+
builder.dividerColorRes ?: R.color.roomkit_color_action_sheet_divider
77+
)
78+
)
6879
}
6980
llActions.addView(divider)
7081
}
@@ -77,8 +88,11 @@ class RoomActionSheetDialog private constructor(
7788
button.setTextColor(
7889
ContextCompat.getColor(
7990
context,
80-
if (action.isWarning) R.color.roomkit_color_end_room
81-
else R.color.roomkit_color_primary
91+
when {
92+
action.isWarning -> R.color.roomkit_color_end_room
93+
builder.textColorRes != null -> builder.textColorRes!!
94+
else -> R.color.roomkit_color_primary
95+
}
8296
)
8397
)
8498
button.setOnClickListener {
@@ -93,7 +107,6 @@ class RoomActionSheetDialog private constructor(
93107
window?.let { win ->
94108
val bottomSheet = win.findViewById<View>(com.google.android.material.R.id.design_bottom_sheet)
95109
bottomSheet?.setBackgroundResource(R.drawable.roomkit_bg_bottom_sheet_dialog)
96-
97110
win.setBackgroundDrawableResource(android.R.color.transparent)
98111
win.setWindowAnimations(R.style.RoomKitBottomDialogAnimation)
99112

@@ -125,6 +138,9 @@ class RoomActionSheetDialog private constructor(
125138
class Builder(private val context: Context) {
126139
internal var tipsText: String = ""
127140
internal val actions = mutableListOf<ActionItem>()
141+
internal var backgroundRes: Int? = null
142+
internal var textColorRes: Int? = null
143+
internal var dividerColorRes: Int? = null
128144

129145
fun setTips(@StringRes tipsResId: Int): Builder {
130146
this.tipsText = context.getString(tipsResId)
@@ -159,6 +175,21 @@ class RoomActionSheetDialog private constructor(
159175
return this
160176
}
161177

178+
fun setBackgroundResource(@androidx.annotation.DrawableRes drawableRes: Int): Builder {
179+
this.backgroundRes = drawableRes
180+
return this
181+
}
182+
183+
fun setTextColor(@androidx.annotation.ColorRes colorRes: Int): Builder {
184+
this.textColorRes = colorRes
185+
return this
186+
}
187+
188+
fun setDividerColor(@androidx.annotation.ColorRes colorRes: Int): Builder {
189+
this.dividerColorRes = colorRes
190+
return this
191+
}
192+
162193
fun show(): RoomActionSheetDialog {
163194
val dialog = RoomActionSheetDialog(context, this)
164195
dialog.show()

room/tuiroomkit/src/main/java/com/trtc/uikit/roomkit/view/RoomCreateView.kt

Lines changed: 43 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package com.trtc.uikit.roomkit.view
22

3+
import android.app.Activity
34
import android.content.Context
45
import android.content.Intent
56
import android.util.AttributeSet
@@ -12,6 +13,7 @@ import android.widget.TextView
1213
import com.trtc.uikit.roomkit.R
1314
import com.trtc.uikit.roomkit.RoomMainActivity
1415
import com.trtc.uikit.roomkit.base.extension.getDisplayName
16+
import com.trtc.uikit.roomkit.base.ui.RoomActionSheetDialog
1517
import io.trtc.tuikit.atomicxcore.api.login.LoginStore
1618
import io.trtc.tuikit.atomicxcore.api.login.UserProfile
1719
import kotlinx.coroutines.CoroutineScope
@@ -30,10 +32,15 @@ class RoomCreateView @JvmOverloads constructor(
3032
attrs: AttributeSet? = null,
3133
defStyleAttr: Int = 0
3234
) : FrameLayout(context, attrs, defStyleAttr) {
35+
36+
enum class RoomType { STANDARD, WEBINAR }
37+
3338
private val roomIdLength: Int = 6
3439

3540
private val ivBack: ImageView by lazy { findViewById(R.id.iv_back) }
3641
private val tvYourName: TextView by lazy { findViewById(R.id.tv_your_name) }
42+
private val llRoomType: LinearLayout by lazy { findViewById(R.id.ll_room_type_container) }
43+
private val tvRoomType: TextView by lazy { findViewById(R.id.tv_room_type) }
3744
private val llAudio: LinearLayout by lazy { findViewById(R.id.ll_audio) }
3845
private val ivAudioSwitch: ImageView by lazy { findViewById(R.id.iv_audio_switch) }
3946
private val llSpeaker: LinearLayout by lazy { findViewById(R.id.ll_speaker) }
@@ -48,6 +55,7 @@ class RoomCreateView @JvmOverloads constructor(
4855
private var isAudioEnabled: Boolean = true
4956
private var isSpeakerEnabled: Boolean = true
5057
private var isVideoEnabled: Boolean = true
58+
private var selectedRoomType: RoomType = RoomType.STANDARD
5159

5260
init {
5361
LayoutInflater.from(context).inflate(R.layout.roomkit_view_create, this)
@@ -83,6 +91,10 @@ class RoomCreateView @JvmOverloads constructor(
8391
handleBackClick()
8492
}
8593

94+
llRoomType.setOnClickListener {
95+
showRoomTypeDialog()
96+
}
97+
8698
llAudio.setOnClickListener {
8799
handleAudioClick()
88100
}
@@ -98,6 +110,30 @@ class RoomCreateView @JvmOverloads constructor(
98110
btnCreateRoom.setOnClickListener {
99111
handleCreateRoomClick()
100112
}
113+
114+
selectRoomType(selectedRoomType)
115+
}
116+
117+
private fun selectRoomType(type: RoomType) {
118+
selectedRoomType = type
119+
tvRoomType.text = when (type) {
120+
RoomType.STANDARD -> context.getString(R.string.roomkit_room_type_meeting)
121+
RoomType.WEBINAR -> context.getString(R.string.roomkit_room_type_webinar)
122+
}
123+
}
124+
125+
private fun showRoomTypeDialog() {
126+
RoomActionSheetDialog.Builder(context)
127+
.setBackgroundResource(R.drawable.roomkit_bg_bottom_sheet_dialog_white)
128+
.setTextColor(R.color.roomkit_color_text_primary)
129+
.setDividerColor(R.color.roomkit_color_background)
130+
.addAction(R.string.roomkit_room_type_meeting) {
131+
selectRoomType(RoomType.STANDARD)
132+
}
133+
.addAction(R.string.roomkit_room_type_webinar) {
134+
selectRoomType(RoomType.WEBINAR)
135+
}
136+
.show()
101137
}
102138

103139
private fun updateUserInfo(userInfo: UserProfile) {
@@ -109,7 +145,7 @@ class RoomCreateView @JvmOverloads constructor(
109145
}
110146

111147
private fun handleBackClick() {
112-
(context as? android.app.Activity)?.finish()
148+
(context as? Activity)?.finish()
113149
}
114150

115151
private fun handleAudioClick() {
@@ -145,8 +181,11 @@ class RoomCreateView @JvmOverloads constructor(
145181
private fun generateRoomID(): String {
146182
val min = 10.pow(roomIdLength - 1)
147183
val max = 10.pow(roomIdLength) - 1
148-
val roomId = (min..max).random().toString()
149-
return roomId
184+
val id = (min..max).random().toString()
185+
return when (selectedRoomType) {
186+
RoomType.WEBINAR -> "webinar_$id"
187+
RoomType.STANDARD -> id
188+
}
150189
}
151190

152191
private fun Int.pow(exponent: Int): Int = toDouble().pow(exponent).toInt()
@@ -171,4 +210,4 @@ class RoomCreateView @JvmOverloads constructor(
171210
else R.drawable.roomkit_ic_switch_off
172211
)
173212
}
174-
}
213+
}

0 commit comments

Comments
 (0)