清霜辰-博客

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

本文首发地址:https://blog.csdn.net/CSqingchen/article/details/121426660
最新更新地址:https://gitee.com/chenjim/chenjimblog

在 ITelephony.aidl 8.0 源码9.0 源码 中存在 endCall() 接口
10 源码 中,已经没有 endCall() 接口
在 Android 10 之前可以通过如下方式 挂断 电话

//详细 参见   https://www.jianshu.com/p/a5662fad84b5  
public void endCall() {
    try {
        //1.通过类加载器加载相应类的class文件
        //Class<?> forName = Class.forName("android.os.ServiceManager");
        Class<?> loadClass = getClassLoader().loadClass("android.os.ServiceManager");
        //2.获取类中相应的方法
        //name : 方法名
        //parameterTypes : 参数类型
        Method method = loadClass.getDeclaredMethod("getService", String.class);
        //3.执行方法,获取返回值
        //receiver : 类的实例
        //args : 具体的参数
        IBinder invoke = (IBinder) method.invoke(null, Context.TELEPHONY_SERVICE);
        //aidl
        ITelephony iTelephony = ITelephony.Stub.asInterface(invoke);
        //挂断电话
        iTelephony.endCall();
    } catch (Exception e) {
        e.printStackTrace();
    }
}

那 Android 10 如何挂断电话呢?
在 TelephonyManager.java 9.0 源码 10.0 源码 中我们可以看到如下

    /**
     * @removed Use {@link android.telecom.TelecomManager#endCall()} instead.
     * @hide
     * @removed
     */
    @Deprecated
    @SystemApi
    @RequiresPermission(android.Manifest.permission.CALL_PHONE)
    public boolean endCall() {
        return false;
    }

是不是可以使用 android.telecom.TelecomManager#endCall() 呢 ?

看下 TelecomManager.java 源码 9.010.0,可以看到如下

    @RequiresPermission(Manifest.permission.ANSWER_PHONE_CALLS)
    @Deprecated
    public boolean endCall() {
        try {
            if (isServiceConnected()) {
                return getTelecomService().endCall(mContext.getPackageName());
            }
        } catch (RemoteException e) {
            Log.e(TAG, "Error calling ITelecomService#endCall", e);
        }
        return false;
    }

所以问题不大了,最终代码如下

AndroidManifest.xml 需 添加以下权限
<uses-permission android:name="android.permission.ANSWER_PHONE_CALLS" />
<uses-permission android:name="android.permission.CALL_PHONE" />

//注意动态申请权限(Permission.ANSWER_PHONE_CALLS)
private fun endCallAction() {
    try {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
             val tcm = context.getSystemService(Context.TELECOM_SERVICE) as TelecomManager
            tcm.endCall()
        } else {
            val loadClass: Class<*> =
                javaClass.classLoader.loadClass("android.os.ServiceManager")
            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()
    }
}

这就完了,还没有,我们再看下 TelecomManager.java 中 endcall 注释

     * @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() {   ...   }

@Deprecated @Deprecated @Deprecated
也就是将来也可能会移除,那时怎么做呢?
上面注释中看到可穿戴设备用 InCallService, 其它APP用 CallScreeningService
我们看下 InCallService.java 10.0 源码 和 CallScreeningService.java 10.0 源码
哇,类注释都非常详细,需要时参考下就好,本文暂时结束。

当前页面是本站的「Google AMP」版。查看和发表评论请点击:完整版 »