跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客我的书AI学习GitHub 精选镜像AI工具UI配色美学关于
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
Javajava

Android 电话操作指南:拨打、监听与拦截

Android 平台下电话功能的开发实现,涵盖拨打电话、监听通话状态、拦截呼出电话及自动挂断来电四大场景。内容包含 Intent 跳转机制、TelephonyManager 监听器使用、BroadcastReceiver 拦截逻辑以及 TelecomManager 挂断接口。同时强调了不同 Android 版本对权限的要求,特别是 Android 6.0+ 的运行时权限申请以及高版本对 PROCESS_OUTGOING_CALLS 的废弃说明,确保代码在现代环境下的兼容性与安全性。

二进制发布于 2025/2/7更新于 2026/10/2193 浏览
Android 电话操作指南:拨打、监听与拦截

Android 电话功能开发指南

在 Android 应用开发中,电话功能涉及拨打电话、监听通话状态、拦截呼出电话以及处理来电挂断等核心场景。由于涉及用户隐私和通信费用,相关 API 需要严格的权限声明和运行时授权。

1. 如何使用代码拨打电话

Android 提供了两种主要的拨打电话方式:

  1. 打开拨号界面:使用 Intent.ACTION_DIAL。用户确认后会显示号码并等待点击呼叫。此方式不需要 CALL_PHONE 权限。
  2. 直接拨打电话:使用 Intent.ACTION_CALL。程序直接发起呼叫,无需用户二次确认。此方式必须声明 android.permission.CALL_PHONE 权限。

代码示例

// 打开拨号界面(无需 CALL_PHONE 权限)
Intent intentDial = new Intent();
intentDial.setAction(Intent.ACTION_DIAL);
intentDial.setData(Uri.parse("tel:10086"));
startActivity(intentDial);

// 直接拨打电话(需 CALL_PHONE 权限)
Intent intentCall = new Intent();
intentCall.setAction(Intent.ACTION_CALL);
intentCall.setData(Uri.parse("tel:10086"));
startActivity(intentCall);

权限配置

在 AndroidManifest.xml 中添加权限:

<uses-permission android:name="android.permission.CALL_PHONE" />

注意:从 Android 6.0 (API 23) 开始,CALL_PHONE 属于危险权限,必须在运行时动态申请并获得用户授权后才能调用,否则会导致 SecurityException。

2. 如何监听电话状态

Android 提供了 TelephonyManager 类来管理电话服务,配合 PhoneStateListener 可以监听三种主要状态:

  • 空闲状态 (IDLE):无通话活动。
  • 振铃状态 (RINGING):有来电或正在拨出。
  • 摘机状态 (OFFHOOK):通话正在进行中。

