自 2025 年 3 月 27 日起,我们建议您使用 android-latest-release
而非 aosp-main
构建 AOSP 并为其做出贡献。如需了解详情,请参阅 AOSP 的变更。
支持第三方通话应用
使用集合让一切井井有条
根据您的偏好保存内容并对其进行分类。
Android 9 提供了一些 API 来更好地支持第三方通话应用。第三方通话应用通常借助电话 API(例如 PHONE_STATE
广播)与运营商通话共存。因此,第三方通话应用必须“礼让”运营商通话,而且通常会以静默方式拒绝应用中的来电,或者终止正在进行的通话,以便为运营商通话“让路”。
Android 9 中的 API 支持在运行第三方应用的同时进行运营商通话。这使得在运营商通话过程中接听第三方来电成为可能。该框架要负责确保,在用户进行第三方应用通话时使运营商通话处于呼叫保持状态。
在 Android 9 中,建议您使用第三方通话应用实现自行管理的 ConnectionService
API。要详细了解如何使用此 API 构建通话应用,请参阅构建通话应用。
自行管理的 ConnectionService
API 还让开发者有机会选择将其应用中的通话添加到系统通话记录中(请参阅 EXTRA_LOG_SELF_MANAGED_CALLS
)。根据 Android 兼容性定义文档 (CDD)(第 7.4.1.2 节)中的要求,您应确保拨号器/“电话”应用能够显示此类通话记录条目,并显示接入通话的第三方通话应用的名称(如需查看有关 AOSP 拨号器应用如何满足此要求的示例,请参阅源自第三方通话应用的通话记录条目)。
应用需要对其连接设置 CAPABILITY_SUPPORT_HOLD
和 CAPABILITY_HOLD
。但在某些情况下,应用可能无法使通话处于呼叫保持状态。该框架包含了应对此类情形的规定。
场景
您应当修改自己的拨号器应用以应对以下场景。
处理导致正在进行的通话中断的来电
如果正在进行的第三方通话(例如 SuperCaller 通话)不支持呼叫保持,而此时用户接到移动网络来电(例如使用运营商 FooCom),您的拨号器/电话应用应提示用户:接听移动网络来电将终止正在进行的第三方通话。
这种用户体验非常重要,因为该框架可能不支持对第三方通话应用的通话进行呼叫保持。接听新的移动网络来电会导致正在进行的第三方通话中断。
请参阅图中的界面示例:
图 1. 导致正在进行的第三方通话中断的来电。
拨号器应用可通过检查通话 extra 判断某个来电是否会导致其他通话中断。请务必将 EXTRA_ANSWERING_DROPS_FG_CALL
设为 TRUE
,并将 EXTRA_ANSWERING_DROPS_FG_CALL_APP_NAME
设为接听移动网络来电时其通话会被中断的应用的名称。
源自第三方通话应用的通话记录条目
第三方通话应用的开发者可以选择将其应用中的通话添加到系统通话记录中(请参阅 EXTRA_LOG_SELF_MANAGED_CALLS
)。这意味着,通话记录中可以包含移动网络通话以外的条目。
当 AOSP 拨号器应用显示与第三方通话应用相关的通话记录条目时,发生通话的应用的名称将显示在通话记录中,如图所示:
图 2. 拨号器应用上显示的通话记录条目(包含第三方通话应用的名称)。
如需确定与通话记录条目相关联的应用的名称,请使用通话记录提供程序中的 PHONE_ACCOUNT_COMPONENT_NAME
和 PHONE_ACCOUNT_ID
列创建一个 PhoneAccountHandle
实例,该实例会识别通话记录条目的来源。查询 TelecomManager
以获取 PhoneAccount 的详细信息。
如需确定某个通话记录条目是否源自第三方通话应用,请检查 PhoneAccount
功能,查看是否已设置 CAPABILITY_SELF_MANAGED
。
返回的 PhoneAccount
的 getLabel
方法将返回与源自第三方通话应用的通话记录条目相关联的应用的名称。
验证
如需测试设备是否支持第三方通话应用,请使用 Telecomm 测试应用,该应用可实现自行管理的 ConnectionService API。该应用位于 /packages/services/Telecomm/testapps/
中。
使用以下命令从 Android 源代码库的根目录构建测试应用:
mmma packages/services/Telecomm/testapps/
使用 adb install -g -r <apk path>
安装 build APK。自行管理的示例图标随后会添加到您的启动器。
点按该图标以打开测试应用。
处理导致正在进行的通话中断的来电
请按照以下步骤操作,以验证某个来电是否会导致正在进行的第三方通话中断。
图 3. 使用 ConnectionService API 的示例实现测试应用。
- 清除 Holdable 选项。
- 点按 OUTGOING 以开始新的示例去电。
- 点按 ACTIVE 按钮以激活通话。
- 用另一部手机拨打被测设备的电话号码。在这一场景中,您的拨号器会显示通话将被中断的应用的名称。
- 操作完成后,在测试应用中点按 DISCONNECT 按钮。
源自第三方通话应用的通话记录条目
完成上述步骤后,测试应用会在系统通话记录中添加一条通话记录。如需确认设备是否记录了源自第三方通话应用的通话,请打开您的拨号器应用并确认相应通话显示在系统通话记录中。
本页面上的内容和代码示例受内容许可部分所述许可的限制。Java 和 OpenJDK 是 Oracle 和/或其关联公司的注册商标。
最后更新时间 (UTC):2025-03-26。
[[["易于理解","easyToUnderstand","thumb-up"],["解决了我的问题","solvedMyProblem","thumb-up"],["其他","otherUp","thumb-up"]],[["没有我需要的信息","missingTheInformationINeed","thumb-down"],["太复杂/步骤太多","tooComplicatedTooManySteps","thumb-down"],["内容需要更新","outOfDate","thumb-down"],["翻译问题","translationIssue","thumb-down"],["示例/代码问题","samplesCodeIssue","thumb-down"],["其他","otherDown","thumb-down"]],["最后更新时间 (UTC):2025-03-26。"],[],[],null,["# Support third-party calling apps\n\nAndroid 9 provides APIs to better support third-party\ncalling apps. Third-party calling apps typically rely on Telephony APIs such as\nthe `PHONE_STATE` broadcast to co-exist alongside carrier phone calls. As a\nconsequence, third-party calling apps must give carrier calls priority and often\nresort to silently rejecting incoming calls in the app, or terminating an\nongoing call to make way for a carrier call.\n\nThe APIs in Android 9 support concurrent calling\nscenarios between third-party apps and carrier calls. This makes it possible,\nfor example, to receive an incoming third-party call while engaged in a carrier\ncall. The framework assumes responsibility for ensuring the carrier call is held\nwhen the user engages in the third-party call.\n\nIn Android 9, third-party calling apps are encouraged to\nimplement the self-managed `ConnectionService` API. For more information on how\nto build a calling app using this API, see\n[Build a calling app](https://developer.android.com/guide/topics/connectivity/telecom/selfManaged).\n\nThe self-managed `ConnectionService` API also gives developers the opportunity\nto opt-in to having calls in their app logged in the system call log (see\n[`EXTRA_LOG_SELF_MANAGED_CALLS`](https://developer.android.com/reference/android/telecom/PhoneAccount#EXTRA_LOG_SELF_MANAGED_CALLS)).\nPer the requirements in the\n[Android Compatibility Definition Document (CDD)](/docs/compatibility/android-cdd#7_4_data_connectivity)\n(section 7.4.1.2), you should ensure your dialer or phone app displays these\ncall log entries and shows the name of the third-party calling app where the\ncall originated (for an example of how the AOSP dialer app meets this\nrequirement, see\n[Call log entries from third-party calling apps](#call_log_entries_from_3p_calling_apps)).\n\nApps are responsible for setting\n[`CAPABILITY_SUPPORT_HOLD`](https://developer.android.com/reference/android/telecom/Connection.html#CAPABILITY_SUPPORT_HOLD)\nand\n[`CAPABILITY_HOLD`](https://developer.android.com/reference/android/telecom/Connection.html#CAPABILITY_HOLD)\non their apps' connections. However, it is possible that an app cannot hold a\ncall in some circumstances. The framework includes provisions for resolving\nthese types of cases.\n\nScenarios\n---------\n\nYou should modify your dialer app to handle the following scenarios.\n\n### Handle incoming calls that disconnect an ongoing call\n\nIn a scenario where there is an ongoing third-party call (e.g. in a SuperCaller call)\nthat does not support hold, and the user receives a mobile call (for example,\nusing their carrier FooCom), your Dialer or Phone app should indicate to the\nuser that answering the mobile network call will end the ongoing third-party call.\n\nThis user experience is important as a third-party calling app may have an ongoing call\nthat cannot be held by the framework. Answering a new mobile call causes the\nongoing third-party call to be disconnected.\n\nSee the user interface in the figure for an example:\n\n**Figure 1.** Incoming call disconnecting an ongoing third-party call.\n\nYour dialer app can check if an incoming call causes another call to be\ndisconnected by checking the\n[call extras](https://developer.android.com/reference/android/telecom/Call.Details.html#getExtras()).\nMake sure that\n[`EXTRA_ANSWERING_DROPS_FG_CALL`](https://developer.android.com/reference/android/telecom/Connection.html#EXTRA_ANSWERING_DROPS_FG_CALL)\nis set to `TRUE`, and\n[`EXTRA_ANSWERING_DROPS_FG_CALL_APP_NAME`](https://developer.android.com/reference/android/telecom/Connection.html#EXTRA_ANSWERING_DROPS_FG_CALL_APP_NAME)\nis set to the name of the app whose call is disconnected upon answering the\nincoming mobile call.\n\n### Call log entries from third-party calling apps\n\nDevelopers of third-party calling apps can opt-in to having calls in their app\nlogged in the system call log (see\n[`EXTRA_LOG_SELF_MANAGED_CALLS`](https://developer.android.com/reference/android/telecom/PhoneAccount#EXTRA_LOG_SELF_MANAGED_CALLS)).\nThis means that it is possible to have entries in the call log that are not for\nmobile network calls.\n\nWhen the AOSP dialer app displays call log entries related to a third-party\ncalling app, the name of the app where the call took place is displayed in the\ncall log, as illustrated in the figure:\n\n**Figure 2.** Call log entry with name of third-party calling app on dialer app.\n\nTo determine the name of an app associated with a call log entry, use the\n[`PHONE_ACCOUNT_COMPONENT_NAME`](https://developer.android.com/reference/android/provider/CallLog.Calls.html#PHONE_ACCOUNT_COMPONENT_NAME)\nand\n[`PHONE_ACCOUNT_ID`](https://developer.android.com/reference/android/provider/CallLog.Calls.html#PHONE_ACCOUNT_ID)\ncolumns in the call log provider to create an instance of\n[`PhoneAccountHandle`](https://developer.android.com/reference/android/telecom/PhoneAccountHandle.html#PhoneAccountHandle(android.content.ComponentName,%20java.lang.String)),\nwhich identifies the source of a call log entry. Query\n[`TelecomManager`](https://developer.android.com/reference/android/telecom/TelecomManager.html#getPhoneAccount(android.telecom.PhoneAccountHandle))\nto get the details for the PhoneAccount. \n\nTo determine if a call log entry is from a third-party calling app, check\n[`PhoneAccount` capabilities](https://developer.android.com/reference/android/telecom/PhoneAccount.html#getCapabilities())\nto see if\n[`CAPABILITY_SELF_MANAGED`](https://developer.android.com/reference/android/telecom/PhoneAccount.html#CAPABILITY_SELF_MANAGED)\nis set.\n\nThe\n[`getLabel`](https://developer.android.com/reference/android/telecom/PhoneAccount.html#getLabel())\nmethod of the returned `PhoneAccount` returns the name of the app associated\nwith a call log entry from the third-party calling app.\n\nValidation\n----------\n\nTo test that your device supports third-party calling apps, use the Telecomm test\napp, which implements the self-managed ConnectionService API. The\napp is located in\n[`/packages/services/Telecomm/testapps/`](https://android.googlesource.com/platform/packages/services/Telecomm/+/android16-release/testapps/).\n\n1. Build the test app from the root of your Android source repository using:\n\n `mmma packages/services/Telecomm/testapps/`\n2. Install the build apk using `adb install -g -r \u003capk path\u003e`. A Self-Managed\n Sample icon is then added to your launcher.\n\n3. Tap the icon to open the test app.\n\n### Handle incoming calls that disconnect an ongoing call\n\nFollow these steps to verify that an incoming call disconnects an ongoing\nthird-party call.\n\n**Figure 3.** Test app with sample implementations of the ConnectionService API.\n\n1. Clear the **Holdable** option.\n2. Tap **OUTGOING** to start a new sample outgoing call.\n3. Tap the **ACTIVE** button to make the call go active.\n4. Call the phone number of the device under test with another phone. This invokes the scenario where your dialer is provided with the name of an app, which will have its call disconnected.\n5. When you are finished, tap the **DISCONNECT** button in the test app.\n\n### Call log entries from third-party calling apps\n\nAfter completing the steps above, the test app should have logged a call to the\nsystem call log. To confirm the device logs calls from third-party calling apps,\nopen your dialer app and confirm the call appears in the system call log."]]