会话状态
在CSipSimple中,一个会话定义有如下的状态:
/**
* 源码非官方,如需查看请到官方地址下载源码
* 官方源码中,以下内容是int型,这样更容易被序列化及反序列化
*/
public enum InvState{
/**无效的状态,与sip堆栈不同步的情况下显示的是这种状态*/
INVALID,
/**当一个会话被发送或接收前,处于该状态*/
NULL,
/**当一个会话被发送*/
CALLING,
/**当一个会话被接收*/
INCOMING,
/**响铃*/
EARLY,
/**当2xx(成功信息)被发送*/
CONNECTING,
/**当ACK被接收或发送*/
CONFIRMED,
/**当通话结束*/
DISCONNECTED;
}
媒体状态
public class MediaState {
/** * Call currently has no media 当前会话没有媒体信息*/
public static final int NONE = 0;
/** * The media is active 当前会话媒体新正在活动 */
public static final int ACTIVE = 1;
/** * The media is currently put on hold by local endpoint 会话媒体被本地端点挂起 */
public static final int LOCAL_HOLD = 2;
/** The media is currently put on hold by remote endpoint 会话媒体被远程端点挂起 */
public static final int REMOTE_HOLD = 3;
/** The media has reported error (e.g. ICE negotiation) 会话媒体出错 */
public static final int ERROR = 4;
// Should not be constructed, just an older for int values
// Not an enum because easier to pass to Parcelable
private MediaState() { }
}
最佳通话的获取
如果当前有多个通话需要处理,CSipSimple会根据自己的一套规则对其进行筛选,选出最优的会话作为当前通话,具体筛选规则如下:
- 会话实体不为空
- 当前的会话状态 非处于[断开连接,无效或无状态]
- 会话状态没有被本地挂起
- 更早的会话有优先权
判断当前是否注册成功
/**
* 获取sip通话服务注册状态
* @param context 上下文
* @param key PreferencesProviderWrapper.HAS_ALREADY_SETUP_SERVICE
* @return */
public boolean obtainSipServiceSetupState(Context context,String key){
PreferencesProviderWrapper wrapper = new PreferencesProviderWrapper(context);
return wrapper.getPreferenceBooleanValue(key, false);
}
CSipSimple中比较重要的Action
要获取会话状态需要监听广播中的ACTION_SIP_CALL_CHANGED 的 Action 事件。
public class SipAction{
/**当会话状态改变时触发*/
public static final String ACTION_SIP_CALL_CHANGED = "com.csipsimple.service.CALL_CHANGED";
/**当账号改变时触发*/
public static final String ACTION_SIP_ACCOUNT_CHANGED = "com.csipsimple.service.ACCOUNT_CHANGED";
/**当账号被删除时触发*/
public static final String ACTION_SIP_ACCOUNT_DELETED = "com.csipsimple.service.ACCOUNT_DELETED";
/**TODO 通知注册账号已更改,与ACTION_SIP_ACCOUNT_CHANGED区别?*/
public static final String ACTION_SIP_REGISTRATION_CHANGED = "com.csipsimple.service.REGISTRATION_CHANGED";
/**媒体状态改变*/
public static final String ACTION_SIP_MEDIA_CHANGED = "com.csipsimple.service.MEDIA_CHANGED";
/**短信接收*/
public static final String ACTION_SIP_MESSAGE_RECEIVED = "com.csipsimple.service.MESSAGE_RECEIVED";
/**当前无法呼出,因为你还没注册*/
public static final String ACTION_OUTGOING_UNREGISTER = "com.csipsimple.service.ACTION_OUTGOING_UNREGISTER";
/**当前已执行一个SIP Action,但是无法呼出(呼出无法成功),因为还没注册*/
public static final String ACTION_DEFER_OUTGOING_UNREGISTER = "com.csipsimple.service.ACTION_DEFER_OUTGOING_UNREGISTER";}
如何更改
因此对于项目中CSipSimple,如何监听CSipSimple的状态变化:
- 当无网络的状态下,CSipSimple 状态一定是Error
- 当网络正常的情况下,检测SIP注册状态是否成功 obtainSipServiceSetupState
SipService-->isConnectivityValid(); 该方法可以有效的判断当前Sip软通话是否可用,是否在此方法中增加广播信息,用于通知第三方应用更改Sip软通话的可用状态。 - DynamicReceiver4 --> onReceiveInternal();
通过该方法的广播,肯定可以知道网络状态是否正常
该方法是运行在Sip执行线程上的内部接收器
当 该内部接收器接收到:
CONNECTIVITY_ACTION(网络状态变更):
ACTION_VPN_CONNECTIVITY(VPN通道):
① onConnectivityChanged 通过判断connected当前的连接情况可以初步判定当前的Sip软通话是否可用. 需要在该方法中进行广播通知
ACTION_SIP_ACCOUNT_CHANGED(账号改变):
ACTION_SIP_ACCOUNT_DELETED(账号删除):
service.setAccountRegistration() 执行账号变更,当执行过程中没有任何错误时,返回true,否则返回false;
SipManager.ACTION_SIP_CAN_BE_STOPPED(当SIP服务可以被停止时,广播发送) :
stopSipStack() 无论如何,当出现该内容时,代表SIP服务很可能进入到一个死亡的状态,需要进行强行停止,所以即使stopSipStack()在强制停止失败,仍需要将状态置成error.
ACTION_SIP_REQUEST_RESTART(重新启动服务):service.restartSipStack()
restartSipStack()重启服务前,因为Sip需要对之前的服务进行关闭,但是关闭服务可能失败, 因此在关闭失败的情况下需要发送 SIP功能故障的广播给第三方客户端
restartSipStack()方法涉及到 startSipStack()方法的调用.当PjSipService#sipStart()方法成功调用后,可认为是启动Sip服务启动成功
需要特别注意的是PjSipService#sipStart()方法的线程安全需要由上层进行确保来自pjsip的每个调用都需要在同一线程调用底层堆栈的start / stop / getInfos方法.
=======================================
2016年11月15日14:13:47
SipService#updateRegistrationsState() 该方法会对账号的注册结果进行判断,通过该方法
=========================================
2016年11月17日18:50:06
/**调整音量*/
service.adjustVolume(mainCallInfo, AudioManager.ADJUST_RAISE, AudioManager.FLAG_SHOW_UI);