Android实现电话来电自动接听功能

目录

 

前言

一、效果展示

二、实现分析

三、具体业务调整

四、总结


前言

关于手机来电自动接听这个需求公司领导提了有一段时间了,直到最近才开始处理这个功能。拿到这个需求,先分析了一下,肯定是牵扯到硬件层和系统层面了,到网上查了资料之后,发现都是大同小异,你抄他他抄你的,尝试了几种方案,适配性较差,最后找到了一篇文章,地址在这:https://blog.csdn.net/z82367825/article/details/78820559?utm_source=blogxgwz1,这篇文章的适配结果还是较为理想的,感谢这位小伙伴!

一、效果展示

1、中兴 ZTE BV0730 Android6.0系统

2、小米 MI MAX3 Android8.1系统

3、小米 MI8 Android8.1系统

二、实现分析

这个功能目前没找到Android7.0版本的手机,所以没有在7.x版本上测试过是否可行,网上有人说7.0的不行,后面如果有手机,测试结果我会及时更新到文章中。主要的实现思路和代码实现,都是参考的上面那篇文章,所以我这里就不在详细说了,有需要的直接点击链接查看即可:https://blog.csdn.net/z82367825/article/details/78820559?utm_source=blogxgwz1

大致分析一下:网上有些通过aidl结合反射机制的方法在很多手机上都不适用了,所以作者更换了思路,对不同版本的系统单独进行适配。首先,Android API大于等于19的时候,通过对AudioManager模拟耳机按键事件,来实现自动接听,当Android API小于19的时候,dispatchMediaKeyEvent方法是不支持的,所以又通过Runtime.getRuntime().exec来执行底层Linux下的程序或脚本((bat),adb shell input keyevent “value” 一般用于模拟物理事件)。在Android8.0出来之后,由于Android系统的安全性提高了,无法随意地模拟耳机按键事件。但是Android8.0官方推出了API让我们可以实现自动接听,官方文档说明 https://developer.android.com/about/versions/oreo/android-8.0.html?hl=zh-cn ,Android8.0引入了新的权限ANSWER_PHONE_CALLS,我们可以通过调用TelecomManager#acceptRingingCall()直接实现接听。

需要注意的是ANSWER_PHONE_CALLS这权限被声明为必须动态获取的权限,并且8.0以后的权限一组权限中的单一权限必须单独申请,不会出现一组中一个有全都有的情况了,所以作者又针对targetSDKVersion作了一层判断,如果targetSDKVersion小于23,转换思路通过通知栏去获取Telecom进程的MediaController去模拟耳机按键事件。这样就完成了自动接听的适配。所有的接听功能,都是在Activity运行时调用,所以作者还写了一个不可见的空白Activity,它的作用是让应用置于前台状态,确保以上的功能能够顺利调用,简单来说就是起到了保活的作用。

三、具体业务调整

在我的项目中还有一个需求时要求针对指定的某些来电号码进行自动接听,所以我对作者的代码作了一点改动,又进行了一层来电号码监听的处理,需要通过TelephonyManager对象去实现PhoneStateListener的一个回调监听,代码也很简单:

package com.nari.yihui.helper;

import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.telephony.PhoneStateListener;
import android.telephony.TelephonyManager;

import com.nari.yihui.ui.activity.CallWorkActivity;
import com.nari.yihui.utils.LogUtil;

/**
 * @作者:纪安奇
 * @时间:2018/10/16 14:13
 * @描述:通过广播监听来电
 */

@SuppressWarnings("ALL")
public class CallReceiver extends BroadcastReceiver {

    private static int mState = -1;

    @Override
    public void onReceive(final Context context, Intent intent) {
        if (!intent.getAction().equals(Intent.ACTION_NEW_OUTGOING_CALL)) {
            TelephonyManager telephonyManager = (TelephonyManager) context.getSystemService(Service.TELEPHONY_SERVICE);
            telephonyManager.listen(new PhoneStateListener() {
                @Override
                public void onCallStateChanged(int state, String incomingNumber) {
                    LogUtil.e("---------------"+state + "------" + mState);
                    if (mState != state) {
                        mState = state;
                        switch (state) {
                            case TelephonyManager.CALL_STATE_RINGING: //来电
                                if (incomingNumber.equals("022" + UserManager.getInstance().getUser().getObj().getUser().getSipid())) {
                                    LogUtil.e("监听接听电话---------" + incomingNumber);
                                    Intent workIntent = new Intent(context, CallWorkActivity.class);
                                    workIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                                    context.startActivity(workIntent);
                                }
                                break;
                            case TelephonyManager.CALL_STATE_OFFHOOK:
                                break;
                            case TelephonyManager.CALL_STATE_IDLE:
                                break;
                        }
                    }
                    super.onCallStateChanged(state, incomingNumber);
                }
            }, PhoneStateListener.LISTEN_CALL_STATE);
        }
    }
}

四、总结

因为国内的安卓手机都是各大厂商自己进行的ROM的定制,加上并没有那么多的手机测试,所以可能实际使用中还会碰到问题,所以如果有朋友用了这个功能发现有问题的,麻烦告知机型和系统版本号,感谢!完整代码原文中也有,这里也再附上GitHub地址:https://github.com/82367825/CallHepler

发布了48 篇原创文章 · 获赞 47 · 访问量 9万+

猜你喜欢

转载自blog.csdn.net/JArchie520/article/details/83274494