目录

 

前言

一、效果展示

二、实现分析

三、具体业务调整

四、总结


前言

关于手机来电自动接听这个需求公司领导提了有一段时间了,直到最近才开始处理这个功能。

一、效果展示

1、中兴 ZTE BV0730 Android6.0系统

android手机实现拨打电话功能 安卓手机接电话设置_android

2、小米 MI MAX3 Android8.1系统

android手机实现拨打电话功能 安卓手机接电话设置_电话自动接听_02

3、小米 MI8 Android8.1系统

android手机实现拨打电话功能 安卓手机接电话设置_按键事件_03

二、实现分析

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

大致分析一下:网上有些通过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);
        }
    }
}