使用 android.telecom 和 InCallService 接听来电

Answer incoming call using android.telecom and InCallService

自 API 21 以来,Google 一直在向 android.telecom in general, especially by implementing more members of TelecomManager and the addition of InCallService 添加功能。最后一个应该允许非系统的第 3 方应用程序提供和替换系统呼叫应用程序通话屏幕的功能 - 弹出的 Window 允许对 EXTRA_STATE_OFFHOOK 进行操作或 EXTRA_STATE_RINGING 广播(即传入和传出 phone 呼叫)。

目前,只有这个屏幕可以完全控制振铃和活动呼叫以及具有细粒度信息的相关系统回调,通过 root-restricted MODIFY_PHONE_STATE 权限和许多安全的 AOSP 代码甚至通过反射访问。值得注意的是,它是不同制造商的 ROM 风格中变化最大的代码片段之一,还有启动器、联系人和相机。

这一切都非常漂亮但是...

您实际上是如何开发第 3 方 InCallService 的?

即:

  1. 您如何获得有关 GSM 呼叫的通知和获取实例
  2. 如何接听这些电话
  3. 此 class
  4. 的回调的生命周期是多少
  5. Google 是否提供了任何我没有找到的实际教程

我不会一次问所有这些问题的答案,但任何一个答案都可能与其他问题相关联。这是广泛的,但本质上它需要:除了 AOSP 代码之外,我在网上没有发现任何示例,并且该代码基于 root 权限的假设,这使得它无法用于 3rd 方应用程序开发目的。

遵循 第二条评论中的建议。此外,您需要一个实现 InCallService 接口的服务。当呼叫到达时,将调用 onCallAdded(Call call) 方法,为您提供对呼叫对象的引用。

<service
  android:name=".InCallServiceImplementation"
  android:enabled="true"
  android:exported="true"
  android:permission="android.permission.BIND_INCALL_SERVICE">

  <meta-data
    android:name="android.telecom.IN_CALL_SERVICE_UI"
    android:value="true" />

  <intent-filter>
    <action android:name="android.telecom.InCallService" />
  </intent-filter>
</service>

一旦你有了调用对象,回答它就像 call.answer() 一样简单。我建议当你让上面的东西工作时,运行 几个测试调用来了解何时调用不同的回调。

关于教程,我在研究这个的时候找不到,但那是一年多以前的事了...

希望对您有所帮助!

我想 Google 一定看过这个问题,因为显然在 Android 8 上,终于 allows answering calls through a 3rd party dev-facing permission.

获得了新的许可

android.permission.ANSWER_PHONE_CALLS (...) allows apps to answer incoming phone calls programmatically

不过还没有详细信息,因为 API 26 的文档尚未发布。我会确保在他们这样做时更新此答案。

编辑:用户 arekolek 提供了一个完美解决这个问题的原始 API 版本的答案(在提问时,API 23,即使问题提到 API 21),因此他得到了正确答案的勾号。如果你想实现一个目标最小 SDK 为 23 的调用屏幕,请参考他的回答。请注意,如果你想让它在更新的 APIs 上工作,你可能需要 API-dependent 代码或兼容库调整弃用(或限制)提供的示例代码的使用。 github 回购按照我最初的预期工作。

您如何获得有关 GSM 呼叫的通知和获取实例

首先,用户需要 select 您的应用程序作为默认 Phone 应用程序。请参阅 以了解执行此操作的方法。

您还需要定义一个 InCallService 系统将绑定到的实现并通知您调用:

<service
    android:name=".CallService"
    android:permission="android.permission.BIND_INCALL_SERVICE">
    <meta-data
        android:name="android.telecom.IN_CALL_SERVICE_UI"
        android:value="true" />
    <intent-filter>
        <action android:name="android.telecom.InCallService" />
    </intent-filter>
</service>

你至少应该处理 onCallAdded (set up listeners on Call, start your UI - activity - for the call) and onCallRemoved(删除监听器)。

如何接听这些电话

如果用户想接听来电,需要调用方法Call#answer(int) with VideoProfile.STATE_AUDIO_ONLY,例如

此 class

的回调的生命周期是多少

查看 Call.Callback 一次调用可能发生的事件。

Google 是否提供了任何我没有找到的实际教程

我不知道 Google,但你可以查看我的简化示例 https://github.com/arekolek/simple-phone

我建议您查看此项目,为 Android 构建一个拨号器应用程序。 https://github.com/HiddenPirates/Dialer