@tencent-rtc/mcp 1.7.2 → 1.7.4

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 (49) hide show
  1. package/CHANGELOG.md +26 -0
  2. package/README.md +25 -17
  3. package/knowledge/bm25.js +20 -11
  4. package/knowledge/path-meta.js +23 -1
  5. package/knowledge/search/generic-rerank.js +123 -0
  6. package/knowledge/search/search-pass.js +8 -1
  7. package/package.json +1 -1
  8. package/resource/index/manifest.json +1 -1
  9. package/resource/knowledge/callkit/best-practice/android/video-chat-dating.md +497 -0
  10. package/resource/knowledge/callkit/best-practice/flutter/android-keep-call-alive-background.md +79 -0
  11. package/resource/knowledge/callkit/best-practice/flutter/background-incoming-call-no-notification.md +99 -0
  12. package/resource/knowledge/callkit/best-practice/flutter/ios-keep-call-alive-background.md +93 -0
  13. package/resource/knowledge/callkit/best-practice/flutter/ios-startup-crash-version-voip.md +68 -0
  14. package/resource/knowledge/callkit/core-sdk/miniprogram/call-engine.md +386 -0
  15. package/resource/knowledge/callkit/core-sdk/miniprogram/call-event.md +315 -0
  16. package/resource/knowledge/callkit/faq/uniapp-miniprogram.md +204 -0
  17. package/resource/knowledge/callkit/preset/harmonyos/api.md +362 -0
  18. package/resource/knowledge/callkit/preset/harmonyos/integration.md +318 -0
  19. package/resource/knowledge/callkit/preset/miniprogram/api-uniapp.md +430 -0
  20. package/resource/knowledge/callkit/preset/miniprogram/api.md +293 -0
  21. package/resource/knowledge/callkit/preset/miniprogram/integration.md +294 -0
  22. package/resource/knowledge/callkit/preset/miniprogram/uniapp-integration.md +224 -0
  23. package/resource/knowledge/callkit/preset/uni-app/api.md +339 -0
  24. package/resource/knowledge/callkit/preset/uni-app/integration.md +243 -0
  25. package/resource/knowledge/chat/best-practice/common/web-sdk-log-level.md +76 -0
  26. package/resource/knowledge/chat/best-practice/miniprogram/desktop-wechat-miniprogram-error.md +79 -0
  27. package/resource/knowledge/chat/preset/react/h5/integration.md +964 -0
  28. package/resource/knowledge/chat/preset/vue/h5/integration.md +717 -0
  29. package/resource/knowledge/roomkit/best-practice/vue/screen-share-auto-stop-on-leave.md +62 -0
  30. package/resource/knowledge/roomkit/core-sdk/react/network-proxy.md +83 -0
  31. package/resource/knowledge/roomkit/core-sdk/vue/network-proxy.md +83 -0
  32. package/resource/knowledge/roomkit/core-sdk/vue/recording.md +245 -0
  33. package/resource/knowledge/roomkit/core-sdk/vue/whiteboard-annotation.md +196 -0
  34. package/resource/knowledge/roomkit/faq/error-code.md +103 -0
  35. package/resource/knowledge/roomkit/preset/harmonyos/integration.md +461 -0
  36. package/resource/knowledge/roomkit/preset/react/features/network-proxy.md +79 -0
  37. package/resource/knowledge/roomkit/preset/uniapp-app/integration.md +580 -0
  38. package/resource/knowledge/roomkit/preset/vue/features/ai-caption-translation.md +69 -0
  39. package/resource/knowledge/roomkit/preset/vue/features/ai-denoiser.md +67 -0
  40. package/resource/knowledge/roomkit/preset/vue/features/network-proxy.md +79 -0
  41. package/resource/knowledge/roomkit/preset/vue/features/recording.md +85 -0
  42. package/resource/knowledge/roomkit/preset/vue/features/whiteboard-annotation.md +86 -0
  43. package/resource/knowledge/rtcengine/web/plugin/23-advanced-support-detection.md +6 -6
  44. package/resource/knowledge/rtcengine/web/plugin/31-advanced-plugins-overview.md +8 -6
  45. package/resource/knowledge/rtcengine/web/plugin/42-advanced-realtime-transcriber.md +30 -10
  46. package/server.js +1 -1
  47. package/utils/preflight-route.js +18 -6
  48. package/utils/report-cls-client.js +1 -1
  49. package/utils/report-es-client.js +1 -1