实现步骤

  1. 创建继承自 PhoneStateListener 的类。
  2. 重写 onCallStateChanged 方法处理状态变化。
  • 获取 TelephonyManager 实例并注册监听器。
  • 在适当时机取消监听以避免内存泄漏。
  • 代码示例

    public class MainActivity extends AppCompatActivity {
        private TelephonyManager telephonyManager;
        private MyPhoneStateListener listener;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            // 获取电话管理器
            telephonyManager = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
            
            // 创建监听器
            listener = new MyPhoneStateListener();
            
            // 开启监听(需 READ_PHONE_STATE 权限)
            if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_PHONE_STATE) == PackageManager.PERMISSION_GRANTED) {
                telephonyManager.listen(listener, PhoneStateListener.LISTEN_CALL_STATE);
            }
        }
    
        // 电话状态监听器
        class MyPhoneStateListener extends PhoneStateListener {
            @Override
            public void onCallStateChanged(int state, String incomingNumber) {
                switch (state) {
                    case TelephonyManager.CALL_STATE_IDLE:
                        Log.i("Telephony", "CALL_STATE_IDLE: 空闲");
                        break;
                    case TelephonyManager.CALL_STATE_OFFHOOK:
                        Log.i("Telephony", "CALL_STATE_OFFHOOK: 通话中");
                        break;
                    case TelephonyManager.CALL_STATE_RINGING:
                        Log.i("Telephony", "CALL_STATE_RINGING: 振铃,号码:" + incomingNumber);
                        break;
                }
            }
        }
    
        @Override
        protected void onDestroy() {
            super.onDestroy();
            // 取消监听
            if (telephonyManager != null && listener != null) {
                telephonyManager.listen(listener, PhoneStateListener.LISTEN_NONE);
            }
        }
    }
    

    权限配置

    需要在清单文件中声明以下权限:

    <uses-permission android:name="android.permission.READ_PHONE_STATE" />
    <uses-permission android:name="android.permission.READ_CALL_LOG" />
    

    同样,READ_PHONE_STATE 也需要在运行时动态申请。

    3. 如何拦截呼出电话

    通过广播接收器监听系统发出的呼出电话广播,可以在特定条件下阻止呼叫。

    实现逻辑

    1. 注册 BroadcastReceiver 监听 Intent.ACTION_NEW_OUTGOING_CALL。
    2. 在 onReceive 中获取目标号码。
    3. 根据业务逻辑决定是否中断呼叫(设置结果为 null)。

    代码示例

    public class MainActivity extends AppCompatActivity {
        private MyPhoneReceiver receiver;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            // 注册广播接收器
            receiver = new MyPhoneReceiver();
            IntentFilter filter = new IntentFilter();
            filter.addAction(Intent.ACTION_NEW_OUTGOING_CALL);
            registerReceiver(receiver, filter);
        }
    
        // 拦截呼出电话的 Receiver
        class MyPhoneReceiver extends BroadcastReceiver {
            @Override
            public void onReceive(Context context, Intent intent) {
                String number = getResultData();
                Log.i("MyPhoneReceiver", "Outgoing call to: " + number);
                
                // 示例:拦截拨打 10086
                if (number != null && number.equals("10086")) {
                    setResultData(null); // 阻止拨出
                }
            }
        }
    
        @Override
        protected void onDestroy() {
            super.onDestroy();
            // 取消注册广播接收器
            if (receiver != null) {
                unregisterReceiver(receiver);
            }
        }
    }
    

    权限配置

    <uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS" />
    

    注意:从 Android 9 (API 28) 开始,PROCESS_OUTGOING_CALLS 已被废弃,且普通应用无法再拦截所有呼出电话。此功能通常仅适用于默认电话应用或系统级应用。现代开发建议使用 Telecom API 进行更合规的管理。

    4. 如何自动挂断来电

    对于特定的来电,可以使用 TelecomManager 提供的接口在响铃阶段自动挂断。

    代码示例

    if (incomingNumber.equals("10086")) {
        TelecomManager tm = (TelecomManager) getSystemService(Context.TELECOM_SERVICE);
        if (tm != null) {
            tm.endCall();
        }
    }
    

    权限与版本要求

    • 需要添加权限:android.permission.ANSWER_PHONE_CALLS
    • 该 API 仅在 Android 8.0 (API 28) 及以上版本可用。

    5. 最佳实践与注意事项

    1. 生命周期管理:务必在 onDestroy 或 onPause 中取消电话监听器和广播接收器,防止内存泄漏。
    2. 权限检查:始终在调用敏感 API 前检查运行时权限,避免崩溃。
    3. 兼容性:部分电话相关 API 随 Android 版本迭代发生变化,开发时需查阅对应版本的官方文档。
    4. 用户体验:拦截或自动挂断电话应谨慎使用,避免影响正常通信体验。

    通过以上方法,开发者可以在 Android 应用中安全、有效地实现电话相关的核心功能。

    目录

    1. Android 电话功能开发指南
    2. 1. 如何使用代码拨打电话
    3. 代码示例
    4. 权限配置
    5. 2. 如何监听电话状态
    6. 实现步骤
    7. 代码示例
    8. 权限配置
    9. 3. 如何拦截呼出电话
    10. 实现逻辑
    11. 代码示例
    12. 权限配置
    13. 4. 如何自动挂断来电
    14. 代码示例
    15. 权限与版本要求
    16. 5. 最佳实践与注意事项

    更多推荐文章

    查看全部
    • Git 入门指南:安装配置与分支管理
    • RustFS + Docker 生产环境部署指南
    • Markdown 笔记图片自动上传方案:Gitee + PicGo 搭建指南
    • DeepSeek 使用指南:提示词技巧与本地知识库搭建
    • 远程桌面工具横评:性能、功能与价格对比分析
  • 利用 KSWEB 与 cpolar 在安卓手机部署 Typecho 博客并实现外网访问
  • LLaMA Factory 核心原理讲解
  • 基于 Canvas 和 Web Audio API 的交互式烟花动画实现
  • 安卓/鸿蒙虚拟定位打卡操作指南
  • Python 调用高德地图 MCP 服务查询天气示例
  • Python 列表内存存储本质:差异原因与优化建议
  • 大语言模型发展脉络与主流基座模型概览
  • OpenClaw 多机器人多 Agent 模式:构建 AI 助手团队
  • OpenClaw-多飞书机器人与多Agent团队实战复盘
  • EhViewer:开源免费安卓 E-Hentai 漫画浏览器安装与使用教程
  • Apache Shiro JSP 标签库详解
  • 无需网络,在手机上部署本地大模型指南
  • 使用 CSS 实现水平导航菜单
  • 基于 DeepFace 与 OpenCV 的实时情绪分析器
  • 大模型技术指南:从基础理论到实战应用
  • 相关免费在线工具

    • Keycode 信息

      查找任何按下的键的javascript键代码、代码、位置和修饰符。 在线工具,Keycode 信息在线工具,online

    • Escape 与 Native 编解码

      JavaScript 字符串转义/反转义;Java 风格 \uXXXX(Native2Ascii)编码与解码。 在线工具,Escape 与 Native 编解码在线工具,online

    • JavaScript / HTML 格式化

      使用 Prettier 在浏览器内格式化 JavaScript 或 HTML 片段。 在线工具,JavaScript / HTML 格式化在线工具,online

    • JavaScript 压缩与混淆

      Terser 压缩、变量名混淆,或 javascript-obfuscator 高强度混淆(体积会增大)。 在线工具,JavaScript 压缩与混淆在线工具,online

    • Base64 字符串编码/解码

      将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online

    • Base64 文件转换器

      将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online