PhoneCallStateObserver.java 4.94 KB
Newer Older
konghaorui committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148
package com.yidianling.avchatkit.receiver;

import android.telephony.TelephonyManager;
import android.text.TextUtils;
import android.util.Log;

import com.netease.nimlib.sdk.Observer;
import com.netease.nimlib.sdk.avchat.AVChatCallback;
import com.netease.nimlib.sdk.avchat.AVChatManager;
import com.yidianling.avchatkit.common.log.LogUtil;

import java.util.ArrayList;
import java.util.List;

/**
 * Created by huangjun on 2015/5/13.
 */
public class PhoneCallStateObserver {

    public enum PhoneCallStateEnum {
        IDLE,           // 空闲
        INCOMING_CALL,  // 有来电
        DIALING_OUT,    // 呼出电话已经接通
        DIALING_IN      // 来电已接通
    }

    private final String TAG = "PhoneCallStateObserver";

    private int phoneState = TelephonyManager.CALL_STATE_IDLE;
    private PhoneCallStateEnum stateEnum = PhoneCallStateObserver.PhoneCallStateEnum.IDLE;

    private List<Observer<Integer>> autoHangUpObservers = new ArrayList<>(1); // 与本地电话互斥的挂断监听

    private static class InstanceHolder {
        public final static PhoneCallStateObserver instance = new PhoneCallStateObserver();
    }

    private PhoneCallStateObserver() {

    }

    public static PhoneCallStateObserver getInstance() {
        return InstanceHolder.instance;
    }

    public void onCallStateChanged(String state) {
        Log.i(TAG, "onCallStateChanged, now state =" + state);

        stateEnum = PhoneCallStateEnum.IDLE;
        if (TelephonyManager.EXTRA_STATE_IDLE.equals(state)) {
            phoneState = TelephonyManager.CALL_STATE_IDLE;
            stateEnum = PhoneCallStateEnum.IDLE;
        } else if (TelephonyManager.EXTRA_STATE_RINGING.equals(state)) {
            phoneState = TelephonyManager.CALL_STATE_RINGING;
            stateEnum = PhoneCallStateEnum.INCOMING_CALL;
        } else if (TelephonyManager.EXTRA_STATE_OFFHOOK.equals(state)) {
            int lastPhoneState = phoneState;
            phoneState = TelephonyManager.CALL_STATE_OFFHOOK;
            if (lastPhoneState == TelephonyManager.CALL_STATE_IDLE) {
                stateEnum = PhoneCallStateEnum.DIALING_OUT;
            } else if (lastPhoneState == TelephonyManager.CALL_STATE_RINGING) {
                stateEnum = PhoneCallStateEnum.DIALING_IN;
            }
        }

        handleLocalCall();
    }

    /**
     * 处理本地电话与网络通话的互斥
     */
    public void handleLocalCall() {
        LogUtil.i(TAG, "notify phone state changed, state=" + stateEnum.name());

        if (stateEnum != PhoneCallStateEnum.IDLE) {
            AVChatManager.getInstance().hangUp2(AVChatManager.getInstance().getCurrentChatId(), new HandleLocalCallCallback(1));
        }
    }

    public PhoneCallStateEnum getPhoneCallState() {
        return stateEnum;
    }

    private class HandleLocalCallCallback implements AVChatCallback<Void> {
        private int reason;
        private String log;

        public HandleLocalCallCallback(int reason) {
            this.reason = reason;
            this.log = "handle local call";
        }

        @Override
        public void onSuccess(Void param) {
            notifyObservers(autoHangUpObservers, reason);
        }

        @Override
        public void onFailed(int code) {
            notifyObservers(autoHangUpObservers, -1 * reason);
        }

        @Override
        public void onException(Throwable exception) {
            notifyObservers(autoHangUpObservers, 0);

            if (!TextUtils.isEmpty(log)) {
                LogUtil.i(TAG, log + " throws exception, e=" + exception.getMessage());
            }
        }
    }

    private <T> void notifyObservers(List<Observer<T>> observers, T result) {
        if (observers == null || observers.isEmpty()) {
            return;
        }

        // 创建副本,为了使得回调到app后,app如果立即注销观察者,会造成List异常。
        List<Observer<T>> copy = new ArrayList<>(observers.size());
        copy.addAll(observers);

        for (Observer<T> o : copy) {
            o.onEvent(result);
        }
    }

    private <T> void registerObservers(List<Observer<T>> observers, final Observer<T> observer, boolean register) {
        if (observers == null || observer == null) {
            return;
        }

        if (register) {
            observers.add(observer);
        } else {
            observers.remove(observer);
        }
    }

    /**
     * 监听网络通话发起,接听或正在进行时有本地来电的通知
     * 网络通话发起或者正在接通时,需要监听是否有本地来电(用户接通本地来电)。
     * 若有本地来电,目前Demo中示例代码的处理是网络通话自动拒绝或者挂断,开发者可以自行灵活处理。
     */
    public void observeAutoHangUpForLocalPhone(Observer<Integer> observer, boolean register) {
        LogUtil.i(TAG, "observeAutoHangUpForLocalPhone->" + observer + "#" + register);
        registerObservers(this.autoHangUpObservers, observer, register);
    }
}