Android Sip使用及坑
Posted danfengw
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android Sip使用及坑相关的知识,希望对你有一定的参考价值。
https://github.com/android/platform_development/tree/master/samples/SipDemo
上面是android自带的SipDemo,下
https://developer.android.com/reference/android/net/sip/package-summary.html
Android 官网对sip的相关使用的介绍。
使用
1、注册广播
private void registerInComingCallReceiver() {
IntentFilter filter = new IntentFilter();
filter.addAction("android.SipDemo.INCOMING_CALL");
callReceiver = new IncomingCallReceiver();
this.registerReceiver(callReceiver, filter);
}
2、实例SipManager
if (manager == null) {
manager = SipManager.newInstance(this);
}
3、SipProfile
SipProfile.Builder builder = new SipProfile.Builder("Android004", "115.236.167.22");
builder.setPassword("78cdb4164g");
// builder.setOutboundProxy("45.56.91.117");
me = builder.build();
4、设置接听电话广播,如果不需要接电话可以直接manager.open(me);就可以了
Intent i = new Intent();
i.setAction("android.SipDemo.INCOMING_CALL");
PendingIntent pi = PendingIntent.getBroadcast(this, 0, i, Intent.FILL_IN_DATA);
manager.open(me, pi, null);
5、设置是否登录成功的监听,必须在上面的open方法之后调用
manager.setRegistrationListener(me.getUriString(), new SipRegistrationListener() {
public void onRegistering(String localProfileUri) {
//修改textview显示的文字
updateStatus("Registering with SIP Server...");
}
public void onRegistrationDone(String localProfileUri, long expiryTime) {
updateStatus("Ready");
}
public void onRegistrationFailed(String localProfileUri, int errorCode,
String errorMessage) {
updateStatus("Registration failed. Please check settings.");
}
});
6、初始化电话
//sipaddress电话号码
updateStatus(sipAddress);
SipAudioCall.Listener listener = new SipAudioCall.Listener() {
// Much of the client‘s interaction with the SIP Stack will
// happen via listeners. Even making an outgoing call, don‘t
// forget to set up a listener to set things up once the call is established.
@Override
public void onCallEstablished(SipAudioCall call) {
call.startAudio();
call.setSpeakerMode(true);
call.toggleMute();
updateStatus(call);
}
@Override
public void onCallEnded(SipAudioCall call) {
updateStatus("Ready.");
}
};
call = manager.makeAudioCall(me.getUriString(), sipAddress, listener, 30);
7、关闭SipProfile
public void closeLocalProfile() {
if (manager == null) {
return;
}
try {
if (me != null) {
manager.close(me.getUriString());
}
} catch (Exception ee) {
Log.d( "Failed to close profile", ee.toString());
}
}
权限
<uses-sdk android:minSdkVersion="10" />
<uses-permission android:name="android.permission.USE_SIP" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-feature android:name="android.hardware.sip.voip" android:required="true" />
<uses-feature android:name="android.hardware.wifi" android:required="true" />
<uses-feature android:name="android.hardware.microphone" android:required="true" />
receiver
<receiver android:name=".ui.demo.sip.IncomingCallReceiver" android:label="Call Receiver"/>
坑
坑1:WalkieTalkieActivity这个类的类名不能修改,之前试过好多次,自己创建了一个类,代码也是一样的,怎么弄都登录失败,很郁闷!不知道是不是我自己的问题。
坑2:不能设置stun,要想设置自己的stun可以使用sipdroid或者想要实现网络电话的话也可以使用开源的linphone,不过lingphone需要在linux环境下进行编译,并且下载源码编译需要翻墙,所以你必须有一个好的网络环境!
坑3:closeLocalProfile()方法最好放在opause()方法中进行调用。
坑4:安装到手机上,经常出注册失败的问题,但是重启一下手机就变成ready状态了,很无语,不知道是不是所有手机都这样,我只试了华为手机。
相对完整一点的代码
相对完整一点的代码,由于后面发现没法设置stun,所以通话的建立方法一直没能实现。InComingCall类在最开头的连接中下载即可。
public class WalkieTalkieActivity extends AppCompatActivity implements View.OnClickListener {
private Button mButtonSipCall;
public String sipAddress = "111";
public SipManager manager = null;
public SipProfile me = null;
public SipAudioCall call = null;
public IncomingCallReceiver callReceiver;
private boolean isCalling = false;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.walkietalkie);
mButtonSipCall = (Button) findViewById(R.id.btn_sipcall);
mButtonSipCall.setOnClickListener(this);
registerInComingCallReceiver();
}
private void registerInComingCallReceiver() {
IntentFilter filter = new IntentFilter();
filter.addAction("android.SipDemo.INCOMING_CALL");
callReceiver = new IncomingCallReceiver();
this.registerReceiver(callReceiver, filter);
}
@Override
public void onStart() {
super.onStart();
initSipManager();
}
@Override
protected void onPause() {
super.onPause();
if (call != null) {
call.close();
}
closeLocalProfile();
if (callReceiver != null) {
this.unregisterReceiver(callReceiver);
}
}
public void initSipManager() {
if (manager == null) {
manager = SipManager.newInstance(this);
}
if (manager == null) {
return;
}
if (me != null) {
closeLocalProfile();
}
buildSipProfile();
setReceiveCallListener();
setRegistrationListener();
}
public void buildSipProfile() {
try {
SipProfile.Builder builder = new SipProfile.Builder("Android", "000.000.000.000");
builder.setPassword("abc");
me = builder.build();
} catch (ParseException e) {
e.printStackTrace();
}
}
private void setRegistrationListener() {
try {
manager.setRegistrationListener(me.getUriString(), new SipRegistrationListener() {
public void onRegistering(String localProfileUri) {
updateStatus("Registering with SIP Server...");
}
public void onRegistrationDone(String localProfileUri, long expiryTime) {
updateStatus("Ready");
initiateCall();
}
public void onRegistrationFailed(String localProfileUri, int errorCode,
String errorMessage) {
updateStatus("Registration failed. Please check settings.");
}
});
} catch (SipException e) {
e.printStackTrace();
}
}
private void setReceiveCallListener() {
try {
Intent i = new Intent();
i.setAction("android.SipDemo.INCOMING_CALL");
PendingIntent pi = PendingIntent.getBroadcast(this, 0, i, Intent.FILL_IN_DATA);
manager.open(me, pi, null);
} catch (SipException e) {
e.printStackTrace();
}
}
public void closeLocalProfile() {
if (manager == null) {
return;
}
try {
if (me != null) {
manager.close(me.getUriString());
}
} catch (Exception ee) {
Log.d( "Failed to close profile", ee.toString());
}
}
/**
* Make an outgoing call.
*/
public void initiateCall() {
updateStatus(sipAddress);
try {
SipAudioCall.Listener listener = new SipAudioCall.Listener() {
// Much of the client‘s interaction with the SIP Stack will
// happen via listeners. Even making an outgoing call, don‘t
// forget to set up a listener to set things up once the call is established.
@Override
public void onCallEstablished(SipAudioCall call) {
call.startAudio();
call.setSpeakerMode(true);
call.toggleMute();
mButtonSipCall.setText("正在拨打电话");
updateStatus(call);
}
@Override
public void onCallEnded(SipAudioCall call) {
updateStatus("Ready.");
}
};
call = manager.makeAudioCall(me.getUriString(), sipAddress, listener, 30);
} catch (Exception e) {
// Log.i("WalkieTalkieActivity/InitiateCall", "Error when trying to close manager.", e);
if (me != null) {
try {
manager.close(me.getUriString());
} catch (Exception ee) {
// Log.i("WalkieTalkieActivity/InitiateCall",
// "Error when trying to close manager.", ee);
ee.printStackTrace();
}
}
if (call != null) {
call.close();
}
}
}
public void updateStatus(final String status) {
// Be a good citizen. Make sure UI changes fire on the UI thread.
this.runOnUiThread(new Runnable() {
public void run() {
TextView labelView = (TextView) findViewById(R.id.sipLabel);
labelView.setText(status);
}
});
}
/**
* Updates the status box with the SIP address of the current call.
*
* @param call The current, active call.
*/
public void updateStatus(SipAudioCall call) {
String useName = call.getPeerProfile().getDisplayName();
if (useName == null) {
useName = call.getPeerProfile().getUserName();
}
updateStatus(useName + "@" + call.getPeerProfile().getSipDomain());
}
@Override
public void onClick(View v) {
if (isCalling){
mButtonSipCall.setText("拨打电话");
if (call != null) {
try {
call.endCall();
} catch (SipException se) {
}
call.close();
}
}else {
// putInCallNumber();
initiateCall();
if (call == null) {
return;
}else if ( call != null && call.isMuted()) {
call.toggleMute();
} else if ( call.isMuted()) {
call.toggleMute();
}
}
isCalling=!isCalling;
}
private void putInCallNumber() {
initiateCall();
// LayoutInflater factory = LayoutInflater.from(this);
// final View textBoxView = factory.inflate(R.layout.call_address_dialog, null);
// new AlertDialog.Builder(this)
// .setTitle("Call Someone.")
// .setView(textBoxView)
// .setPositiveButton(
// android.R.string.ok, new DialogInterface.OnClickListener() {
// public void onClick(DialogInterface dialog, int whichButton) {
// EditText textField = (EditText)
// (textBoxView.findViewById(R.id.calladdress_edit));
// sipAddress = textField.getText().toString();
// initiateCall();
//
// }
// })
// .setNegativeButton(
// android.R.string.cancel, new DialogInterface.OnClickListener() {
// public void onClick(DialogInterface dialog, int whichButton) {
// // Noop.
// }
// })
// .create();
}
}
以上是关于Android Sip使用及坑的主要内容,如果未能解决你的问题,请参考以下文章