0

0

Android SDK 31 中监听电话状态变化的完整实现指南

花韻仙語

花韻仙語

发布时间:2026-02-24 11:22:14

|

302人浏览过

|

来源于php中文网

原创

Android SDK 31 中监听电话状态变化的完整实现指南

在 Android 12(SDK 31)及以上版本中,TelephonyManager.listen() 已被弃用,需改用 registerTelephonyCallback() 配合 TelephonyCallback.CallStateListener 实时监听通话状态(如拨出、接通、挂断),本文详解安全、合规的注册与回调实现。

android 12(sdk 31)及以上版本中,`telephonymanager.listen()` 已被弃用,需改用 `registertelephonycallback()` 配合 `telephonycallback.callstatelistener` 实时监听通话状态(如拨出、接通、挂断),本文详解安全、合规的注册与回调实现。

自 Android 12(API level 31)起,系统出于隐私与后台限制考量,彻底废弃了传统的 TelephonyManager.listen() 方法。若你的应用仍需感知用户发起或结束通话(例如:自动关闭语音通道、更新 UI 状态、触发后续业务逻辑),必须迁移到基于 TelephonyCallback 的新机制。该方案不仅更轻量、线程安全,还天然适配主线程执行器(MainExecutor),避免手动处理 Handler 或 Looper。

✅ 正确实现步骤

  1. 继承 TelephonyCallback 并实现 CallStateListener 接口
    注意:TelephonyCallback 是抽象基类,不可直接实例化;必须子类化并重写所需监听方法(如 onCallStateChanged)。

  2. 在合适生命周期内注册/注销回调
    建议在 Activity.onResume() 或 Service.onStartCommand() 中注册,在 onPause() 或 onDestroy() 中调用 unregisterTelephonyCallback() —— 未及时注销将导致内存泄漏与资源占用

  3. 使用 getMainExecutor() 保证回调在主线程执行
    所有 TelephonyCallback 方法均在指定 Executor 上调用,主线程回调可直接更新 UI,无需额外切线程。

以下是完整、可直接集成的示例代码:

public class CallStateMonitor extends TelephonyCallback implements TelephonyCallback.CallStateListener {
    private static final String TAG = "CallStateMonitor";
    private final Context context;

    public CallStateMonitor(Context context) {
        this.context = context.getApplicationContext(); // 使用 Application Context 避免 Activity 泄漏
    }

    @Override
    public void onCallStateChanged(@TelephonyManager.CallState int state) {
        switch (state) {
            case TelephonyManager.CALL_STATE_IDLE:
                Log.i(TAG, "通话已结束或无活跃通话");
                // ✅ 此处处理“挂断”逻辑:如停止录音、释放媒体资源、跳转页面等
                break;
            case TelephonyManager.CALL_STATE_OFFHOOK:
                Log.i(TAG, "通话已接通(正在通话中)");
                // ⚠️ 注意:CALL_STATE_OFFHOOK 包含拨出接通、呼入接听两种场景
                break;
            case TelephonyManager.CALL_STATE_RINGING:
                Log.i(TAG, "有来电振铃中");
                // 可选:响应来电事件(需 READ_PHONE_STATE 权限)
                break;
            default:
                Log.w(TAG, "未知通话状态: " + state);
        }
    }
}

在 Activity 或 Service 中注册与销毁:

private CallStateMonitor callStateMonitor;

@Override
protected void onResume() {
    super.onResume();
    TelephonyManager tm = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
    if (tm != null) {
        callStateMonitor = new CallStateMonitor(this);
        tm.registerTelephonyCallback(getMainExecutor(), callStateMonitor);
    }
}

@Override
protected void onPause() {
    super.onPause();
    if (callStateMonitor != null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
        TelephonyManager tm = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
        if (tm != null) {
            tm.unregisterTelephonyCallback(callStateMonitor);
        }
        callStateMonitor = null;
    }
}

