I'm trying to use the native Android SIP stack to make direct SIP calls within a LAN. It appears that within the native stack, you are required to register a local profile in order to make SIP calls.
Here is the code I (try to) use to register a profile. I do not have a SIP server on this network, so I just use localhost for a domain.
if (mSipManager == null) {
mSipManager = SipManager.newInstance(mContext);
try {
SipProfile.Builder builder = new SipProfile.Builder("foo", "localhost");
builder.setPassword("bar");
mSipProfile = builder.build();
mSipManager.register(mSipProfile, 30000, new SipRegistrationListener() {
public void onRegistering(String localProfileUri) {
Log.v(TAG, "Registering with profile with SIP Server. URI: " + localProfileUri);
}
public void onRegistrationDone(String localProfileUri, long expiryTime) {
Log.v(TAG, "Registered with profile with SIP Server. URI: " + localProfileUri);
}
public void onRegistrationFailed(String localProfileUri, int errorCode,
String errorMessage) {
Log.e(TAG, "Registration failed. Code: " + Integer.toString(errorCode));
Log.e(TAG, errorMessage);
}
});
} catch (ParseException e) {
Log.e(TAG, "Unable to set up local SipProfile.", e);
} catch (SipException e) {
Log.e(TAG, "Unable to open local SipProfile.", e);
}
}
Elsewhere, here is my code for making a call:
try {
Log.v(TAG, "VOIP Supported: " + SipManager.isVoipSupported(mActivity));
Log.v(TAG, "SIP API Supported: " + SipManager.isApiSupported(mActivity));
SipProfile.Builder builder = new SipProfile.Builder(mSipUri);
SipProfile remote = builder.build();
SipAudioCall.Listener listener = new SipAudioCall.Listener() {
@Override
public void onCalling(SipAudioCall call) {
Log.d(TAG, "SIP Call initiating...");
}
@Override
public void onCallEstablished(SipAudioCall call) {
Log.d(TAG, "SIP Call established.");
call.startAudio();
call.setSpeakerMode(true);
call.toggleMute();
}
@Override
public void onCallEnded(SipAudioCall call) {
Log.d(TAG, "SIP Call ended.");
}
@Override
public void onError(SipAudioCall call, int errorCode, String errorMessage) {
Log.e(TAG, "SIP Call Error. Code: " + Integer.toString(errorCode));
Log.e(TAG, errorMessage);
}
};
mSipCall = mSipManager.makeAudioCall(mSipProfile, remote, listener, 10);
} catch (ParseException e) {
Log.e(TAG, "Unable to set up remote SipProfile.", e);
} catch (SipException e) {
Log.e(TAG, "SipAudioCall error.", e);
}
This all results in the following logcat output:
11-20 11:46:33.150 1412-1412/package.name E/XmlTest﹕ 1- Unable to open local SipProfile.
android.net.sip.SipException: SipService.createSession() returns null
at android.net.sip.SipManager.register(SipManager.java:481)
I'm unable to find further details as to why createSession is returning null; is it because I've not provided a valid server for the profile to register with? If so, is there a way to use the native SIP stack without registering with a server?
It turns out the problem is that Android's SIP stack appears to require the local SIP Profile you provide to the SIPManager (in the first codeblock above, represented by
builder
andmSipProfile
) to have a valid IP address supplied to it.Where I originally specified "localhost", you must actually provide the IP address of whatever interface you are making the SIP call over; if you are using a VPN, you must provide the IP of the VPN interface.