Android ITelephony EndCall Remove 各版本挂断、拦截电话方法

Android 各版本挂断电话方法演进及最佳实践

本文首发地址:https://h89.cn/archives/13.html

一、背景介绍

Android系统中挂断电话的方法随着版本的演进发生了多次变化。本文将详细介绍从Android 8.0到最新版本的实现方法,以及各个版本的兼容性处理方案。

二、Android 10之前的实现方式

2.1 源码分析

在Android 8.0和9.0中,ITelephony.aidl提供了endCall()接口:

而在Android 10源码中,已经移除了endCall()接口。

2.2 实现代码

// Android 10之前的实现方式
public void endCall() {
    try {
        // 1. 通过类加载器加载相应类
        Class<?> loadClass = getClassLoader().loadClass("android.os.ServiceManager");
        
        // 2. 获取getService方法
        Method method = loadClass.getDeclaredMethod("getService", String.class);
        
        // 3. 执行方法获取IBinder对象
        IBinder invoke = (IBinder) method.invoke(null, Context.TELEPHONY_SERVICE);
        
        // 4. 转换为ITelephony接口并调用endCall方法
        ITelephony iTelephony = ITelephony.Stub.asInterface(invoke);
        iTelephony.endCall();
    } catch (Exception e) {
        e.printStackTrace();
        // 建议添加日志记录,方便问题排查
        Log.e("EndCall", "Failed to end call using ITelephony", e);
    }
}

三、Android 10的实现方式

3.1 源码变更

在Android 10中,TelephonyManager类的endCall()方法被标记为@Deprecated,并建议使用TelecomManagerendCall()方法:

// TelephonyManager.java in Android 10
@Deprecated
@SystemApi
@RequiresPermission(android.Manifest.permission.CALL_PHONE)
public boolean endCall() {
    return false;
}

3.2 新的实现方式

// AndroidManifest.xml 权限配置
<uses-permission android:name="android.permission.ANSWER_PHONE_CALLS" />
<uses-permission android:name="android.permission.CALL_PHONE" />

// 代码实现
private fun endCallAction() {
    try {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
            // Android 9.0(API 28)及以上版本使用TelecomManager
            val tcm = context.getSystemService(Context.TELECOM_SERVICE) as? TelecomManager
            tcm?.let {
                // 检查权限
                if (checkSelfPermission(Manifest.permission.ANSWER_PHONE_CALLS) == 
                    PackageManager.PERMISSION_GRANTED) {
                    it.endCall()
                } else {
                    // 请求权限
                    requestPermissions(arrayOf(Manifest.permission.ANSWER_PHONE_CALLS), 
                        REQUEST_CODE_ANSWER_PHONE_CALLS)
                }
            }
        } else {
            // Android 9.0以下版本使用反射调用ITelephony
            val loadClass: Class<*> = javaClass.classLoader?.loadClass("android.os.ServiceManager") 
                ?: throw ClassNotFoundException("ServiceManager class not found")
            val method: Method = loadClass.getDeclaredMethod("getService", String::class.java)
            val invoke: IBinder = method.invoke(null, Context.TELEPHONY_SERVICE) as IBinder
            val iTelephony: ITelephony = ITelephony.Stub.asInterface(invoke)
            iTelephony.endCall()
        }
    } catch (e: Exception) {
        e.printStackTrace()
        Log.e("EndCall", "Failed to end call", e)
        // 可以在这里添加错误提示或其他处理逻辑
    }
}

四、未来发展趋势

4.1 TelecomManager的废弃警告

值得注意的是,在最新版本中TelecomManagerendCall()方法也被标记为@Deprecated

/**
 * @deprecated Companion apps for wearable devices should use the {@link InCallService} API
 * instead. Apps performing call screening should use the {@link CallScreeningService} API instead.
 */
@RequiresPermission(Manifest.permission.ANSWER_PHONE_CALLS)
@Deprecated
public boolean endCall() { ... }

4.2 未来的替代方案

根据官方建议,未来的实现方向将分为两类:

  1. 可穿戴设备应用:使用InCallService API
  2. 电话拦截应用:使用CallScreeningService API

具体实现可参考:

五、总结

Android系统挂断电话的实现方式经历了从ITelephony.aidlTelecomManager,再到InCallService/CallScreeningService的演变。在实际开发中,需要注意以下几点:

  1. 根据目标Android版本选择合适的实现方式
  2. 做好权限管理和异常处理
  3. 关注API的更新和变化
  4. 保持代码的可维护性和兼容性

通过合理的实现方式和完善的异常处理,可以确保应用在各个Android版本上都能稳定地实现挂断电话的功能。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

清霜辰

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值