Android 电话状态的监听和回调

知识储备

实现手机电话状态的监听,主要依靠两个类:TelephonyManager和PhoneStateListener。TelephonyManager提供手机的基本信息,PhoneStateListener提供来电状态的监听和回调。

TelephonyManager

在监听状态的时候,我用到了TelephonyManager.CALL_STATE_IDLE:
1、TelephonyManager.CALL_STATE_IDLE:当前状态为挂断
2、TelephonyManager.CALL_STATE_OFFHOOK:当前状态为接听或拨打
3、TelephonyManager.CALL_STATE_RINGING:当前状态为响铃

PhoneStateListener

需要重写onCallStateChanged(int state, String mobile)方法,以监听电话状态并作出回调

权限

需要以下几个权限来实现功能:

<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.CALL_PHONE" />
<uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS" />
<uses-permission android:name="android.permission.modify_phone_state" />
<uses-permission android:name="android.permission.READ_CONTACTS" />
<uses-permission android:name="android.permission.RECEIVE_USER_PRESENT" />

解析

首先,需要写一个类来管理整个监听机制和回调,CallingStateListener,继承PhoneStateListener,在应用程序的活动中完成启动监听和结束监听的操作。

public class CallingStateListener extends PhoneStateListener {

    private boolean isListening = false; //是否正在回调
    private int CALL_STATE = TelephonyManager.CALL_STATE_IDLE; //电话状态

    private TelephonyManager mTelephonyManager = null;
    /**
     * 回调
     */
    private OnCallStateChangedListener mOnCallStateChangedListener = null;

    /**
     * @param context 上下文
     */
    public CallingStateListener(Context context) {
        mTelephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
    }

    /**
     * 启动监听
     *
     * @return
     */
    public boolean startListener() {
        if (isListening) {
            return false;
        }
        isListening = true;
        mTelephonyManager.listen(this, PhoneStateListener.LISTEN_CALL_STATE);
        return true;
    }

    /**
     * 结束监听
     *
     * @return
     */
    public boolean stopListener() {
        if (!isListening) {
            return false;
        }
        isListening = false;
        mTelephonyManager.listen(this, PhoneStateListener.LISTEN_NONE);
        return true;
    }

    /**
     * @param state       状态
     * @param mobilePhone 手机号
     */
    @Override
    public void onCallStateChanged(int state, String mobilePhone) {
        switch (state) {
            //当前状态为挂断
            case TelephonyManager.CALL_STATE_IDLE:
                if (mOnCallStateChangedListener != null) {
                    mOnCallStateChangedListener.onCallStateChanged(OnCallStateChangedListener.STATE_IDLE, mobilePhone);
                }
                CALL_STATE = state;
                break;
            //当前状态为接听或拨打
            case TelephonyManager.CALL_STATE_OFFHOOK:
                if (mOnCallStateChangedListener != null) {
                    mOnCallStateChangedListener.onCallStateChanged(CALL_STATE == TelephonyManager.CALL_STATE_RINGING ?
                            OnCallStateChangedListener.STATE_IN : OnCallStateChangedListener.STATE_OUT, mobilePhone);
                }
                CALL_STATE = state;
                break;
            //当前状态为响铃
            case TelephonyManager.CALL_STATE_RINGING:
                if (mOnCallStateChangedListener != null) {
                    mOnCallStateChangedListener.onCallStateChanged(OnCallStateChangedListener.STATE_RINGING, mobilePhone);
                }
                CALL_STATE = state;
                break;
        }
    }


    /**
     * 监听回调
     *
     * @param onCallStateChangedListener OnCallStateChangedListener
     */
    public void setOnCallStateChangedListener(OnCallStateChangedListener onCallStateChangedListener) {
        this.mOnCallStateChangedListener = onCallStateChangedListener;
    }

    /**
     * 监听回调
     */
    public interface OnCallStateChangedListener {

        int STATE_IDLE = 0;//已挂断
        int STATE_IN = 1;//正在接听(已接通)
        int STATE_OUT = 2;//正在拨打(已接通或未接通)
        int STATE_RINGING = 3;//未接听,正在响铃

        /**
         * @param state  状态
         * @param number 手机号
         */
        void onCallStateChanged(int state, String number);
    }
}

并在应用程序的活动的onCreate()中和onDestory()中,分别调用startListener()和stopListener(),例:

mCallingStateListener = new CallingStateListener(context);
        mCallingStateListener.setOnCallStateChangedListener(this);
        mCallingStateListener.startListener();
if (mCallingStateListener != null) {
                    mCallingStateListener.stopListener();
                }

最后写一个控制类用于活动UI或数据和监听结果之间的交互。

public class CallingScreenStateListener implements CallingStateListener.OnCallStateChangedListener {

    private static final String TAG = "CallingScreenStateListener";

    private Context mContext = null;
    //监听回调
    private CallingStateListener mCallingStateListener = null;

    public CallingScreenStateListener(Context context) {
        this.mContext = context;
        mCallingStateListener = new CallingStateListener(context);
        mCallingStateListener.setOnCallStateChangedListener(this);
        mCallingStateListener.startListener();
    }

    public void stopListener() {
        mCallingStateListener.stopListener();
        mScreenObserver.shutdownObserver();
    }


    /********************************** 监听电话 回调 ****************************************/

    /**
     * @param state  监听状态
     * @param number 手机号
     */
    @Override
    public void onCallStateChanged(int state, final String number) {
        switch (state) {
            case CallingStateListener.OnCallStateChangedListener.STATE_RINGING:
                LogHelper.i(TAG, "当前状态为响铃,来电号码:" + number);
                //对应的数据交互方法
                break;
            case CallingStateListener.OnCallStateChangedListener.STATE_IN:
                LogHelper.i(TAG, "当前状态为接听");
                //对应的数据交互方法
                break;
            case CallingStateListener.OnCallStateChangedListener.STATE_OUT:
                LogHelper.i(TAG, "当前状态为拨打,拨打号码:" + number);
                //对应的数据交互方法
                break;
            case CallingStateListener.OnCallStateChangedListener.STATE_IDLE:
                LogHelper.i(TAG, "当前状态为挂断");
                //对应的数据交互方法
                break;
        }
    }
}

对于数据交互的方法,各人业务需求不一样。在我的运用中,是来电时,非锁屏状态下弹出活动,锁屏状态下自定义锁屏状态,其余状态不作操作。思路仅供大家参考。

你可能感兴趣的:(Android)