@tencentcloud/sdk-mcp 1.4.1 → 1.4.3-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. package/package.json +1 -1
  2. package/resource/doc/callkit/core-sdk/android/answer-call.md +942 -0
  3. package/resource/doc/callkit/core-sdk/android/make-call.md +876 -0
  4. package/resource/doc/callkit/core-sdk/android/offline-push.md +368 -0
  5. package/resource/doc/callkit/core-sdk/flutter/answer-call.md +1132 -0
  6. package/resource/doc/callkit/core-sdk/flutter/make-call.md +1206 -0
  7. package/resource/doc/callkit/core-sdk/flutter/offline-push.md +357 -0
  8. package/resource/doc/callkit/core-sdk/ios/answer-call.md +1009 -0
  9. package/resource/doc/callkit/core-sdk/ios/make-call.md +1154 -0
  10. package/resource/doc/callkit/core-sdk/ios/offline-push.md +470 -0
  11. package/resource/doc/callkit/core-sdk/uni-app/answer-call.md +1146 -0
  12. package/resource/doc/callkit/core-sdk/uni-app/make-call.md +1267 -0
  13. package/resource/doc/callkit/preset/android/integration.md +1 -1
  14. package/resource/doc/callkit/preset/flutter/integration.md +1 -1
  15. package/resource/doc/callkit/preset/ios/integration.md +1 -1
  16. package/resource/doc/callkit/preset/react/api.md +1 -1
  17. package/resource/doc/callkit/preset/vue/api.md +1 -1
  18. package/tools/call/get_native_callkit_core_integration.js +67 -0
  19. package/tools/call/get_native_callkit_core_integration.js.map +1 -0
  20. package/tools/common/present_framework_choice.js +1 -1
  21. package/tools/common/present_framework_choice.js.map +1 -1
  22. package/tools/common/record_skill_session.js +17 -6
  23. package/tools/common/record_skill_session.js.map +1 -1
  24. package/tools/definitions/get_native_call_uikit_integration_def.js +9 -3
  25. package/tools/definitions/get_native_call_uikit_integration_def.js.map +1 -1
  26. package/tools/definitions/get_native_callkit_core_integration_def.js +63 -0
  27. package/tools/definitions/get_native_callkit_core_integration_def.js.map +1 -0
  28. package/tools/index.js +2 -0
  29. package/tools/index.js.map +1 -1
  30. package/utils/report-cls-client.js +1 -1
  31. package/utils/report-cls-client.js.map +1 -1
  32. package/utils/report-es-client.js +1 -1
  33. package/utils/report-es-client.js.map +1 -1
  34. package/utils/report-runtime-error-cls-client.js +91 -0
  35. package/utils/report-runtime-error-cls-client.js.map +1 -0
