知识的价值不在于占有,而在于使用。这篇文章主要讲述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状态了,很无语,不知道是不是所有手机都这样,我只试了华为手机。
相对完整一点的代码【Android Sip使用及坑】相对完整一点的代码,由于后面发现没法设置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 studio 混淆打包问题
- 深入理解Android Instant Run运行机制
- Android 获取外网IP,实测有效
- android 练习之路
- 移动端自动化之-----搭建android开发环境
- AndroidStudio 新建不同的Drawable文件夹
- Android项目导入发生的问题
- Android interface接口传值
- Android java.lang.IllegalArgumentException: Object returned from onCreateLoader must not be a non-st