@@ -0,0 +1,497 @@
1
+ ---
2
+ title: Android 1v1 Video Chat Dating — Quick Start (VideoChat Demo Setup & Component Integration)
3
+ product: call
4
+ frameworks: [android]
5
+ scope: platform_specific
6
+ tags: [video chat, 1v1, VideoChat, dating, video-chat-solution, TUICallKit, Android, Demo, quick start, social, beauty filter, offline push, call reachability]
7
+ ---
8
+
9
+ This guide walks you through running the video calling Demo quickly. Following this document, you can get the Demo running in 10 minutes and experience a fully-featured 1v1 video chat dating app with a complete UI.
10
+
11
+ ## Prerequisites
12
+
13
+ ### Environment Setup
14
+ - Install [Android Studio](https://developer.android.com/studio).
15
+
16
+ - Two or more Android 5.0+ devices.
17
+
18
+ ### Activate the Service
19
+
20
+ ## Run the Demo
21
+
22
+ ### Step 1: Download the Demo
23
+
24
+ You can download the [VideoChat Demo](https://github.com/Tencent-RTC/video-chat-solution) source code directly from GitHub, or run the following command:
25
+ ``` java
26
+ git clone https://github.com/Tencent-RTC/video-chat-solution.git
27
+ ```
28
+
29
+ ### Step 2: Configure the Demo
30
+ 1. **Configure SDKAppID and SecretKey (required):** Open the file `video-chat-solution/blob/main/android/app/src/main/java/io/trtc/uikit/demo/debug/GenerateTestUserSig.java` and fill in the `SDKAppID` and `SDKSecretKey` obtained during service activation.
31
+
32
+ 2. **Configure Beauty Filters (optional):** The Demo includes Tencent basic beauty filters by default, which require a License to take effect. Refer to the [License Guide](https://cloud.tencent.com/document/product/616/79137) to obtain the LicenseURL and LicenseKey, and fill them into `video-chat-solution/android/app/src/main/java/io/trtc/uikit/demo/debug/GenerateTestUserSig.java`.
33
+
34
+ ### Step 3: Run the Demo
35
+ 1. **Import recommended test users:** For a quick trial, run the script `video-chat-solution/tools/import_users_to_video_chat.py` (fill in your AppID and SecretKey). The script will automatically register 6 recommended test accounts. After logging in, you can see them in the "Dating" module.
36
+
37
+ 2. **Build and run:** Select a device and run the Demo.
38
+
39
+ 3. **Demo running successfully:** After logging in, the following screen is displayed.
40
+
41
+ ### Step 4: Video and Chat Interaction
42
+ 1. **Interact with recommended users:** You can use another device B to log in with a "recommended user" account (e.g., UserID: VideoChatlinxiaoyu) to complete 1v1 chat and video interaction.
43
+
44
+ - **Device A:** Log in and follow the recommended user "Chen Kexin", then start chatting and video calling.
45
+
46
+ - **Device B:** Log in and start chatting and video calling.
47
+
48
+ ## Quick Integration
49
+
50
+ For fast deployment, you can directly integrate the UI components from the Demo to implement core features like 1v1 chat and calling.
51
+
52
+ ### Step 1: Integrate Components
53
+ 1. Download the [VideoChat Demo](https://github.com/Tencent-RTC/video-chat-solution) source code from the GitHub repository, and copy the `video-chat` and `tuikit` components to your project directory.
54
+
55
+ 2. Add the following code to `settings.gradle` to complete the integration:
56
+
57
+ ``` java
58
+ // Import the top-level application module
59
+ include ':app'
60
+
61
+ // Import the 1v1 video chat dating UI module
62
+ include ':video-chat'
63
+
64
+ // Import the common module
65
+ include(":atomic_x")
66
+ project(":atomic_x").projectDir = file("./tuikit/atomic_x")
67
+
68
+ // Import the chat module
69
+ include ':tuichat'
70
+ project(':tuichat').projectDir = file("./tuikit/chat")
71
+
72
+ // Import the beauty filter module
73
+ include ':tebeautykit'
74
+ project(':tebeautykit').projectDir = file("./tuikit/tebeautykit")
75
+
76
+ // Import the effects player module
77
+ include ':tceffectplayerkit'
78
+ project(':tceffectplayerkit').projectDir = file("./tuikit/tceffectplayerkit")
79
+ ```
80
+
81
+ ### Step 2: Complete Login
82
+
83
+ Authentication is required before using component features. Call the LoginStore `login` API with the sdkAppID, userID, and userSig obtained above:
84
+ ``` java
85
+
86
+ import io.trtc.tuikit.atomicxcore.api.CompletionHandler
87
+ import io.trtc.tuikit.atomicxcore.api.login.LoginStore
88
+
89
+ LoginStore.shared.login(
90
+ context,
91
+ sdkAppID, // Int, obtained from the console
92
+ userID, // String
93
+ userSig, // String, generated from the console or server
94
+ object : CompletionHandler {
95
+ override fun onSuccess() {
96
+ // Login successful, navigate to conversation list or chat page
97
+ }
98
+ override fun onFailure(code: Int, desc: String) {
99
+ // Login failed, show error dialog
100
+ }
101
+ }
102
+ )
103
+ ```
104
+
105
+ > **Note:**
106
+ > In production environments, it is recommended to generate UserSig on your server. The app requests a dynamic UserSig from the backend when needed. See Server-side UserSig Generation.
107
+ >
108
+
109
+ ### Step 3: Build the Recommended Users List
110
+
111
+ 1. **Add the page:** Add the "Recommended Users List (MeetPage)" to your project:
112
+
113
+ ``` java
114
+ import com.tencent.qcloud.tuikit.videochat.page.meet.MeetPage
115
+
116
+ class MeetPageFragment : Fragment() {
117
+ override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
118
+ super.onViewCreated(view, savedInstanceState)
119
+ addMeetPage()
120
+ }
121
+
122
+ private fun addMeetPage() {
123
+ val meetPage = MeetPage(requireContext())
124
+ val container = findViewById<FrameLayout>(R.id.meet_container)
125
+ container.addView(meetPage, MATCH_PARENT, MATCH_PARENT)
126
+ }
127
+ }
128
+ ```
129
+ 2. **Provide data:** You can use `setPageUsers` to provide the recommended user list, and listen for pull-up refresh (`onLoadMoreRequested`) to append users and pull-down refresh (`onRefreshRequested`) to fully update the user list.
130
+
131
+ ``` java
132
+ import com.tencent.qcloud.tuikit.videochat.page.meet.MeetPage
133
+
134
+ meetPage.setListener(object : MeetPage.Listener {
135
+ // Triggered on pull-down refresh
136
+ override fun onRefreshRequested() {
137
+ // Full update of user list
138
+ fetchUsers { users, hasMore ->
139
+ // Set user list
140
+ meetPage.setPageUsers(users, hasMore)
141
+ }
142
+ }
143
+
144
+ // Triggered on pull-up refresh
145
+ override fun onLoadMoreRequested() {
146
+ // Append new users at the end
147
+ fetchNextPage { users, hasMore ->
148
+ // Set user list
149
+ meetPage.setPageUsers(users, hasMore)
150
+ }
151
+ }
152
+ })
153
+ ```
154
+ - **setPageUsers details:**
155
+
156
+ ``` java
157
+ fun setPageUsers(users: List<V2TIMUserFullInfo>, hasMore: Boolean)
158
+ ```
159
+ | **Parameter** | **Type** | **Description** |
160
+ | --- | --- | --- |
161
+ | users | List<[V2TIMUserFullInfo](https://im.sdk.qcloud.com/doc/zh-cn/classcom_1_1tencent_1_1imsdk_1_1v2_1_1V2TIMUserFullInfo.html)> | User list. [V2TIMUserFullInfo](https://im.sdk.qcloud.com/doc/zh-cn/classcom_1_1tencent_1_1imsdk_1_1v2_1_1V2TIMUserFullInfo.html) contains user ID, nickname, avatar, gender, and other key information. |
162
+ | hasMore | Boolean | Whether there is a next page:<br>- true: more pages available, scrolling to the bottom will trigger onLoadMoreRequested()<br>- false: no more data, scrolling to the bottom will not trigger the callback |
163
+
164
+ 3. **Switch layout (optional):** MeetPage provides two layout modes — "Card" and "List". You can use `setLayoutTemplate` to choose your preferred layout.
165
+
166
+ ``` java
167
+ import com.tencent.qcloud.tuikit.videochat.page.meet.MeetPage
168
+
169
+ class MeetPageFragment : Fragment() {
170
+ override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
171
+ super.onViewCreated(view, savedInstanceState)
172
+ addMeetPage()
173
+ }
174
+
175
+ private fun addMeetPage() {
176
+ val meetPage = MeetPage(requireContext())
177
+ // Set layout
178
+ meetPage.setLayoutTemplate(MeetPage.Template.LIST) // List layout (default)
179
+ // meetPage.setLayoutTemplate(MeetPage.Template.GRID) // Card layout
180
+ val container = findViewById<FrameLayout>(R.id.meet_container)
181
+ container.addView(meetPage, MATCH_PARENT, MATCH_PARENT)
182
+ }
183
+ }
184
+ ```
185
+ - **setLayoutTemplate details:**
186
+
187
+ ``` java
188
+ fun setLayoutTemplate(template: MeetPage.Template)
189
+ ```
190
+ | **Parameter** | **Type** | **Description** |
191
+ | --- | --- | --- |
192
+ | template | MeetPage.Template | Layout type:<br>- MeetPage.Template.LIST: List layout.<br>- MeetPage.Template.GRID: Card layout. |
193
+
194
+ ### Step 4: Build the Conversation List
195
+
196
+ The conversation list simply requires creating a `ConversationPage` object and adding it to your layout. The conversation list reads recent chat records from the database. When a user taps a chat record, `ConversationPage` navigates to the chat page by default.
197
+
198
+ - **Sample code:**
199
+
200
+ ``` java
201
+ val conversationPage = ConversationPage()
202
+
203
+ // R.id.container is the FrameLayout in your layout that holds the conversation list Fragment
204
+ supportFragmentManager.beginTransaction()
205
+ .add(R.id.container, conversationPage)
206
+ .commit()
207
+ ```
208
+
209
+ ### Step 5: Build the Chat Page
210
+
211
+ The chat page displays and sends messages. You can build the page as follows:
212
+
213
+ - **Sample code:**
214
+
215
+ ``` java
216
+ Bundle param = new Bundle();
217
+ param.putInt(TUIConstants.TUIChat.CHAT_TYPE, V2TIMConversation.V2TIM_C2C);
218
+ val userId = "jack" // The other party's UserId
219
+ param.putString(TUIConstants.TUIChat.CHAT_ID, userId);
220
+ TUICore.startActivity("TUIC2CChatActivity", param);
221
+ ```
222
+
223
+ ### Step 6: Audio/Video Calling
224
+
225
+ In social entertainment scenarios, call requirements are complex and diverse. We recommend using the [AtomicxCore SDK](https://liteav.sdk.cloudcachetci.com/doc/product/tuikit/atomic-x/android/zh/-atomic-x%20-core%20-a-p-i/io.trtc.tuikit.atomicxcore.api.call/-call-store/index.html) to flexibly customize your calling scenarios. Taking the video-chat module's call page (VideoCallPage) as an example, it is built on the SDK's CallStore module and deeply integrates core UI elements such as beauty filters, follow actions, and participant info display. You can use it as source code reference or integrate it directly into your project to quickly build a custom call interface.
226
+
227
+ - **Initiate a video call — sample code:** You can use [CallStore.calls](https://liteav.sdk.cloudcachetci.com/doc/product/tuikit/atomic-x/android/zh/-atomic-x%20-core%20-a-p-i/io.trtc.tuikit.atomicxcore.api.call/-call-store/calls.html) to initiate a video call and launch the call page on success.
228
+
229
+ ``` java
230
+ // Initiate a video call using AtomicxCore SDK's CallStore.calls
231
+ CallStore.shared.calls(list, mediaType, params, object : CompletionHandler {
232
+ override fun onFailure(code: Int, desc: String) {
233
+ completion?.onFailure(code, desc)
234
+ }
235
+
236
+ override fun onSuccess() {
237
+ completion?.onSuccess()
238
+ // Call succeeded, launch VideoCallPage
239
+ val intent = Intent(context, VideoCallPage::class.java)
240
+ intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
241
+ context.startActivity(intent)
242
+ }
243
+ })
244
+ ```
245
+ - **AtomicxCore SDK call module — core API reference:**
246
+
247
+ | **Module** | **Description** |
248
+ |---------|---------|
249
+ | [CallCoreView](https://liteav.sdk.cloudcachetci.com/doc/product/tuikit/atomic-x/android/zh/-atomic-x%20-core%20-a-p-i/io.trtc.tuikit.atomicxcore.api.view/-call-core-view/index.html) | Core call view component. Automatically listens to CallStore data and renders the video. Provides layout switching, avatar, and icon customization capabilities. |
250
+ | [CallStore](https://liteav.sdk.cloudcachetci.com/doc/product/tuikit/atomic-x/android/zh/-atomic-x%20-core%20-a-p-i/io.trtc.tuikit.atomicxcore.api.call/-call-store/index.html) | Call lifecycle management: make, accept, reject, and hang up calls. Real-time access to participants' audio/video status, call duration, call records, etc. |
251
+ | [DeviceStore](https://liteav.sdk.cloudcachetci.com/doc/product/tuikit/atomic-x/android/zh/-atomic-x%20-core%20-a-p-i/io.trtc.tuikit.atomicxcore.api.device/-device-store/index.html) | Audio/video device control: microphone (on/off, volume), camera (on/off, switch, quality), screen sharing, real-time device status monitoring. |
252
+
253
+ ## More Features
254
+
255
+ You can integrate the following features to enhance your app's competitiveness and deliver a better user experience.
256
+ | **Feature** | **Description** | **Integration Guide** |
257
+ | --- | --- | --- |
258
+ | Call Billing | We provide precise server-side call status callbacks. You can listen to call-start and call-end server callbacks to implement call billing. | - Post-call-start callback<br>- Post-call-end callback |
259
+ | Beauty Filters | We offer two beauty filter solutions: **Basic Beauty** (built-in) and **Advanced Beauty** (requires additional integration and fee). Choose based on your needs. | Integrate Beauty Filters |
260
+ | Voice Effects | TRTC audio voice-changing features and usage scenarios to help developers create rich audio interaction experiences. | Integrate Voice Effects |
261
+ | AI Real-time Translation | An essential feature for going global, helping users break language barriers. | Integrate AI Real-time Translation |
262
+ | Audio/Video Content Moderation | Essential for 1v1 social entertainment apps. Helps moderate audio/video streams and text content to prevent app removal from stores. | - [Audio/Video Content Moderation](https://cloud.tencent.com/document/product/647/77791)<br>- [Text Content Moderation](https://cloud.tencent.com/document/product/269/103732) |
263
+
264
+ ## FAQ
265
+
266
+ ### Why are the Demo's beauty filters not working?
267
+
268
+ The Demo includes built-in beauty filter functionality, but it requires License authentication. Please check whether the `LicenseURL` and `LicenseKey` in `video-chat-solution/android/app/src/main/java/io/trtc/uikit/demo/debug/GenerateTestUserSig.java` are correct. Refer to the [License Guide](https://cloud.tencent.com/document/product/616/79137) for details.
269
+
270
+ ### How to customize the UI?
271
+
272
+ If you have extensive UI customization requirements, we recommend:
273
+ 1. **Call module:** You can use the AtomicxCore SDK (see sample code: No-UI Integration) to customize the call module's interface. Core modules:
274
+
275
+ | **Module** | **Description** |
276
+ |---------|---------|
277
+ | [LoginStore](https://liteav.sdk.cloudcachetci.com/doc/product/tuikit/atomic-x/android/zh/-atomic-x%20-core%20-a-p-i/io.trtc.tuikit.atomicxcore.api.login/-login-store/index.html) | Login management class for user login, logout, and user info management. Provides a complete set of login management APIs including login, logout, and profile configuration. |
278
+ | [CallCoreView](https://liteav.sdk.cloudcachetci.com/doc/product/tuikit/atomic-x/android/zh/-atomic-x%20-core%20-a-p-i/io.trtc.tuikit.atomicxcore.api.view/-call-core-view/index.html) | Core call view component. Automatically listens to CallStore data and renders the video. Provides layout switching, avatar, and icon customization capabilities. |
279
+ | [CallStore](https://liteav.sdk.cloudcachetci.com/doc/product/tuikit/atomic-x/android/zh/-atomic-x%20-core%20-a-p-i/io.trtc.tuikit.atomicxcore.api.call/-call-store/index.html) | Call lifecycle management: make, accept, reject, and hang up calls. Real-time access to participants' audio/video status, call duration, call records, etc. |
280
+ | [DeviceStore](https://liteav.sdk.cloudcachetci.com/doc/product/tuikit/atomic-x/android/zh/-atomic-x%20-core%20-a-p-i/io.trtc.tuikit.atomicxcore.api.device/-device-store/index.html) | Audio/video device control: microphone (on/off, volume), camera (on/off, switch, quality), screen sharing, real-time device status monitoring. |
281
+
282
+ 2. **Chat module:** Refer to the [IM SDK No-UI Integration](https://cloud.tencent.com/document/product/269/75283).
283
+
284
+ ### How to customize call status message display in chat?
285
+
286
+ When the call status changes, IM delivers a call status change message. The signaling protocol is as follows. Depending on whether you use our provided UI code, you have two solutions:
287
+
288
+ | **Question** | **Description** |
289
+ |---------|---------|
290
+ | How to identify "call initiated" | actionType = 1 and cmd = 'videoCall' or 'audioCall' |
291
+ | How to identify "call accepted" | actionType = 3 |
292
+ | How to identify "call ended" and "call duration" | actionType = 1 and cmd = 'hangup'; duration from the call_end field (unit: seconds) |
293
+ | How to identify "call cancelled" | actionType = 2 |
294
+ | How to identify "call rejected" | actionType = 4 |
295
+ | How to identify "call rejected due to busy line" | actionType = 4 and cmd = "line_busy" |
296
+ | How callee identifies "call timed out" | actionType = 5 |
297
+
298
+ - **Option 1: Modify the provided UI source code**
299
+
300
+ Locate the source file `tuikit/TUIChat/tuichat/src/main/java/com/tencent/qcloud/tuikit/tuichat/bean/CallModel.java` and modify the `getContentForSimplifyAppearance` function to customize call status message display.
301
+
302
+ ``` java
303
+ /**
304
+ * Customize 1v1 call status message display text
305
+ *
306
+ * Location: CallModel.java -> getContentForSimplifyAppearance()
307
+ * Only modify the text within the participantType == CALL_PARTICIPANT_TYPE_C2C branch.
308
+ *
309
+ * Available fields within the method:
310
+ * - protocolType: call protocol type (initiate/accept/reject/cancel/hangup/timeout/busy)
311
+ * - participantRole: current user role (CALLER / CALLEE)
312
+ * - streamMediaType: media type (VOICE / VIDEO)
313
+ * - duration: call duration (seconds)
314
+ */
315
+
316
+ // =================== Example: Customize 1v1 call display text ===================
317
+
318
+ // In the getContentForSimplifyAppearance() method,
319
+ // find the if (participantType == CALL_PARTICIPANT_TYPE_C2C) branch and modify:
320
+
321
+ if (participantType == CALL_PARTICIPANT_TYPE_C2C) {
322
+ // Determine media type for text prefix
323
+ val mediaPrefix = if (streamMediaType == CALL_STREAM_MEDIA_TYPE_VIDEO) {
324
+ "[Video Call]" // Your custom video call text
325
+ } else {
326
+ "[Voice Call]" // Your custom voice call text
327
+ }
328
+
329
+ val isCaller = (participantRole == CALL_PARTICIPANT_ROLE_CALLER)
330
+
331
+ // display is the call status message shown in chat
332
+ display = when (protocolType) {
333
+ // Call rejected (actionType = 4, excluding line_busy)
334
+ CALL_PROTOCOL_TYPE_REJECT -> {
335
+ if (isCaller) {
336
+ "$mediaPrefix Declined by the other party"
337
+ } else {
338
+ "$mediaPrefix Declined"
339
+ }
340
+ }
341
+
342
+ // Call cancelled (actionType = 2, caller cancelled)
343
+ CALL_PROTOCOL_TYPE_CANCEL -> {
344
+ if (isCaller) {
345
+ "$mediaPrefix Cancelled"
346
+ } else {
347
+ "$mediaPrefix Cancelled by the other party"
348
+ }
349
+ }
350
+
351
+ // Call ended (actionType = 1, cmd = "hangup")
352
+ // duration field is call duration in seconds
353
+ CALL_PROTOCOL_TYPE_HANGUP -> {
354
+ val formattedDuration = DateTimeUtil.formatSecondsTo00(duration)
355
+ "$mediaPrefix Duration $formattedDuration"
356
+ }
357
+
358
+ // Timed out (actionType = 5)
359
+ CALL_PROTOCOL_TYPE_TIMEOUT -> {
360
+ if (isCaller) {
361
+ "$mediaPrefix No answer"
362
+ } else {
363
+ "$mediaPrefix Missed"
364
+ }
365
+ }
366
+
367
+ // Busy line rejection (actionType = 4, top-level JSON contains "line_busy" field)
368
+ CALL_PROTOCOL_TYPE_LINE_BUSY -> {
369
+ if (isCaller) {
370
+ "$mediaPrefix The other party is busy"
371
+ } else {
372
+ "$mediaPrefix Busy, missed call"
373
+ }
374
+ }
375
+
376
+ // Call initiated (actionType = 1, cmd = "videoCall" or "audioCall")
377
+ CALL_PROTOCOL_TYPE_SEND -> {
378
+ "$mediaPrefix Call initiated"
379
+ }
380
+
381
+ // Call accepted (actionType = 3)
382
+ CALL_PROTOCOL_TYPE_ACCEPT -> {
383
+ "$mediaPrefix Accepted"
384
+ }
385
+
386
+ else -> {
387
+ context.getString(R.string.invalid_command)
388
+ }
389
+ }
390
+ }
391
+ ```
392
+ - **Option 2: Implement custom call status message display**
393
+
394
+ You can set an [IM message listener](https://cloud.tencent.com/document/product/269/75318) to implement call status message display. Sample code:
395
+
396
+ ``` java
397
+ // Set message listener
398
+ V2TIMManager.getMessageManager().addAdvancedMsgListener(advancedMsgListener)
399
+
400
+ /**
401
+ * Receive new message
402
+ * @param msg message
403
+ */
404
+ override fun onRecvNewMessage(msg: V2TIMMessage) {
405
+ // Get signaling info; returns null for non-signaling messages
406
+ val signalingInfo = V2TIMManager.getSignalingManager().getSignalingInfo(msg)
407
+ ?: return
408
+
409
+ // Only handle 1v1 private chats (empty groupID = private chat, non-empty = group chat)
410
+ if (!signalingInfo.groupID.isNullOrEmpty()) {
411
+ return
412
+ }
413
+
414
+ // Parse the signaling data field (JSON format)
415
+ val gson = Gson()
416
+ val jsonData: Map<String, Any> = try {
417
+ gson.fromJson(signalingInfo.data, object : TypeToken<Map<String, Any>>() {}.type)
418
+ } catch (e: Exception) {
419
+ return
420
+ }
421
+
422
+ // Verify businessID to confirm this is a call signaling message
423
+ val businessId = jsonData["businessID"] as? String
424
+ if (businessId != "av_call" && businessId != "tuikit_calling") {
425
+ return
426
+ }
427
+
428
+ // Extract cmd from the data sub-object
429
+ val dataMap = jsonData["data"] as? Map<*, *>
430
+ val cmd = dataMap?.get("cmd") as? String
431
+
432
+ // Determine call status based on actionType
433
+ when (signalingInfo.actionType) {
434
+
435
+ // ========== actionType = 1: Send invitation ==========
436
+ V2TIMSignalingInfo.SIGNALING_ACTION_TYPE_INVITE -> {
437
+ when (cmd) {
438
+ // Initiate video call
439
+ "videoCall" -> {
440
+ val mediaType = "video"
441
+ Log.i(TAG, "Call initiated | Type: $mediaType, Caller: ${msg.sender}")
442
+ }
443
+ // Initiate voice call
444
+ "audioCall" -> {
445
+ val mediaType = "audio"
446
+ Log.i(TAG, "Call initiated | Type: $mediaType, Caller: ${msg.sender}")
447
+ }
448
+ // Hang up (call ended)
449
+ "hangup" -> {
450
+ // Call duration from top-level call_end field, unit: seconds
451
+ val duration = jsonData["call_end"]
452
+ ?.toString()?.toDoubleOrNull()?.toInt() ?: 0
453
+ Log.i(TAG, "Call ended | Duration: ${duration}s")
454
+ }
455
+ }
456
+ }
457
+
458
+ // ========== actionType = 2: Cancel call (caller cancelled) ==========
459
+ V2TIMSignalingInfo.SIGNALING_ACTION_TYPE_CANCEL_INVITE -> {
460
+ Log.i(TAG, "Call cancelled | Caller: ${msg.sender}")
461
+ }
462
+
463
+ // ========== actionType = 3: Accept call (callee accepted) ==========
464
+ V2TIMSignalingInfo.SIGNALING_ACTION_TYPE_ACCEPT_INVITE -> {
465
+ Log.i(TAG, "Call accepted")
466
+ }
467
+
468
+ // ========== actionType = 4: Reject call (callee rejected) ==========
469
+ V2TIMSignalingInfo.SIGNALING_ACTION_TYPE_REJECT_INVITE -> {
470
+ // Check if it's a busy line rejection: top-level JSON contains "line_busy" field
471
+ if (jsonData.containsKey("line_busy")) {
472
+ Log.i(TAG, "Rejected due to busy line")
473
+ } else {
474
+ Log.i(TAG, "Call rejected")
475
+ }
476
+ }
477
+
478
+ // ========== actionType = 5: Timed out ==========
479
+ V2TIMSignalingInfo.SIGNALING_ACTION_TYPE_INVITE_TIMEOUT -> {
480
+ Log.i(TAG, "Call timed out")
481
+ }
482
+ }
483
+ }
484
+ ```
485
+
486
+ ### Improve Call Reachability
487
+ 1. **Integrate offline push to improve call reachability:**
488
+
489
+ - Mainland China: Integrate Notification
490
+
491
+ - Overseas: Integrate FCM
492
+
493
+ 2. **Provide push controls:** Based on our experience, over 90% of users who miss call notifications have manually disabled app notification permissions. To ensure call reachability, we strongly recommend:
494
+
495
+ - **Send notifications prudently:** Avoid sending low-quality or irrelevant notifications to reduce the likelihood of users disabling notification permissions.
496
+
497
+ - **Provide granular controls:** Following the approach of apps like WeChat, provide separate toggles in your app settings for "Notification" and "FCM Data Message", rather than directing users to system settings to disable all notifications at once.
@@ -0,0 +1,79 @@
1
+ ---
2
+ title: Keep TUICallKit Flutter Calls Alive When the Android App Goes to Background (Foreground Service Configuration)
3
+ product: call
4
+ frameworks: [flutter, android]
5
+ scope: platform_specific
6
+ tags: [TUICallKit, Flutter, Android, foreground service, CallForegroundService, keep alive, background, FOREGROUND_SERVICE_MICROPHONE, FOREGROUND_SERVICE_CAMERA, Android14, foregroundServiceType, MethodChannel]
7
+ version_range: ">=2.0.0"
8
+ ---
9
+
10
+ # Keep TUICallKit Flutter Calls Alive When the Android App Goes to Background (Foreground Service Configuration)
11
+
12
+ ## 1. Key Takeaway
13
+
14
+ - Required: Android restricts background apps from accessing the microphone/camera. Without a foreground service to keep the app alive, audio/video capture will be interrupted by the system when the app goes to the background or the screen is locked.
15
+ - Root cause: Starting from Android 9 (API 28), accessing the microphone/camera requires declaring foreground service permissions. Starting from Android 14 (API 34), foreground services must explicitly declare `foregroundServiceType`; otherwise, starting a foreground service will throw an exception.
16
+ - Fix: TUICallKit Flutter does **not include** a built-in foreground service. You need to implement `CallForegroundService` in the Android native layer and invoke its `start()`/`stop()` from the Flutter side via `MethodChannel` at the appropriate time.
17
+ - Version constraint: When `targetSdkVersion >= 34`, if the `<service>` tag does not declare `android:foregroundServiceType="camera|microphone"`, calling `startForegroundService` will throw `MissingForegroundServiceTypeException` and crash.
18
+
19
+ ## 2. Field Reference
20
+
21
+ | Field / Capability | Purpose | Notes |
22
+ |---|---|---|
23
+ | `FOREGROUND_SERVICE` | Base permission to use foreground services | Required since Android 9 (API 28) |
24
+ | `FOREGROUND_SERVICE_MICROPHONE` / `FOREGROUND_SERVICE_CAMERA` | Declare microphone/camera usage in foreground services | Required since Android 14 (API 34) |
25
+ | `android:foregroundServiceType="camera\|microphone"` | Declare the service type in the `<service>` tag | Must match the above permissions; missing this on API 34+ causes a crash |
26
+ | `CallForegroundService` (must be implemented by you) | The foreground service class for keep-alive | Not built into TUICallKit; developers must create it and call `startForeground` |
27
+ | `MethodChannel` | Bridge between Flutter and Android native layer | Used to trigger `start()` from the Flutter side when a call starts or the app goes to background |
28
+
29
+ ## 3. Flow
30
+
31
+ App goes to background / screen locked -> Android reclaims background microphone/camera access -> Call capture interrupted (no audio / black screen) -> Check: verify foreground service permissions and `<service>` declaration -> Identify: missing `CallForegroundService` or `start()` not triggered when going to background -> Fix: declare permissions + implement foreground service class + bridge via `MethodChannel` -> Verify: audio/video capture continues after going to background / locking screen; a persistent notification appears in the notification bar.
32
+
33
+ ## 4. Standard Usage
34
+
35
+ 1. Declare foreground service permissions in `AndroidManifest.xml` and set `foregroundServiceType` for the `<service>`:
36
+
37
+ ``` xml
38
+ <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
39
+ <uses-permission android:name="android.permission.FOREGROUND_SERVICE_CAMERA" />
40
+ <uses-permission android:name="android.permission.FOREGROUND_SERVICE_MICROPHONE" />
41
+
42
+ <application>
43
+ <service
44
+ android:name=".CallForegroundService"
45
+ android:enabled="true"
46
+ android:exported="false"
47
+ android:foregroundServiceType="camera|microphone" />
48
+ </application>
49
+ ```
50
+
51
+ 2. Implement `CallForegroundService` in the Android native layer (extend `Service`, call `startForeground` with a persistent notification in `onCreate`), and provide static `start(context)` / `stop(context)` methods for external invocation.
52
+
53
+ 3. Register a `MethodChannel` on the Flutter side. Call the native `CallForegroundService.start()` when a call starts (`calls` / `accept` succeeds) or the app is about to go to background. Call `stop()` when the call ends (`hangup` / `onCallEnd`) to avoid keeping the service running unnecessarily.
54
+
55
+ 4. On iOS, configure `Background Modes` (check `Audio, AirPlay, and Picture in Picture` and `Voice over IP`) and set up `AVAudioSession` before the call. Use `MethodChannel` to trigger the corresponding background keep-alive logic at the appropriate time.
56
+
57
+ ## 5. Verification
58
+
59
+ - After going to background or locking the screen, call audio/video capture is not interrupted; the remote participant can still hear/see the local participant.
60
+ - A persistent foreground service notification (e.g., "Call in progress") appears in the system notification bar.
61
+ - On devices with `targetSdkVersion >= 34`, no crash occurs due to missing `foregroundServiceType` declaration.
62
+
63
+ ## 6. Common Mistakes
64
+
65
+ - Mistake 1: Assuming TUICallKit Flutter SDK has a built-in foreground service keep-alive capability that requires no manual implementation. In reality, developers must create `CallForegroundService` themselves; the SDK does not handle this automatically.
66
+ - Mistake 2: Declaring permissions and `<service>` in `AndroidManifest.xml` but never actually calling `start()` via `MethodChannel` during a call. The service is never started, making the permission declarations useless.
67
+ - Mistake 3: After upgrading `targetSdkVersion` to 34+, only declaring the `FOREGROUND_SERVICE` permission while missing `FOREGROUND_SERVICE_CAMERA` / `FOREGROUND_SERVICE_MICROPHONE` and the corresponding `foregroundServiceType`. This causes crashes on Android 14 devices after release.
68
+
69
+ ## 7. Problem Definition (Search Anchor)
70
+
71
+ How to keep voice/video calls alive in a Flutter TUICallKit Android app when it goes to background or is minimized. Whether a microphone/camera foreground service with a persistent notification is required. Recommended integration approach for Android 14+.
72
+
73
+ ## 8. Alternative Phrasings (Search Recall)
74
+
75
+ - Does a Flutter TUICallKit Android call drop when the app goes to background?
76
+ - How to configure a foreground service for TUICallKit Android?
77
+ - How to add FOREGROUND_SERVICE_MICROPHONE for Android 14?
78
+ - Flutter call app minimized and microphone/camera stopped working?
79
+ - Do I need to implement CallForegroundService myself?