首先簡單介紹一下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(); } } }}
設定本地sip:
/** * 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::::::::::"); }}