Android Tutorial Android Sip / Voip tutorial

With the new Sip library you can make audio calls using Voip (Voice over IP) services.
Sip features were added in Android 2.3 (API level 9). Note that not all devices above Android 2.3 support Sip features.

In order to use this library you will need to set android.jar in Tools > Configure Paths to platform-9 or above.

The library includes two types of objects: Sip and SipAudioCall. Sip is the main object which manages the Sip services. Once you make a call or receive an incoming call you will get a SipAudioCall which represents the call.

In this example the Sip code is written in the main Activity. A better solution is to manage the Sip services from a Service module. Otherwise you may lose incoming calls if the Activity is not in the foreground.

Registration
The first step is to register to the server.
B4X:
Sub Activity_Create(FirstTime As Boolean)
   If Sip.IsInitialized = False Then
      'Check if SIP and VOIP are supported.
      If Sip.IsSipSupported = False OR Sip.IsVoipSupported = False Then
         Log("Not supported.")
         ToastMessageShow("SIP not supported.", True)
      Else
         'Register with the VOIP service
         Sip.Initialize2("SIP", "sip:[email protected]", "xxx")
         Sip.Register
      End If
   End If
   Activity.LoadLayout("1")
End Sub

Sub SIP_Registering
   Log("Registering")
End Sub

Sub SIP_RegistrationFailed (ErrorCode As Int, ErrorMessage As String)
   Log("Failed, ErrorCode=" & ErrorCode & ", Message=" & ErrorMessage)
   ToastMessageShow("Registration failed.", True)
End Sub

Sub SIP_RegistrationDone (ExpiryTime As Long)
   Log("RegistrationDone, ExpiryTime=" & ExpiryTime)
   ToastMessageShow("SIP registered sucessfully", True)
   btnMakeCall.Enabled = True
End Sub
Registering is done by initializing the Sip object with your account Uri and password and calling Register.
The actual registration is done in the background.
RegistrationDone event is raised when registration completes successfully (with the expiry time measured in seconds). If there is a problem then RegistrationFailed will be raised.
The error codes are available here.

Making calls
Now that the Sip is registered we can make audio calls.
This is done by calling Sip.MakeCall.
For example, this code calls a free directory service:
B4X:
Sub btnMakeCall_Click
   CurrentCall = Sip.MakeCall("sip:[email protected]", 30)
End Sub
CurrentCall is of type SipAudioCall and it is declared in Process_Globals.
You should now wait for the CallEstablished event (or CallError if there is a problem).
CallEstablished event is raised when the other side answers the call.
B4X:
Sub SIP_CallEstablished
   'Check that we are not already in a call.
   'Seems like this event can be raised by the SIP service multiple times.
   If CurrentCall.IsInCall Then Return

   CurrentCall.StartAudio 'Start the audio
   CurrentCall.SpeakerMode = True
   ToastMessageShow("Call established", True)
End Sub
When the call is established we need to call StartAudio and set SpeakerMode to True in order to start talking.

As you can see in the above code, we first check if CurrentCall.IsInCall is false. It will be true after the StartAudio call. It seems that the internal Sip service raises the CallEstablished more than once for a single call. This way we make sure that our code only runs once for each call.

Incoming calls
When there is an incoming call, the CallRinging event will be raised:
B4X:
'Incoming call
Sub SIP_CallRinging (IncomingCall As SipAudioCall)
   Log("CallRinging")
   ToastMessageShow("Ringing from: " & IncomingCall.PeerUri, True)
   CurrentCall = IncomingCall
End Sub

'Answers an incoming call
Sub btnAnswer_Click
   CurrentCall.AnswerCall(30)
End Sub
A SipAudioCall is passed in this event. We should hold a reference to this object. Calling AnswerCall will cause the call to be established and will raise the CallEstablished event.

See the attached example for a simple program that calls a free directory service and handles incoming calls.

In order to test it you can register to Welcome to iptel.org, the IP Telecommunications Portal | iptel.org. I registered two accounts and then I was able to call from the computer to the device (to test the incoming calls).

The library is available here: http://www.b4x.com/forum/additional-libraries-official-updates/13089-sip-voip-library.html#post73694
 

Attachments

  • Sip.zip
    6.9 KB · Views: 11,076

luke2012

Well-Known Member
Licensed User
Longtime User

This is my first approach to Service Module.
In a service perspective I have to initialize the SIP object (the same code of the Activity_Create) within the Service_Create, correct?

The service must include also the "SIP_CallRinging" event in order to instantiate the "CurrentCall" object correct?
 

luke2012

Well-Known Member
Licensed User
Longtime User
Erel as you suggested I'm implementing a service that handle SIP calls.

The service start at system boot and initialize the SIP & CurrentCall objects.

It's work fine also when the app isn't in foreground but when a user close the app (for example with Android task manager) also the Process Global objects are killed (SIP & CurrentCall) and the SIP service became unavailable for the Caller.

Implementing a specific app that handle SIP service and a specific app that handle user interface could solve the problem?
Any other solution ?
 

luke2012

Well-Known Member
Licensed User
Longtime User
I read the "long running background tasks" and I'm thinking to implement the 2° solution "Service.StartForeground".

1) In this scenario I have to change the automatic "start at boot" (B4A) to "Service.StartForeground".
2) I have to execute the app at system boot in order to call Service.StartForeground method (I need that the service will be always available at system boot).

Is this correct?
 
Last edited:

luke2012

Well-Known Member
Licensed User
Longtime User
If the user has installed a custom task manager then he can kill the process no matter what...

Service.StartForeground is not really related to "start at boot". Just call Service.StartForeground in Service_Create.

Assuming that the user cannot install custom task manager, I can set the service as "Start at boot" and call Service.StartForeground in Service_Create in order to have a always available service?
 

luke2012

Well-Known Member
Licensed User
Longtime User
I implemented a service that handle sip calls.
My tests :

1) Calling from SIP sample app to my app (sip as service) = OK
2) Calling from my app to my app = no audio (all events are raised as expected)

The difference points are:

1) The SIP and SipAudioCall objects are created in the Service module
2) The SIP_CallRinging and SIP_CallEstablished has been implemented within the Service module (the code are the same of the sample app)
 
Last edited:

luke2012

Well-Known Member
Licensed User
Longtime User
I'm using the code of the example to initialize SIP within the Service.
The SIP_Calling event is raised so the SIP is initialized.

If you want I can send you the project (I prefer via eMail).
 
Last edited:

luke2012

Well-Known Member
Licensed User
Longtime User
Your code looks correct. The problem is that CurrentCall.StartAudio doesn't have any effect when its done in the service, right?

Yes!
If the caller is a CurrentCall object within the main activity in the foregroud app (your example attached in this tutorial) and the "receiver" is a CurrentCall object within the service (my code) I can hear the audio.

The problem is between my service and my service (in this case the CurrentCall object in both case is within the service).
 

luke2012

Well-Known Member
Licensed User
Longtime User
Not sure why it happens. You can try to show an activity during the call.

I known that the service interact only with logs & Notify messagges.
Could be that it can't interact directly with the audio of the phone ?
 
Top