简介
之前分析了Sip,过了这么久,再到官方看一下sipdroid项目,已经3.4版本了,心中产生一个念头,重新封装Sipdroid项目成.jar(项目名称为SipCore.jar),其它项目使用只要引入jar即可,我花了一个星期的业余时间重新封装了Sipdroid项目(经测试可实现互通,o(∩_∩)o 哈哈 )。
项目
先看效果图:
主要应用代码如下:
sip初始化
SipManager.getInstance().initConfig(mContext.getApplicationContext()); //实例一个sip管理
SessionManager.getInstance().initConfig(
mContext.getApplicationContext()); //实例化一个sip会话管理
SipManager.getInstance().setmIXSessionChange(
SessionManager.getInstance()); //会话监听
SipManager.getInstance().setUserName("1002"); //用户名
SipManager.getInstance().setPassword("1002"); //密码
SipManager.getInstance().setServer("baidu.com"); //域名
// SipManager.getInstance().setUseWifi(true);// wifi默认使用
SipManager.getInstance().setUse3G(true); //使用3G
SipManager.getInstance().setUseEdge(true); //使用E网
// SipManager.getInstance().setUseVpn(useVpn)
// SipManager.getInstance().setUseStun(useSTUN)
// SipManager.getInstance().setUseMMtel(useMMtel)
// ……
设置警报声,该资源来自Assets目录。
try {
SipManager.getInstance().setAlertingStream(
this.getAssets().open("alerting")); // 警报声
} catch (Exception e) {
}
监听接口如下:
if (mSipBroadcastReceiver != null)
return;
mSipBroadcastReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
int event = intent.getIntExtra(SipManager.ACTION_EVENT, 0);
if (event == 0)
return;
if (event == SipEvent.SipStatusChange) { // sip状态变化
onSipChange();
} else if (event == SipEvent.SipSessionChange) {// sip会话状态变化
}
}
};
final IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(SipManager.ACTION_TAG); // 注册事件
mContext.registerReceiver(mSipBroadcastReceiver, intentFilter);
拨打电话如下:
private void callPhone() {
mPhoneNumber = null;
mPhoneNumber = new EditText(mContext);
mPhoneNumber.setText("15079**2011");
new AlertDialog.Builder(this).setTitle("请输入")
.setIcon(android.R.drawable.ic_dialog_info)
.setView(mPhoneNumber)
.setPositiveButton("确定", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface arg0, int arg1) {
try {
SessionManager.getInstance().makeSipSession(
mPhoneNumber.getText().toString(),
CallType.OutgoCall);
// if (SipManager.getInstance().makeAudioCall(
// mPhoneNumber.getText().toString())) {
// Log.i("", "");
// }
} catch (Exception e) {
}
}
}).setNegativeButton("取消", null).show();
}
//会话管理(针对Sip电话管理类)
//一个会话包括(连接sip、连接对方、连接成功、连接结束)
//类实现(会话状态改变监听、拨打电话、监听来电等操作)
public class SessionManager implements IXTaskListener, IXSessionChangeListener {
private static String TAG = SessionManager.class.getCanonicalName();
public static SessionManager getInstance() {
if (mThis == null) {
mThis = new SessionManager();
}
return mThis;
}
private SipSession mSession;
private static SessionManager mThis;
private Context mContext;
private GSTask mSipSessionTask;
private SystemCallLogOperate mSystemCallLogOperate;
public SipSession getSession() {
return mSession;
}
public SystemCallLogOperate getSystemCallLogOperate() {
if (mSystemCallLogOperate == null) {
mSystemCallLogOperate = new SystemCallLogOperate();
mSystemCallLogOperate.initConfig(mContext);
}
return mSystemCallLogOperate;
}
public void initConfig(Context context) {
mContext = context;
}
public SipSession makeSipSession(String number, CallType callType)
throws Exception {// 开启会话
Log.i(TAG, "makeSipSession");
if (TextUtils.isEmpty(number))
throw new Exception("无效号码…");
if (callType == null)
throw new Exception("拨打出错");
if (mSession != null) {
if (mSession.getCallType() == CallType.IncomeCall
&& mSession.getCallStatus() == CallStatus.ConnectSuccess)
return null;
if (mSession.getCallType() == CallType.OutgoCall
&& mSession.getCallStatus() != CallStatus.ConnectOver)
return null;
mSession = null;
}
mSession = new SipSession(number, callType);
mSession.setCallStatus(CallStatus.ConnectSip);
if (callType == CallType.IncomeCall) { // 来电(需要建立成功后再去通话界面)
} else { // 去电(直接去通话界面)
ActivityHelp.jumpToNewActivity(mContext, SipCallStatus.class);
}
startSipSessionTask();
return mSession;
}
@Override
public boolean onSessionState(int state, String number) {
if (state == UserAgent.UA_STATE_INCOMING_CALL) {// 来电
if (mSession != null
&& mSession.getCallType() == CallType.OutgoCall
&& mSession.getCallStatus() != CallStatus.ConnectOver)
return true;
else if (mSession != null
&& mSession.getCallType() == CallType.IncomeCall
&& mSession.getCallStatus() == CallStatus.ConnectSuccess) {
return true;
}
if (mSession == null || !mSession.getNumber().equals(number)) {
mSession = null;
}
if (mSession == null) {
mSession = new SipSession(number, CallType.IncomeCall);
mSession.setCallStatus(CallStatus.ConnectSuccess);
startSipSessionTask();
}
mSession.setRingTime(System.currentTimeMillis());
mSession.setCallStatus(CallStatus.ConnectOther);
ActivityHelp.jumpToNewActivity(mContext, SipCallStatus.class);
} else if (state == UserAgent.UA_STATE_OUTGOING_CALL) {// 去电
} else if (state == UserAgent.UA_STATE_IDLE) {// 挂断等操作
if (mSession != null) {
mSession.setCallStatus(CallStatus.ConnectOver);// 结束
// 1 来电 2去电 3丢失
int callType = mSession.getCallType() == CallType.IncomeCall ? 1
: 2;
long duration = System.currentTimeMillis()
- mSession.getInCallTime();
if (mSession.getInCallTime() == 0) {
callType = 3;
duration = 0;
}
try {
getSystemCallLogOperate().insertEotuCallLog(callType,
mSession.getNumber(), "",
mSession.getEstablishTime(), duration);
} catch (Exception e) {
e.printStackTrace();
}
}
} else if (state == UserAgent.UA_STATE_INCALL) {// 通话中
if (mSession != null) {
mSession.setInCallTime(System.currentTimeMillis());
mSession.setCallStatus(CallStatus.ConnectSuccess);//
}
} else if (state == UserAgent.UA_STATE_HOLD) {// 暂停
if (mSession != null) {
// mSession.rejectcall();// 对方暂停就停止通话
}
} else if (state == UserAgent.UA_STATE_RINGRING) {// 响铃
if (mSession != null) {
mSession.setRingTime(System.currentTimeMillis());
mSession.setCallStatus(CallStatus.ConnectSuccess);// 响铃
}
} else if (state == UserAgent.UA_STATE_IDLE_NOTFOUND) {// 对方未注册(未找到)
}
return false; // false 内部处理(播放声音、电源。。。)
}
@Override
public void onTask(Task task, TaskEvent event, Object... arg2) {
if (mSipSessionTask != null && mSipSessionTask.equalTask(task)) {
if (event == TaskEvent.Work) {
try {
if (!SipManager.getInstance().isRegistered()) {
SipManager.getInstance().startSip();
}
while (true) {
if (task.isCancel())
return;
Thread.sleep(1000);// 休息一秒
SipManager.getInstance().sentEvent(
SipEvent.SipSessionChange);
if (mSession == null) {
return;
}
SipSession.connectSipIncrementing();
if (!GSNetwork.isConnect(mContext)) { // 无网络异常
mSession.setCallStatus(CallStatus.ConnectOver);
mSession = null;
continue;
}
if (mSession.getCallStatus() == CallStatus.ConnectSip) {// 连接Sip
if (SipSession.getConnectSipCount() > 30) { // 超时
mSession.setCallStatus(CallStatus.ConnectOver);
continue;
}
if (!SipManager.getInstance().isRegistered()) {
continue;
}
mSession.setCallStatus(CallStatus.ConnectOther);// 进入第二阶段(连接对方)
} else if (mSession.getCallStatus() == CallStatus.ConnectOther) {// 连接对方
mSession.connectOtherIncrementing();
if (mSession.getConnectOtherCount() >= 20) { // 超过3次视为超时
mSession.setCallStatus(CallStatus.ConnectOver);
continue;
}
if (mSession.getCallType() == CallType.OutgoCall
&& mSession.getConnectOtherCount() % 6 == 1) {// 5秒一次呼叫对方(对话响应直接跳入第三阶段)
Thread.sleep(3000); // 等3秒 让对方登陆
SipManager.getInstance().makeAudioCall(
mSession.getNumber());
}
continue;
// 对方响铃自动 进入第三阶段(与对方通话)
} else if (mSession.getCallStatus() == CallStatus.ConnectSuccess) {// 与对方通话
continue;
} else if (mSession.getCallStatus() == CallStatus.ConnectOver) {// 结束
continue;
}
}
} catch (Exception e) {
e.printStackTrace();
if (mSession != null)
mSession.setCallStatus(CallStatus.ConnectOver);
}
} else if (event == TaskEvent.Before) {
SipSession.resetConnectSipCount();
} else if (event == TaskEvent.Cancel) {
SipManager.getInstance().stopSip();
SipManager.getInstance().sentPostEvent(
SipEvent.SipSessionChange, 2);
}
}
}
public void releaseConfig() {
if (mSipSessionTask != null)
mSipSessionTask.stopTask();
mSipSessionTask = null;
}
private void startSipSessionTask() {
if (mSipSessionTask == null) {
mSipSessionTask = new GSTask();
mSipSessionTask.setIXTaskListener(this);
}
if (!mSipSessionTask.isTasking())
mSipSessionTask.startTask();
}
}
结论
sipdroid3.4重新封装,对其它项目直接使用提供了便捷。
问题:把Sip放入到后台服务中经常出现“No SipListener found matching that message: message DISCARDED“信息
什么原因?原因如下:
02-26 03:30:55.415: W/System.err(292): java.lang.NullPointerException
02-26 03:30:55.415: W/System.err(292): at com.sipdroid.core.SipReceiver.playRingtone(SipReceiver.java:204)
02-26 03:30:55.435: W/System.err(292): at com.sipdroid.core.SipReceiver.onSessionState(SipReceiver.java:76)
02-26 03:30:55.435: W/System.err(292): at org.sipdroid.sipua.UserAgent.changeStatus(UserAgent.java:102)
02-26 03:30:55.465: W/System.err(292): at org.sipdroid.sipua.UserAgent.onCallIncoming(UserAgent.java:582)
02-26 03:30:55.475: W/System.err(292): at org.zoolu.sip.call.Call.onDlgInvite(Call.java:261)
02-26 03:30:55.486: W/System.err(292): at org.zoolu.sip.dialog.InviteDialog.onTransRequest(InviteDialog.java:852)
02-26 03:30:55.495: W/System.err(292): at org.zoolu.sip.transaction.InviteTransactionServer.onReceivedMessage(InviteTransactionServer.java:211)
02-26 03:30:55.515: W/System.err(292): at org.zoolu.sip.provider.SipProvider.processReceivedMessage(SipProvider.java:1089)
02-26 03:30:55.515: W/System.err(292): at org.zoolu.sip.provider.SipProvider.onReceivedMessage(SipProvider.java:1201)
02-26 03:30:55.565: W/System.err(292): at org.zoolu.sip.provider.UdpTransport.onReceivedPacket(UdpTransport.java:117)
02-26 03:30:55.565: W/System.err(292): at org.zoolu.net.UdpProvider.run(UdpProvider.java:189)
在执行的时候发生一个错误导致listener = null了。代码如下:
/** The main thread */
public void run() {
byte[] buf = new byte[BUFFER_SIZE];
UdpPacket packet = new UdpPacket(buf, buf.length);
Exception error = null;
long expire = 0;
if (alive_time > 0)
expire = System.currentTimeMillis() + alive_time;
try {
// socket.setSoTimeout(socket_timeout); modified
// loop
while (!stop) {
try {
socket.receive(packet);
} catch (InterruptedIOException ie) {
if (alive_time > 0 && System.currentTimeMillis() > expire)
halt();
continue;
}
if (packet.getLength() >= minimum_length) {
if (listener != null)
listener.onReceivedPacket(this, packet);
if (alive_time > 0)
expire = System.currentTimeMillis() + alive_time;
}
packet = new UdpPacket(buf, buf.length);
}
} catch (Exception e) {
error = e;
stop = true;
}
is_running = false;
if (listener != null)
listener.onServiceTerminated(this, error);
listener = null;
}