接口参考
本页列出 Android SDK 的公开业务模块、列表和句柄签名。除原生扩展注明的包外,类型位于 com.deeprespond.im。签名采用 Kotlin;Java 的回调、Future、Options 与订阅对应关系见Java 接入。参数默认值表示可以省略,Duration 来自 kotlin.time,JSON 来自 kotlinx.serialization.json。
suspend 方法在协程中调用;Flow / StateFlow 需要收集才会更新界面。网络和权限失败以 DRException 表示。分页通过 nextCursor 继续,列表与订阅结束后要释放。各方法的权限、限流、发送及取消语义见对应业务章节;返回对象的字段见数据类型。
DRClient
// 实例属性
auth: AuthModule
connection: ConnectionModule
users: UsersModule
devices: DevicesModule
config: StateFlow<ClientConfig?>
conversations: ConversationsModule
messages: MessagesModule
friends: FriendsModule
groups: GroupsModule
files: FilesModule
push: PushModule
presence: PresenceModule
chatrooms: ChatroomsModule
calls: CallsModule
channels: ChannelsModule
reports: ReportsModule
appKey: String
events: SharedFlow<DREvent>
startupEvents: List<DREvent>
hasPendingWork: Boolean
fun java(): DRJavaClient
fun <T : DREvent> on(type: KClass<T>): Flow<T>
inline fun <reified T : DREvent> on(): Flow<T>
fun keepForeground(): AutoCloseable
suspend fun <T> keepForeground(block: suspend () -> T): T
suspend fun exportDiagnostics(): java.io.File
suspend fun destroy()
// DRClient 静态入口
fun initialize(context: Context, options: DRClientOptions): DRClient
val instance: DRClient
val instanceOrNull: DRClient?
fun isMainProcess(context: Context): Boolean初始化及选项见客户端。startupEvents 读取后清空;诊断 ZIP 在缓存中保存,24 小时过期。事件流有缓冲上限,业务数据以模块快照为准。
基础与登录
使用规则与示例见相关章节。
AuthModule
interface AuthModule {
val state: StateFlow<AuthState>
val currentUser: CurrentUser?
val restored: StateFlow<Boolean>
suspend fun awaitRestored()
suspend fun loginWithTicket(ticket: String, username: String? = null): LoginResult
suspend fun loginWithPassword(username: String, password: String): LoginResult
suspend fun register(username: String, password: String, nickname: String? = null): SelfProfile
suspend fun logout(clearLocalData: Boolean = false)
suspend fun changePassword(currentPassword: String, newPassword: String)
suspend fun clearLocalData(username: String? = null, all: Boolean = false)
}ConnectionModule
interface ConnectionModule {
val state: StateFlow<DRConnectionState>
val serverTimeOffsetMs: Long
fun reconnectNow()
suspend fun waitUntilReady(timeout: Duration? = null)
fun diagnostics(): Diagnostics
}用户与设备
使用规则与示例见相关章节。
UsersModule
interface UsersModule {
val me: StateFlow<SelfProfile?>
suspend fun refreshMe(): SelfProfile
suspend fun updateMe(nickname: String? = null, avatarUrl: String? = null, attributes: Map<String, String?>? = null, clearAttributes: Boolean = false, version: Long? = null): SelfProfile
val myMute: MyMute
fun get(username: String): UserProfile?
suspend fun fetch(usernames: List<String>, force: Boolean = false): Map<String, UserProfile>
}DevicesModule
interface DevicesModule {
fun online(): List<OnlineDevice>
suspend fun sessions(): List<LoginSession>
suspend fun kick(sessionId: String)
}会话与消息
使用规则与示例见相关章节。
ConversationList
interface ConversationList : LiveList<ConversationView>MessageList
interface MessageList : AutoCloseable {
val conversationKey: String
val snapshot: StateFlow<MessageListSnapshot>
suspend fun loadOlder()
suspend fun loadNewer()
suspend fun loadGap(gap: MessageGap)
suspend fun jumpTo(seq: Long)
fun markRead()
fun setViewing(atBottom: Boolean? = null, visible: Boolean? = null)
override fun close()
}ConversationsModule
interface ConversationsModule {
fun list(): ConversationList
fun listFlow(): Flow<LiveListSnapshot<ConversationView>>
suspend fun get(conversationId: String): ConversationView?
suspend fun openSingle(username: String): ConversationView
suspend fun refresh(conversationId: String): ConversationView
fun markRead(conversationId: String, seq: Long? = null)
suspend fun markAllRead(): MarkAllReadResult
suspend fun setMarkedUnread(conversationId: String, marked: Boolean)
suspend fun setPinned(conversationId: String, pinned: Boolean)
suspend fun remove(conversationId: String, clearMessages: Boolean = false)
suspend fun clearMessages(conversationId: String)
suspend fun setDraft(conversationKey: String, draft: Draft?)
val unreadTotal: StateFlow<Int>
fun getUnreadTotal(excludeMuted: Boolean = false): Int
fun getTyping(conversationKey: String): List<String>
fun typing(conversationKey: String)
}MessagesModule
interface MessagesModule {
fun open(conversationKey: String, aroundSeq: Long? = null): MessageList
suspend fun send(to: SendTarget, content: OutgoingContent, options: SendOptions = SendOptions()): MessageView
suspend fun resend(clientMsgId: String)
suspend fun discard(clientMsgId: String)
suspend fun sendOnline(to: SendTarget, body: JsonObject, ext: JsonObject? = null): OnlineResult
suspend fun sendOnline(to: SendTarget, body: Map<String, Any?>, ext: Map<String, Any?>? = null): OnlineResult
suspend fun recall(conversationId: String, seq: Long): Boolean
fun canRecall(message: MessageView): Boolean
suspend fun deleteForMe(conversationId: String, seqs: List<Long>)
suspend fun react(conversationId: String, seq: Long, key: String): Boolean
suspend fun unreact(conversationId: String, seq: Long, key: String): Boolean
suspend fun reactionUsers(conversationId: String, seq: Long, key: String, cursor: String? = null, limit: Int? = null): DRPage<ReactionUser>
suspend fun setPinned(conversationId: String, seq: Long, pinned: Boolean): Boolean
suspend fun lookup(conversationId: String, seqs: List<Long>): LookupResult
suspend fun searchLocal(keyword: String, conversationId: String? = null, limit: Int = 50): List<MessageView>
suspend fun receipts(conversationId: String, seqs: List<Long>): List<ReceiptCount>
suspend fun receiptUsers(conversationId: String, seq: Long, status: ReceiptStatus, cursor: String? = null, limit: Int? = null): DRPage<ReceiptUser>
fun getReceipt(conversationId: String, seq: Long): ReceiptCount?
}好友
使用规则与示例见相关章节。
FriendsModule
interface FriendsModule {
fun list(): LiveList<Friend>
fun listFlow(): Flow<LiveListSnapshot<Friend>>
fun get(username: String): Friend?
val listInfo: FriendListInfo?
suspend fun check(usernames: List<String>): List<FriendCheck>
suspend fun update(username: String, remark: String? = null, attributes: Map<String, String?>? = null, clearAttributes: Boolean = false): Friend
suspend fun remove(username: String)
val requests: FriendRequestsModule
val blacklist: FriendBlacklistModule
val settings: FriendSettingsModule
}FriendRequestsModule
interface FriendRequestsModule {
suspend fun received(status: FriendRequestStatus? = null, cursor: String? = null, limit: Int? = null): DRPage<FriendRequest>
suspend fun sent(status: FriendRequestStatus? = null, cursor: String? = null, limit: Int? = null): DRPage<FriendRequest>
val unreadCount: StateFlow<Int>
suspend fun markRead(readUntil: Long? = null)
suspend fun send(username: String, message: String? = null, remark: String? = null, addSource: String? = null): FriendRequestResult
suspend fun accept(username: String, remark: String? = null): Friend
suspend fun decline(username: String)
}FriendBlacklistModule
interface FriendBlacklistModule {
fun list(): LiveList<BlacklistEntry>
fun listFlow(): Flow<LiveListSnapshot<BlacklistEntry>>
fun has(username: String): Boolean
suspend fun add(username: String)
suspend fun remove(username: String)
}FriendSettingsModule
interface FriendSettingsModule {
suspend fun
suspend fun set(mode: FriendAddMode?)
}群组
使用规则与示例见相关章节。
GroupsModule
interface GroupsModule {
fun list(): LiveList<GroupView>
fun listFlow(): Flow<LiveListSnapshot<GroupView>>
suspend fun get(groupId: String, refresh: Boolean = false): GroupView?
suspend fun lookup(groupIds: List<String>): List<GroupInfo>
suspend fun publicGroups(namePrefix: String? = null, cursor: String? = null, limit: Int? = null): DRPage<GroupInfo>
suspend fun create(
name: String,
type: GroupType? = null,
avatarUrl: String? = null,
description: String? = null,
announcement: String? = null,
attributes: Map<String, String?>? = null,
memberInvite: MemberInvite? = null,
joinMode: JoinMode? = null,
members: List<String>? = null,
message: String? = null,
): CreateGroupResult
suspend fun update(
groupId: String,
type: GroupType? = null,
name: String? = null,
avatarUrl: String? = null,
description: String? = null,
announcement: String? = null,
attributes: Map<String, String?>? = null,
clearAttributes: Boolean = false,
memberInvite: MemberInvite? = null,
joinMode: JoinMode? = null,
version: Long? = null,
): GroupInfo
suspend fun transferOwner(groupId: String, username: String): GroupInfo
suspend fun setMuteAll(groupId: String, on: Boolean): GroupInfo
suspend fun leave(groupId: String)
suspend fun dismiss(groupId: String)
suspend fun onlineCount(groupId: String): GroupOnlineCount
fun members(groupId: String, role: GroupRole? = null, muted: Boolean? = null): LiveList<GroupMember>
fun membersFlow(groupId: String, role: GroupRole? = null, muted: Boolean? = null): Flow<LiveListSnapshot<GroupMember>>
suspend fun lookupMembers(groupId: String, usernames: List<String>): List<GroupMember>
suspend fun invite(groupId: String, usernames: List<String>, message: String? = null): List<GroupMemberResult>
suspend fun removeMembers(groupId: String, usernames: List<String>): List<GroupMemberResult>
suspend fun updateMember(groupId: String, username: String, groupNickname: String? = null, attributes: Map<String, String?>? = null, clearAttributes: Boolean = false): GroupMember
suspend fun setRole(groupId: String, username: String, role: GroupRole): GroupMember
suspend fun mute(groupId: String, username: String, duration: Duration? = null): GroupMember
suspend fun unmute(groupId: String, username: String): GroupMember
val blacklist: GroupBlacklistModule
val joinLink: GroupJoinLinkModule
val applications: GroupApplicationsModule
val invitations: GroupInvitationsModule
val requests: GroupRequestsModule
val settings: GroupSettingsModule
}GroupBlacklistModule
interface GroupBlacklistModule {
suspend fun list(groupId: String, cursor: String? = null, limit: Int? = null): DRPage<GroupBlacklistEntry>
suspend fun add(groupId: String, username: String, reason: String? = null)
suspend fun remove(groupId: String, username: String)
}GroupJoinLinkModule
interface GroupJoinLinkModule {
suspend fun get(groupId: String): JoinLink
suspend fun create(groupId: String, expiresIn: Duration? = null): JoinLink
suspend fun revoke(groupId: String)
suspend fun preview(link: String): JoinLinkPreview
suspend fun join(link: String): GroupInfo
}GroupApplicationsModule
interface GroupApplicationsModule {
suspend fun apply(groupId: String, message: String? = null): String
suspend fun withdraw(groupId: String)
suspend fun mine(status: GroupRequestStatus? = null, cursor: String? = null, limit: Int? = null): DRPage<GroupRequest>
}GroupInvitationsModule
interface GroupInvitationsModule {
suspend fun received(status: GroupRequestStatus? = null, cursor: String? = null, limit: Int? = null): DRPage<GroupRequest>
suspend fun accept(groupId: String): GroupInfo
suspend fun decline(groupId: String, reason: String? = null)
}GroupRequestsModule
interface GroupRequestsModule {
suspend fun list(groupId: String, kind: GroupRequestKind? = null, status: GroupRequestStatus? = null, cursor: String? = null, limit: Int? = null): DRPage<GroupRequest>
suspend fun approve(groupId: String, kind: GroupRequestKind, username: String): String
suspend fun decline(groupId: String, kind: GroupRequestKind, username: String, reason: String? = null)
suspend fun withdrawInvite(groupId: String, kind: GroupRequestKind, username: String)
}GroupSettingsModule
interface GroupSettingsModule {
suspend fun
suspend fun set(mode: InviteMode?)
}文件
使用规则与示例见相关章节。
FilesModule
interface FilesModule {
fun upload(file: DRFile, purpose: UploadPurpose, kind: FileKind? = null, name: String? = null, groupId: String? = null, original: Boolean = false): UploadTask
fun isFileUrl(url: String): Boolean
suspend fun resolveUrl(url: String): DownloadUrl
suspend fun resolveUrls(urls: List<String>): List<ResolvedUrl>
fun download(source: DownloadSource, saveTo: File? = null, conflict: Conflict = Conflict.RENAME): DownloadTask
suspend fun localPath(url: String): File
suspend fun prepare(file: DRFile, kind: FileKind, original: Boolean = false): PreparedFile
suspend fun clearImageCache()
suspend fun groupFiles(groupId: String, cursor: String? = null, limit: Int? = null): GroupFilesPage
suspend fun deleteGroupFile(groupId: String, fileId: String)
}聊天室
使用规则与示例见相关章节。
ChatroomsModule
interface ChatroomsModule {
suspend fun list(namePrefix: String? = null, cursor: String? = null, limit: Int? = null): DRPage<ChatroomListItem>
suspend fun get(roomId: String): ChatroomInfo
suspend fun create(name: String, description: String? = null, avatarUrl: String? = null, announcement: String? = null, maxMembers: Int? = null, listed: Boolean? = null): ChatroomInfo
suspend fun onlineCounts(roomIds: List<String>): List<ChatroomOnlineCount>
suspend fun enter(roomId: String, ext: String? = null, leaveOthers: Boolean = false): ChatroomHandle
val entered: StateFlow<Map<String, ChatroomHandle>>
}ChatroomHandle
interface ChatroomHandle {
val roomId: String
val snapshot: StateFlow<ChatroomSnapshot>
val events: Flow<ChatroomEvent>
fun <T : ChatroomEvent> on(type: KClass<T>): Flow<T>
suspend fun send(content: OutgoingContent, priority: ChatroomPriority = ChatroomPriority.NORMAL, ext: JsonObject? = null): ChatroomMessageView
fun like(count: Int = 1)
suspend fun setAttributes(attributes: Map<String, String>, autoDelete: Boolean = false, force: Boolean = false): AttributeResult
suspend fun removeAttributes(keys: List<String>, force: Boolean = false): AttributeResult
suspend fun recall(messageId: String): Boolean
suspend fun members(cursor: String? = null, limit: Int? = null): DRPage<ChatroomMember>
suspend fun refresh()
suspend fun leave()
val manage: ChatroomManage
}ChatroomManage
interface ChatroomManage {
suspend fun update(patch: ChatroomPatch, version: Long? = null): ChatroomInfo
suspend fun setMuteAll(on: Boolean)
suspend fun setAdmin(username: String, admin: Boolean)
suspend fun transferOwner(username: String)
suspend fun mute(usernames: List<String>, duration: Duration? = null, reason: String? = null): List<ChatroomMemberResult>
suspend fun unmute(usernames: List<String>): List<ChatroomMemberResult>
suspend fun ban(usernames: List<String>, duration: Duration? = null, reason: String? = null): List<ChatroomMemberResult>
suspend fun unban(usernames: List<String>): List<ChatroomMemberResult>
suspend fun kick(usernames: List<String>): List<ChatroomMemberResult>
val allowlist: ChatroomAllowlist
suspend fun mutes(cursor: String? = null, limit: Int? = null): DRPage<ChatroomMuteEntry>
suspend fun bans(cursor: String? = null, limit: Int? = null): DRPage<ChatroomBanEntry>
suspend fun dismiss()
}ChatroomAllowlist
interface ChatroomAllowlist {
suspend fun list(cursor: String? = null, limit: Int? = null): DRPage<ChatroomAllowlistEntry>
suspend fun add(usernames: List<String>): List<ChatroomMemberResult>
suspend fun remove(usernames: List<String>): List<ChatroomMemberResult>
}音视频
使用规则与示例见相关章节。
CallsModule
interface CallsModule {
val supported: Boolean
suspend fun start(media: CallMedia, target: CallTarget, ext: Map<String, String>? = null): CallHandle
val current: StateFlow<CallHandle?>
val incoming: StateFlow<List<CallHandle>>
suspend fun get(callId: String): CallHandle
suspend fun history(cursor: String? = null, limit: Int? = null): DRPage<CallSummary>
suspend fun groupCall(groupId: String): CallHandle?
fun groupCallBanner(groupId: String): GroupCallBanner?
}CallHandle
interface CallHandle {
val callId: String
val snapshot: StateFlow<CallSnapshot>
val tracks: StateFlow<CallTracks>
val data: Flow<CallDataMessage>
suspend fun join()
suspend fun reject(reason: RejectReason = RejectReason.DECLINED)
suspend fun hangup()
suspend fun end()
suspend fun invite(usernames: List<String>): List<CallInviteResult>
suspend fun resume()
suspend fun setMicrophoneEnabled(on: Boolean)
suspend fun setCameraEnabled(on: Boolean)
suspend fun sendData(data: ByteArray)
}提醒设置
使用规则与示例见相关章节。
PushModule
interface PushModule {
val settings: StateFlow<PushSettings?>
suspend fun updateSettings(dnd: DndChange? = null, quietHours: QuietHoursChange? = null, preview: PreviewChange? = null): PushSettings
suspend fun mute(target: MuteTarget, mode: MuteMode, duration: Duration? = null)
suspend fun unmute(target: MuteTarget)
fun getMute(target: MuteTarget): MuteInfo?
fun shouldNotify(message: MessageView): NotifyDecision
}在线状态
使用规则与示例见相关章节。
PresenceModule
interface PresenceModule {
fun subscribe(usernames: List<String>): AutoCloseable
fun get(username: String): PresenceState?
suspend fun query(usernames: List<String>): List<PresenceState>
}举报
使用规则与示例见相关章节。
ReportsModule
interface ReportsModule {
suspend fun submit(target: ReportTarget, reason: ReportReason, description: String? = null): ReportSubmitResult
suspend fun mine(cursor: String? = null, limit: Int? = null): DRPage<Report>
}列表与文件任务
LiveList 的 snapshot 包含 items、hasMore、loading、error。ConversationList 继承 LiveList。上传和下载的 await 只是等待结果,真正取消需要 cancel。
LiveList
interface LiveList<T> : AutoCloseable {
val snapshot: StateFlow<LiveListSnapshot<T>>
suspend fun loadMore()
override fun close()
}UploadTask
interface UploadTask {
val progress: StateFlow<Progress>
suspend fun await(): FileInfo
fun cancel()
}DownloadTask
interface DownloadTask {
val progress: StateFlow<Progress>
suspend fun await(): java.io.File
fun cancel()
}原生推送
包为 com.deeprespond.im.push,依赖 im-push。接入、厂商配置及点击校验见离线推送。
DRPushController
interface DRPushController {
suspend fun permission(): PushPermission
suspend fun requestPermission(activity: ComponentActivity): PushPermission
fun permissionContract(): ActivityResultContract<Unit, PushPermission>
fun markPermissionRequested()
fun shouldShowRationale(activity: Activity): Boolean
val enabled: Boolean
suspend fun setEnabled(enabled: Boolean)
var language: String?
suspend fun register()
suspend fun currentRegistration(): PushDevice?
val registrations: SharedFlow<PushRegistration>
val opened: Flow<PushOpened>
suspend fun takeLaunchOpen(): PushOpened?
fun clearDeliveredNotifications()
fun cancelNotification(tag: String)
fun setBadge(count: Int?)
fun openNotificationSettings(activity: Activity, channelId: String? = null)
val channelStates: StateFlow<Map<String, Boolean>>
fun isHibernationExempt(): Boolean
fun openHibernationSettings(activity: Activity)
}DRPush
fun of(client: DRClient): DRPushController?
fun handleRemoteMessage(context: Context, message: RemoteMessage): Boolean
fun handleRegistered(context: Context, installationId: String)
fun handleNewToken(context: Context, token: String)
fun handleDeletedMessages(context: Context)
fun handleUnregistered(context: Context, installationId: String)
fun handleIntent(intent: Intent?): Boolean以上是 DRPush 的静态方法。handleRemoteMessage / handleIntent 返回 true 表示 SDK 已接管;业务只处理返回 false 的内容。
原生通话
包为 com.deeprespond.im.call,依赖 im-call。媒体权限、系统来电和视图使用见音视频。
DRCallController
interface DRCallController {
val actions: Flow<CallAction>
fun canUseFullScreenIntent(): Boolean
fun openFullScreenIntentSettings(activity: Activity)
fun callChannelEnabled(): Boolean
fun intentCall(intent: Intent?): CallIntent?
}DRCallUI 与设备扩展
// 静态入口
fun DRCallUI.of(client: DRClient): DRCallController?
// CallHandle 扩展
val CallHandle.audioEndpoints: StateFlow<AudioEndpoints>
suspend fun CallHandle.switchCamera()
suspend fun CallHandle.setSpeakerphoneOn(on: Boolean)
suspend fun CallHandle.setAudioEndpoint(endpoint: AudioEndpoint)
// 视频视图
DRCallVideoView(context: Context, attrs: AttributeSet? = null)
var scaleType: DRCallVideoView.ScaleType // FIT / FILL
var mirror: Boolean
fun bind(call: CallHandle, track: CallTrack?)
fun unbind()文件、录音与图片扩展
// com.deeprespond.im
fun DRFile.Companion.fromUri(context: Context, uri: Uri, name: String? = null, mimeType: String? = null): DRFile
fun DRFile.Companion.fromFile(file: java.io.File, name: String? = null, mimeType: String? = null): DRFile
fun DRFile.Companion.fromBytes(bytes: ByteArray, name: String, mimeType: String? = null): DRFile
fun DRFile.withKeepMetadata(): DRFile
// com.deeprespond.im
suspend fun VoiceRecorder.start(context: Context, maxDuration: Duration = 60.seconds): Recording
val VoiceRecorder.isRecording: Boolean录音任务和结果见数据类型。Coil 包为 com.deeprespond.im.coil:
DRImage(url: String, thumbnail: Boolean = false)
fun DRImage.Companion.of(message: MessageView, thumbnail: Boolean = false): DRImage?
fun DRImage.Companion.stableKey(url: String): String
fun ComponentRegistry.Builder.addDRImage(client: DRClient? = null): ComponentRegistry.Builder使用方法见文件与录音。
Recording
interface Recording {
val level: Flow<Float>
val ended: Flow<VoiceRecordingEnd>
suspend fun stop(): VoiceRecording
fun cancel()
}显示辅助
包为 com.deeprespond.im.render。以下为接收 Android DRClient 的常用重载:
fun displayName(client: DRClient, username: String?, groupId: String? = null, locale: DRLocale = DRLocale.zhCN): String
fun conversationTitle(client: DRClient, view: DRObject, locale: DRLocale = DRLocale.zhCN): String
fun summarize(client: DRClient, message: MessageView, groupId: String? = null, locale: DRLocale = DRLocale.zhCN): String
fun renderTip(client: DRClient, message: MessageView, groupId: String? = null, locale: DRLocale = DRLocale.zhCN): String
fun renderRecall(client: DRClient, message: MessageView, groupId: String? = null, locale: DRLocale = DRLocale.zhCN): String另外两个显示入口:
fun renderCallRecord(message: DRObject, self: String, locale: DRLocale = DRLocale.zhCN): String
fun describeError(err: DRException, locale: DRLocale = DRLocale.zhCN): String其他渲染重载可以直接接收对象和名称解析器。界面组合及生命周期见界面。
独立 RTC 频道
interface ChannelsModule {
val supported: Boolean
val current: StateFlow<ChannelHandle?>
suspend fun get(channelId: String): RTCChannel
suspend fun currentSession(): ChannelSession?
suspend fun members(channelId: String, cursor: String? = null, limit: Int? = null): DRPage<ChannelParticipant>
suspend fun join(channelId: String, options: ChannelJoinOptions = ChannelJoinOptions()): ChannelHandle
suspend fun resume(channelId: String, sessionId: String): ChannelHandle
}
interface ChannelHandle {
val channelId: String
val sessionId: String
val snapshot: StateFlow<ChannelSnapshot>
val tracks: StateFlow<List<ChannelTrack>>
suspend fun refresh()
suspend fun setMicrophoneEnabled(on: Boolean)
suspend fun setCameraEnabled(on: Boolean)
suspend fun leave()
}入口为 DRClient.channels: ChannelsModule。im-call 提供 DRChannelVideoView,其 bind(handle, track) / unbind() 负责画面渲染,结束页面仍须调用 leave。类型见数据类型,权限和生命周期见频道接入。
