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); } }