首先简单介绍一下sip协议,sip是会话启动协议,主要用于网络多媒体通话。必须是android2.3或其以上版本才可以调用Sip api,并且设备必须支持sip才可以进行sip通话。
SIP使用的api主要放在android.net.sip中,其中最核心的类为SipManager.java,关系图如下所示:
本地的SipProfile存放在一个xml文件中,主要用于保存sip的username,domain和password,SharedPreference配置文件如下所示:
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"> <EditTextPreference android:name="SIP Username" android:summary="Username for your SIP Account" android:defaultValue="" android:title="Enter Username" android:key="namePref" /> <EditTextPreference android:name="SIP Domain" android:summary="Domain for your SIP Account" android:defaultValue="" android:title="Enter Domain" android:key="domainPref" /> <EditTextPreference android:name="SIP Password" android:summary="Password for your SIP Account" android:defaultValue="" android:title="Enter Password" android:key="passPref" android:password="true" /> </PreferenceScreen>更新SharedPreference的代码如下:
public void updatePreferences() { Intent settingsActivity = new Intent(getBaseContext(), SipSettings.class); startActivity(settingsActivity); }调用 updatePreferences()方法会有如下的效果图显示:
通过此界面可以修改本地的SipProfile帐号信息。
接打电话时需要更新对方SipProfile的信息,代码如下:
/** * Updates the status box at the top of the UI with a messege of your choice. * @param status The String to display in the status box. */ 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()); }拨电话代码如下:
/** * 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(); 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(); } } }
// Set up the intent filter. This will be used to fire an // IncomingCallReceiver when someone calls the SIP address used by this // application. IntentFilter filter = new IntentFilter(); filter.addAction("android.SipDemo.INCOMING_CALL"); callReceiver = new IncomingCallReceiver(); this.registerReceiver(callReceiver, filter);
package com.example.android.sip; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.net.sip.*; /** * Listens for incoming SIP calls, intercepts and hands them off to WalkieTalkieActivity. */ public class IncomingCallReceiver extends BroadcastReceiver { /** * Processes the incoming call, answers it, and hands it over to the * WalkieTalkieActivity. * @param context The context under which the receiver is running. * @param intent The intent being received. */ @Override public void onReceive(Context context, Intent intent) { System.out.println("IncomingCallReceiver::::::"); SipAudioCall incomingCall = null; try { SipAudioCall.Listener listener = new SipAudioCall.Listener() { @Override public void onRinging(SipAudioCall call, SipProfile caller) { try { call.answerCall(30); } catch (Exception e) { e.printStackTrace(); } } }; WalkieTalkieActivity wtActivity = (WalkieTalkieActivity) context; incomingCall = wtActivity.manager.takeAudioCall(intent, listener); incomingCall.answerCall(30); incomingCall.startAudio(); incomingCall.setSpeakerMode(true); if(incomingCall.isMuted()) { incomingCall.toggleMute(); } wtActivity.call = incomingCall; wtActivity.updateStatus(incomingCall); } catch (Exception e) { if (incomingCall != null) { incomingCall.close(); } } } }
/** * Handles SIP authentication settings for the Walkie Talkie app. */ public class SipSettings extends PreferenceActivity { @Override public void onCreate(Bundle savedInstanceState) { // Note that none of the preferences are actually defined here. // They're all in the XML file res/xml/preferences.xml. super.onCreate(savedInstanceState); addPreferencesFromResource(R.xml.preferences); System.out.println("SipSettings::::::::::"); } }