⚠️ 关键注意事项

  • 权限要求:监听 CALL_STATE_RINGING 和 CALL_STATE_OFFHOOK 需要 READ_PHONE_STATE(危险权限,Android 10+ 还需声明 android.permission.READ_CALL_LOG 或满足特殊豁免条件);但 CALL_STATE_IDLE 通常无需运行时权限(仅需 android.permission.READ_PHONE_STATE 在 AndroidManifest.xml 中声明)。请严格遵循 Android 电话权限指南

    Hotpot.ai
    Hotpot.ai

    AI工具箱(图像、游戏和写作系列工具)

    下载
  • 作用域限制:registerTelephonyCallback() 仅在应用处于前台或前台服务运行时可靠触发。后台应用受 Android 9+ 后台执行限制影响,无法持续监听通话状态 —— 这是系统级设计,不可绕过。

  • 状态语义说明

    • CALL_STATE_IDLE:表示当前无任何通话活动(包括刚挂断后),是检测“通话结束”的唯一可靠信号;
    • CALL_STATE_OFFHOOK:表示至少有一路通话处于已接通状态(无论主叫/被叫),不等于“开始通话”瞬间,可能存在延迟;
    • CALL_STATE_RINGING:仅对呼入有效,且需权限支持。
  • 兼容性提示:该 API 自 Android 11(API 30)引入,但 CALL_STATE_IDLE 的稳定性在 SDK 31(Android 12)后显著增强,推荐以 Build.VERSION.SDK_INT >= Build.VERSION_CODES.S 为最低目标。

✅ 总结

迁移到 TelephonyCallback 不仅是适配新 SDK 的强制要求,更是提升应用健壮性与用户体验的关键一步。通过合理封装监听器、严格管理生命周期、理解各状态语义,并结合权限与后台限制的客观约束,你可以在符合平台规范的前提下,精准捕获通话生命周期关键节点。务必测试真机场景(模拟器不支持真实通话状态),并在 targetSdkVersion ≥ 31 的 build 下全面验证行为一致性。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
pdf怎么转换成xml格式
pdf怎么转换成xml格式

将 pdf 转换为 xml 的方法:1. 使用在线转换器;2. 使用桌面软件(如 adobe acrobat、itext);3. 使用命令行工具(如 pdftoxml)。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

1932

2024.04.01

xml怎么变成word
xml怎么变成word

步骤:1. 导入 xml 文件;2. 选择 xml 结构;3. 映射 xml 元素到 word 元素;4. 生成 word 文档。提示:确保 xml 文件结构良好,并预览 word 文档以验证转换是否成功。想了解更多xml的相关内容,可以阅读本专题下面的文章。

2109

2024.08.01

xml是什么格式的文件
xml是什么格式的文件

xml是一种纯文本格式的文件。xml指的是可扩展标记语言,标准通用标记语言的子集,是一种用于标记电子文件使其具有结构性的标记语言。想了解更多相关的内容,可阅读本专题下面的相关文章。

1134

2024.11.28

硬盘接口类型介绍
硬盘接口类型介绍

硬盘接口类型有IDE、SATA、SCSI、Fibre Channel、USB、eSATA、mSATA、PCIe等等。详细介绍:1、IDE接口是一种并行接口,主要用于连接硬盘和光驱等设备,它主要有两种类型:ATA和ATAPI,IDE接口已经逐渐被SATA接口;2、SATA接口是一种串行接口,相较于IDE接口,它具有更高的传输速度、更低的功耗和更小的体积;3、SCSI接口等等。

1629

2023.10.19

PHP接口编写教程
PHP接口编写教程

本专题整合了PHP接口编写教程,阅读专题下面的文章了解更多详细内容。

485

2025.10.17

php8.4实现接口限流的教程
php8.4实现接口限流的教程

PHP8.4本身不内置限流功能,需借助Redis(令牌桶)或Swoole(漏桶)实现;文件锁因I/O瓶颈、无跨机共享、秒级精度等缺陷不适用高并发场景。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2301

2025.12.29

java接口相关教程
java接口相关教程

本专题整合了java接口相关内容,阅读专题下面的文章了解更多详细内容。

40

2026.01.19

线程和进程的区别
线程和进程的区别

线程和进程的区别:线程是进程的一部分,用于实现并发和并行操作,而线程共享进程的资源,通信更方便快捷,切换开销较小。本专题为大家提供线程和进程区别相关的各种文章、以及下载和课程。

719

2023.08.10

pixiv网页版官网登录与阅读指南_pixiv官网直达入口与在线访问方法
pixiv网页版官网登录与阅读指南_pixiv官网直达入口与在线访问方法

本专题系统整理pixiv网页版官网入口及登录访问方式,涵盖官网登录页面直达路径、在线阅读入口及快速进入方法说明,帮助用户高效找到pixiv官方网站,实现便捷、安全的网页端浏览与账号登录体验。

1228

2026.02.13

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Excel 教程
Excel 教程

共162课时 | 18.6万人学习

Java 教程
Java 教程

共578课时 | 70.9万人学习

Uniapp从零开始实现新闻资讯应用
Uniapp从零开始实现新闻资讯应用

共64课时 | 6.9万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号