feat(mobile-next): 迁移 Android 一对一语音通话薄适配与入口
复用官方 OpenIMLive 信令与房间,换票改走账号服务 /api/rtc_token;入口仅音频,占线/超时/重复回调与销毁释放由公司层防护。 Co-authored-by: Cursor <cursoragent@cursor.com> Co-authored-by: multica-agent <github@multica.ai>
This commit is contained in:
co-authored by
Cursor
multica-agent
parent
2a817e77d8
commit
3832e080c4
@@ -0,0 +1,42 @@
|
||||
/// 把账号服务 `/api/rtc_token` 的响应收成进房凭证。
|
||||
///
|
||||
/// 现网成功体:`{ code: 0, data: { token } }`,可选 `liveURL` / `serverUrl`。
|
||||
/// 缺少直播地址时由调用方填 [fallbackLiveUrl],不得改服务端。
|
||||
class CompanyRtcCredential {
|
||||
const CompanyRtcCredential({required this.token, required this.liveURL});
|
||||
|
||||
final String token;
|
||||
final String liveURL;
|
||||
}
|
||||
|
||||
class RtcTokenMapper {
|
||||
RtcTokenMapper._();
|
||||
|
||||
static CompanyRtcCredential parse(
|
||||
dynamic body, {
|
||||
required String fallbackLiveUrl,
|
||||
}) {
|
||||
if (body is! Map) {
|
||||
throw const FormatException('语音通话凭证格式不正确');
|
||||
}
|
||||
final map = Map<String, dynamic>.from(body);
|
||||
final code = map['code'];
|
||||
if (code != null && code != 0) {
|
||||
final msg = map['msg']?.toString() ?? '';
|
||||
throw FormatException(msg.isNotEmpty ? msg : '获取通话凭证失败');
|
||||
}
|
||||
final data = map['data'];
|
||||
final payload = data is Map ? Map<String, dynamic>.from(data) : map;
|
||||
final token = payload['token']?.toString() ?? '';
|
||||
if (token.isEmpty) {
|
||||
throw const FormatException('服务器未返回通话凭证');
|
||||
}
|
||||
final live = payload['liveURL']?.toString() ??
|
||||
payload['serverUrl']?.toString() ??
|
||||
'';
|
||||
return CompanyRtcCredential(
|
||||
token: token,
|
||||
liveURL: live.isNotEmpty ? live : fallbackLiveUrl,
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user