@@ -0,0 +1,470 @@
1
+ 本文档将指导您如何基于 TIMPush 服务实现 VoIP 推送功能,适用于使用 AtomicXCore 进行无 UI 集成的场景。
2
+
3
+ **注意:** 使用 VoIP 推送功能首先需要开通 TIMPush 服务。
4
+
5
+ LiveCommunicationKit 需要在 **iOS 17.4 及以上系统**中使用。
6
+
7
+ VoIP Push 无法复用 APNs 普通推送证书,需要单独在苹果开发者网站上申请 VoIP Push 证书。
8
+
9
+ ## 集成效果
10
+
11
+ 按照本文档接入 Apple LiveCommunicationKit 后,您的 App 将瞬间拥有微信同款的原生通话能力,在进程关闭或锁屏状态下,也能无差别唤醒系统级全屏接听界面:
12
+
13
+ ## 准备条件
14
+
15
+ ### 开通服务
16
+
17
+ 进入 IM 控制台 > 插件市场,单击**立即购买**或**免费试用**(每个应用可免费试用一次,有效期7天)。
18
+
19
+ > **注意:** 推送插件试用或购买到期后,将自动停止提供推送服务(包括普通消息离线推送、全员/标签推送等)。为避免影响业务正常使用,请提前购买或续费。
20
+
21
+ ### 厂商配置
22
+
23
+ #### 步骤1:申请 VoIP Push 证书
24
+
25
+ 在申请 VoIP Push 证书之前,请先在苹果开发者中心开启 App 的远程推送功能。当 AppID 具备了 Push Notification 能力后,按如下步骤操作:
26
+
27
+ 1. 登录苹果开发者中心,单击 **Certificates, IDs & Profiles**
28
+ 2. 单击 Certificates 右侧的 **+**
29
+ 3. 在 **Create a New Certificate** 中,选择 **VoIP Services Certificate**,单击 **Continue**
30
+ 4. 在 **Select an App ID for your VoIP Service Certificate** 中,选择当前 App 的 BundleID,单击 **Continue**
31
+ 5. 系统提示需要一个 **Certificate Signing Request(CSR)**
32
+ 6. 制作 CSR 文件:Mac 上打开**钥匙串访问工具**,菜单选择 **钥匙串访问 > 证书助理 > 从证书颁发机构请求证书**
33
+ 7. 输入用户电子邮件地址、常用名称,选择**存储到磁盘**,单击继续,生成 `*.certSigningRequest` 文件
34
+ 8. 返回 Apple Developer 网站,上传 `*.certSigningRequest` 文件,单击 Continue 生成证书,点击 Download 下载
35
+ 9. 双击打开 `voip_services.cer`,系统将其导入钥匙串
36
+ 10. 打开钥匙串应用,在 **登录 > 我的证书**,右键导出 VoIP Services 的 **P12** 文件
37
+
38
+ > **说明:** 保存 P12 文件时,请务必为其设置密码。
39
+
40
+ #### 步骤2:上传证书到 IM 控制台
41
+
42
+ 登录 IM 控制台,选择 IM 应用,按如下步骤上传证书:
43
+
44
+ 1. 选择 IM 应用,进入应用的**接入设置**
45
+ 2. 在**厂商配置**中,切换到 **iOS**,点击**添加证书**,上传 iOS 证书(p12),设置证书密码,单击**确认**
46
+ 3. 上传完成后,**记录不同环境下的证书 ID**
47
+
48
+ > **说明:**
49
+ > - 添加证书时,推送类型默认为 APNs,不影响 VoIP 证书的上传和使用。
50
+ > - VoIP Push 证书本身不区分生产环境和测试环境,生产环境和开发环境使用同一份证书,请分别上传
51
+ > - 上传证书名最好使用全英文(不能使用括号等特殊字符)
52
+ > - 上传证书需要设置密码,无密码收不到推送
53
+ > - 发布 App Store 的证书需要设置为生产环境,否则无法收到推送
54
+ > - 上传的 p12 证书必须是自己申请的真实有效的证书
55
+ > - 开发环境和生产环境下的证书 ID 要严格区分
56
+
57
+ ## 功能接入
58
+
59
+ ### 步骤1:完成工程配置
60
+
61
+ 1. 在工程的 **Capability** 中添加 **Push Notification** 能力
62
+ 2. 在工程 Capability 的 **Background Modes** 中,开启 **Voice over IP** 选项
63
+
64
+ ### 步骤2:添加依赖
65
+
66
+ **1. 添加 Pod 依赖:** 在 `Podfile` 文件中添加:
67
+
68
+ ```ruby
69
+ pod 'TUICore'
70
+ ```
71
+
72
+ **2. 安装组件:** 在终端进入 `Podfile` 所在目录,执行:
73
+
74
+ ```bash
75
+ pod install --repo-update
76
+ ```
77
+
78
+ ### 步骤3:初始化 PushKit 并设置证书 ID
79
+
80
+ 创建一个类来管理 VoIP 推送,初始化 PushKit 用于接收 VoIP 推送通知:
81
+
82
+ ```swift
83
+ import PushKit
84
+ import ImSDK_Plus
85
+ import LiveCommunicationKit
86
+
87
+ class VoIPPushManager: NSObject {
88
+ private let pushRegistry: PKPushRegistry
89
+ private var certificateID: Int = 0
90
+ private var voipToken: Data? // 保存 Token,待 TUILogin 成功后上报
91
+
92
+ private var currentCallUUID: UUID?
93
+
94
+ // ConversationManager:用于步骤 7 展示系统来电界面
95
+ private lazy var conversationManager: ConversationManager = {
96
+ let configuration = ConversationManager.Configuration(
97
+ ringtoneName: "phone_ringing.mp3", // 来电铃声文件名
98
+ iconTemplateImageData: nil, // 来电图标(可选)
99
+ supportsVideo: true // 是否支持视频通话
100
+ )
101
+ let manager = ConversationManager(configuration: configuration)
102
+ manager.delegate = self
103
+ return manager
104
+ }()
105
+
106
+ override init() {
107
+ pushRegistry = PKPushRegistry(queue: DispatchQueue.main)
108
+ super.init()
109
+ pushRegistry.delegate = self
110
+ pushRegistry.desiredPushTypes = [.voIP]
111
+
112
+ NotificationCenter.default.addObserver(
113
+ self,
114
+ selector: #selector(onTUILoginSuccess),
115
+ name: NSNotification.Name("TUILoginSuccess"),
116
+ object: nil
117
+ )
118
+ }
119
+
120
+ deinit {
121
+ NotificationCenter.default.removeObserver(self)
122
+ }
123
+
124
+ func setCertificateID(_ certificateID: Int) {
125
+ self.certificateID = certificateID
126
+ }
127
+
128
+ @objc private func onTUILoginSuccess() {
129
+ uploadVoIPToken()
130
+ }
131
+
132
+ private func uploadVoIPToken() {
133
+ guard let token = voipToken else {
134
+ return
135
+ }
136
+ guard certificateID != 0 else {
137
+ return
138
+ }
139
+
140
+ let config = V2TIMVOIPConfig()
141
+ config.certificateID = certificateID
142
+ config.token = token
143
+
144
+ V2TIMManager.sharedInstance().setVOIP(config: config, succ: {
145
+ // VoIP Token 上报成功
146
+ }, fail: { code, desc in
147
+ // VoIP Token 上报失败
148
+ })
149
+ }
150
+ }
151
+ ```
152
+
153
+ 在 `AppDelegate` 中初始化并设置证书 ID:
154
+
155
+ ```swift
156
+ class AppDelegate: UIResponder, UIApplicationDelegate {
157
+ private lazy var voipPushManager: VoIPPushManager = {
158
+ let manager = VoIPPushManager()
159
+ manager.setCertificateID(1234) // 替换为您在 IM 控制台获取的证书 ID
160
+ return manager
161
+ }()
162
+
163
+ func application(_ application: UIApplication,
164
+ didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
165
+ _ = voipPushManager
166
+ return true
167
+ }
168
+ }
169
+ ```
170
+
171
+ > **注意:**
172
+ > - `certificateID` 是您在 IM 控制台上传证书后获取的证书 ID
173
+ > - 开发环境和生产环境的证书 ID 要严格区分
174
+
175
+ ### 步骤4:获取并保存 VoIP Token
176
+
177
+ 实现 `PKPushRegistryDelegate` 代理方法,获取到 VoIP Token 后先保存,等待 TUILogin 成功后再上报:
178
+
179
+ ```swift
180
+ import PushKit
181
+ import ImSDK_Plus
182
+
183
+ extension VoIPPushManager: PKPushRegistryDelegate {
184
+ func pushRegistry(_ registry: PKPushRegistry,
185
+ didUpdate pushCredentials: PKPushCredentials,
186
+ for type: PKPushType) {
187
+ guard type == .voIP else { return }
188
+
189
+ // 保存 token
190
+ voipToken = pushCredentials.token
191
+
192
+ let tokenString = pushCredentials.token.map { String(format: "%02.2hhx", $0) }.joined()
193
+
194
+ // 如果 TUILogin 已经完成,立即上报
195
+ uploadVoIPToken()
196
+ }
197
+
198
+ func pushRegistry(_ registry: PKPushRegistry,
199
+ didInvalidatePushTokenFor type: PKPushType) {
200
+ // VoIP Token 已失效
201
+ }
202
+ }
203
+ ```
204
+
205
+ > **注意:** VoIP Token 的上报必须在 IM SDK 登录成功后才能进行,因此不宜在首次获取 Token 的回调里假设登录已完成。
206
+
207
+ ### 步骤5:Token 上报
208
+
209
+ 在用户登录时,需要先登录 IM SDK,再登录 TUICore。TUICore 登录成功后会发送 `TUILoginSuccess` 通知,`VoIPPushManager` 监听到该通知后会自动上报 VoIP Token:
210
+
211
+ ```swift
212
+ import TUICore
213
+ import AtomicXCore
214
+
215
+ // 步骤1:登录 IM SDK(AtomicXCore 的 LoginStore)
216
+ LoginStore.shared.login(
217
+ sdkAppID: sdkAppID,
218
+ userID: userID,
219
+ userSig: userSig
220
+ ) { result in
221
+ switch result {
222
+ case .success:
223
+ // 步骤2:登录 TUICore
224
+ TUILogin.login(
225
+ sdkAppID,
226
+ userID: userID,
227
+ userSig: userSig
228
+ ) {
229
+ // TUICore 登录成功,触发 VoIP Token 上报
230
+ NotificationCenter.default.post(
231
+ name: NSNotification.Name("TUILoginSuccess"),
232
+ object: nil
233
+ )
234
+ } fail: { code, message in
235
+ // TUICore 登录失败
236
+ }
237
+ case .failure(let error):
238
+ // IM SDK 登录失败
239
+ }
240
+ }
241
+ ```
242
+
243
+ ### 步骤6:接收 VoIP 推送通知
244
+
245
+ 实现 PKPushRegistryDelegate 代理方法,收到 VoIP 推送时必须在 5 秒内向系统报告来电,否则会 crash。
246
+
247
+ ```swift
248
+ extension VoIPPushManager: PKPushRegistryDelegate {
249
+ func pushRegistry(_ registry: PKPushRegistry,
250
+ didReceiveIncomingPushWith payload: PKPushPayload,
251
+ for type: PKPushType) {
252
+ guard type == .voIP else { return }
253
+
254
+ // 必须在 5 秒内向系统报告来电,否则会 crash
255
+ showIncomingCall(with: payload)
256
+ }
257
+ }
258
+ ```
259
+
260
+ ### 步骤7:展示来电通知
261
+
262
+ 使用 LiveCommunicationKit 向系统报告来电,系统自动展示原生来电界面:
263
+
264
+ ```swift
265
+ import LiveCommunicationKit
266
+
267
+ extension VoIPPushManager {
268
+ private func showIncomingCall(with payload: PKPushPayload) {
269
+ // 解析推送数据
270
+ let payloadDict = payload.dictionaryPayload
271
+
272
+ // 1. 获取来电者名称(必需字段)
273
+ guard let callerName = payloadDict["voip_caller_name"] as? String else {
274
+ return
275
+ }
276
+
277
+ // 2. 解析 ext 字段获取通话类型(音频/视频)
278
+ var isVideoCall = false
279
+ if let extString = payloadDict["ext"] as? String,
280
+ let extData = extString.data(using: .utf8),
281
+ let extDic = try? JSONSerialization.jsonObject(with: extData) as? [String: Any],
282
+ let voipExtDic = extDic["voip_ext"] as? [String: String],
283
+ let mediaType = voipExtDic["voip_media_type"] {
284
+ isVideoCall = (mediaType == "video")
285
+ }
286
+
287
+ // 创建来电通知内容
288
+ let uuid = UUID()
289
+ currentCallUUID = uuid
290
+
291
+ var update = Conversation.Update(
292
+ members: [Handle(type: .generic, value: callerName, displayName: callerName)]
293
+ )
294
+ update.capabilities = isVideoCall ? .video : .playingTones
295
+
296
+ // 向系统报告来电(系统自动展示原生来电界面)
297
+ Task {
298
+ do {
299
+ try await conversationManager.reportNewIncomingConversation(uuid: uuid, update: update)
300
+ } catch {
301
+ // 报告失败
302
+ }
303
+ }
304
+ }
305
+ }
306
+
307
+ // MARK: - ConversationManagerDelegate
308
+ extension VoIPPushManager: ConversationManagerDelegate {
309
+ func conversationManager(_ manager: ConversationManager, perform action: ConversationAction) {
310
+ if action is JoinConversationAction {
311
+ // 用户点击"接听"
312
+ CallStore.shared.accept { result in
313
+ switch result {
314
+ case .success:
315
+ // 接听成功,可在此跳转到通话页面
316
+ break
317
+ case .failure(let error):
318
+ break
319
+ }
320
+ }
321
+ } else if action is EndConversationAction {
322
+ // 用户点击"挂断"
323
+ CallStore.shared.hangup { result in
324
+ switch result {
325
+ case .success:
326
+ break
327
+ case .failure(let error):
328
+ break
329
+ }
330
+ }
331
+ }
332
+
333
+ // 必须调用 fulfill() 通知系统操作已完成
334
+ action.fulfill()
335
+ }
336
+ }
337
+ ```
338
+
339
+ 您可以通过配置 `Conversation.Update` 的参数,自定义来电界面显示的来电者信息、通话类型等内容。
340
+
341
+ **`Conversation.Update` 参数说明:**
342
+
343
+ | 参数 | 类型 | 是否必需 | 说明 |
344
+ |------|------|----------|------|
345
+ | `members` | [Handle] | 必需 | 来电者信息数组,支持多人通话场景。每个 Handle 包含:`type`通常使用 `.generic`;`value`来电者唯一标识(建议使用用户 ID);`displayName`显示在来电界面的名称 |
346
+ | `capabilities` | Conversation.Capabilities | 必需 | 通话类型:`.video`为视频通话(显示视频图标);`.playingTones`为语音通话(显示语音图标) |
347
+
348
+ 说明:用户点击「接听」或「挂断」后,系统会回调 [ConversationManagerDelegate](https://developer.apple.com/documentation/livecommunicationkit/conversationmanagerdelegate),您需在回调中处理接听/挂断逻辑(例如跳转通话页、调用 [CallStore](https://tencent-rtc.github.io/TUIKit_iOS/documentation/atomicxcore/callstore) 等)。
349
+
350
+ 参考资料:[Apple LiveCommunicationKit 文档](https://developer.apple.com/documentation/livecommunicationkit)。
351
+
352
+ ## 发起 VoIP 通话
353
+
354
+ ### 发起通话
355
+
356
+ `AtomicXCore` 的 `CallStore` 已经默认使用 VoIP 推送,您不需要手动设置 `offlinePushInfo` 参数。`CallStore` 内部会自动配置以下推送信息:
357
+
358
+ - **推送类型:** `.voIP`
359
+ - **推送标题:** 当前用户 ID
360
+ - **推送描述:** `"You have a new call"`
361
+ - **iOS 铃声:** `phone_ringing.mp3`
362
+
363
+ ```swift
364
+ import AtomicXCore
365
+
366
+ // 构造通话参数(不需要设置 offlinePushInfo)
367
+ var params = CallParams()
368
+ params.timeout = 30 // 超时时间(秒)
369
+ params.userData = "自定义数据" // 扩展信息(可选)
370
+
371
+ // 发起通话
372
+ let userIdList = ["被叫用户的 userID"]
373
+ let mediaType = CallMediaType.video // .video 视频通话,.audio 语音通话
374
+
375
+ CallStore.shared.calls(
376
+ participantIds: userIdList,
377
+ callMediaType: mediaType,
378
+ params: params
379
+ ) { result in
380
+ switch result {
381
+ case .success:
382
+ // 通话发起成功,可跳转到您自己的通话页面
383
+ break
384
+ case .failure(let error):
385
+ // 通话失败处理
386
+ break
387
+ }
388
+ }
389
+ ```
390
+
391
+ > **说明:VoIP 推送降级策略**
392
+ >
393
+ > 当使用 VoIP 推送时,后台会智能判断证书类型,保证用户仍能收到推送通知:
394
+ > - 上传的是 VoIP 证书:发送 VoIP Push
395
+ > - 上传的是 APNs 证书:自动降级为 APNs 推送
396
+
397
+ ### 接听通话
398
+
399
+ 当被叫用户离线时收到 VoIP 推送并点击接听,系统会唤醒您的 App。此时需要监听通话事件并跳转到您自己实现的通话页面。
400
+
401
+ ```swift
402
+ import AtomicXCore
403
+ import Combine
404
+
405
+ class YourViewController: UIViewController {
406
+ private var cancellables = Set<AnyCancellable>()
407
+
408
+ override func viewDidLoad() {
409
+ super.viewDidLoad()
410
+
411
+ CallStore.shared.callEventPublisher
412
+ .receive(on: DispatchQueue.main)
413
+ .sink { [weak self] event in
414
+ guard let self = self else { return }
415
+ switch event {
416
+ case .onCallReceived(let callId, let mediaType, let userData):
417
+ // 收到来电,跳转到您自己的通话页面
418
+ self.showCallViewController(callId: callId, mediaType: mediaType, userData: userData)
419
+ case .onCallEnded(let callId, let mediaType, let reason, let userId):
420
+ // 通话结束,返回或更新 UI
421
+ self.dismissCallViewController()
422
+ case .onCallStarted(let callId, let mediaType):
423
+ // 通话已开始
424
+ break
425
+ }
426
+ }
427
+ .store(in: &cancellables)
428
+ }
429
+
430
+ private func showCallViewController(callId: String, mediaType: CallMediaType, userData: String) {
431
+ // 跳转到您自己的通话页面
432
+ let callVC = YourCallViewController()
433
+ callVC.callId = callId
434
+ callVC.mediaType = mediaType
435
+ callVC.userData = userData
436
+ callVC.modalPresentationStyle = .fullScreen
437
+ present(callVC, animated: true)
438
+ }
439
+
440
+ private func dismissCallViewController() {
441
+ // 关闭通话页面
442
+ dismiss(animated: true)
443
+ }
444
+ }
445
+ ```
446
+
447
+ ## 常见问题
448
+
449
+ ### 获取不到 VoIP Push,如何处理?
450
+
451
+ 1. **检查登录顺序:** 必须先登录 IM SDK,再登录 TUICore,否则 VoIP Token 无法上报(参考步骤 5)。
452
+ 2. 检查 App 的运行环境与证书环境是否一致,证书 ID 是否匹配;不一致则无法收到推送。
453
+ 3. 确认当前登录账号是否处于离线状态:按 Home 切后台、登录后主动杀进程退出。VoIP Push 目前只支持离线状态下的推送。
454
+ 4. 检查**完成工程配置**(步骤 1)是否正确。
455
+ 5. **尝试重启测试手机**以清除系统缓存和内存(很重要)。
456
+ 6. IM 控制台提供推送排查工具,帮助您快速排查推送问题,使用方式详见:Push 排查工具。(很重要)
457
+
458
+ ### 应用在收到 VoIP 推送后 crash 怎么办?
459
+
460
+ 这通常是因为没有在 5 秒内向系统发送展示通知的请求。请确保在 `didReceiveIncomingPushWith` 回调中立即调用 `reportNewIncomingConversation` 方法。
461
+
462
+ ### 如何自定义来电通知的内容?
463
+
464
+ 您可以通过 `Conversation.Update` 自定义来电通知,包括:
465
+
466
+ - 来电者信息(`displayName`)
467
+ - 通话类型(`capabilities`:`.video` 或 `.playingTones`)
468
+ - 其他自定义信息
469
+
470
+ 具体用法请参考 [Apple LiveCommunicationKit](https://developer.apple.com/documentation/livecommunicationkit) 官方文档。