Android SDK Reference

The Plivo Android SDK allows you to create applications capable of making and receiving calls in your Android app. This SDK support both IPv4 and IPv6 Networks, that means you can make and receive calls when your device is connected to a network that uses IPv4, IPv6, or both versions of the protocol. The SDK currently supports Android version 6 and above.

This document gives an overview of different classes and methods available in Plivo Android SDK V2.0.0

New in Android SDK v2.0.0

  1. Incoming call support through firebase push notifications

  2. SDK is provided in both .aar file format

  3. Android SDK support starting from Android 6.0 until latest Android 9

  4. New Example application which covers all the SDK features.

Initialization of application

Registering an endpoint

  1. Declare or use user input for the sip uri endpoint and password from Plivo Console.

    public final static String PLIVO_USERNAME = “Tatooine”; public final static String PLIVO_PASSWORD = “Jabba”;

  2. Instantiate the Endpoint class.

    Endpoint endpoint = Endpoint.newInstance(true, this);

  3. Login with FCM token:

    endpoint.login(username, password, fcmToken);

Login after fetching FCM token from Firebase.

  1. Login with without FCM token:

    endpoint.login(username, password, regTimeout);

    Refer the doc for more info on the login methods.

Examples of basic call actions

Make an outbound call

To make an outbound call, use the following code:

public final static String PHONE_NUMBER = "1415XXXXXXX";
Outgoing outgoing = endpoint.createOutgoingCall();
outgoing.call(PHONE_NUMBER);

Receive a call

Implement EventListener on your class and override the onIncomingCall method using the following command:

public void onIncomingCall(Incoming incoming) {
    		incoming.answer();
}

Note: Also go through the section on Setting up Push credentials to implement incoming call in Android App

Auto-connect when the network is available

Set NetworkChangeReceiver, in the onCreate() method of your class, to auto connect when the network is available.

networkReceiver = new NetworkChangeReceiver();
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
this.registerReceiver(networkReceiver, intentFilter);

Classes and Methods

Class: Endpoint

Endpoint class allows you to register a Plivo SIP Endpoint. Once an endpoint is registered, you can make and receive calls using the same.

private Endpoint endpoint() {
  return endpoint != null? endpoint: (endpoint = Endpoint.newInstance(BuildConfig.DEBUG, this));
}

Note: Creates the following endpoint objects:

public Endpoint(boolean debug, EventListener eventListener)
  • @param debug - Setting this to True turns on the Plivo SDK debug logs. Otherwise, false.

  • @param eventListener - Login, Call events Callback listener.

Following are the methods available in Endpoint class:

Method: login(String username, String password, String fcmToken)

public boolean login(String username, String password, String fcmToken)
Description:

This method is used to register an endpoint with FCM token. If the endpoint is successfully registered, a notification will be sent to the onLogin method of the EventListener. In case of a failure, notification is sent to the onLoginFailed method of the EventListener.

  • username - The username of the endpoint created on Plivo

  • password - The password of the endpoint created on Plivo

  • fcmToken - Device token obtained from firebase. FCM Token is needed to alert the user about incoming calls using Firebase push notifications.

Usage:
// retrieve FCM token & then login
FirebaseInstanceId.getInstance().getInstanceId().addOnSuccessListener(this, instanceIdResult -> {
   String newToken = instanceIdResult.getToken();
   endpoint.login(usernameView.getText().toString(), passwordView.getText().toString(), newToken);
});

Method: login(String username, String password, int regTimeout)

public boolean login(String username, String password, int regTimeout)
Description:

This method is used to register an endpoint without FCM token. If the endpoint is successfully registered, a notification will be sent to the onLogin method of the EventListener. In case of a failure, notification is sent to the onLoginFailed method of the EventListener.

Note: This login method has a limitation - Incoming call may not work if the app goes to background.

  • username - The username of the endpoint created on Plivo.

  • password - The password of the endpoint created on Plivo.

  • regTimeout - Seconds to re register if the app is in foreground. Default value is 600 seconds. Value range is from 120 sec to 86400.

Usage:
endpoint.login(usernameView.getText().toString(), passwordView.getText().toString(),  600);

Method: logout

public boolean logout()
Description:

This method is used to unregister an endpoint.

Usage:
endpoint.logout();

Method: createOutgoingCall

public Outgoing createOutgoingCall ()
Description:

Calling this method returns an Outgoing object linked to the registered endpoint. It returns an Outgoing object which can be used to make outbound calls. Calling this method on an unregistered PlivoEndpoint object returns null. To add custom headers during an outgoing call, use the extraHeaders.put function

Usage:

public void onOutgoingCall(Outgoing outgoing) {

Map<String, String> extraHeaders = new HashMap<>();
       extraHeaders.put("X-PH-Header1", "12345");
       extraHeaders.put("X-Ph-Header2", "34567");


   outgoing.callH(phoneNumberText.getText().toString(),extraHeaders);

}

Method: resetEndpoint

public void resetEndpoint ()
Description:

Calling this method would reset the Endpoint object. This method is used to re-register an endpoint when the application goes in and out of network connectivity.

Usage:
@Override
public void onLogout() {
	endpoint.resetEndpoint();
}

Class: Outgoing

The Outgoing class contains methods to make and control an outbound call.

import com.plivo.endpoint.Outgoing;
public Outgoing outgoing;

outgoing = new Outgoing(endpoint);

Following are the methods available in Outgoing class:
Method: call
	public boolean call(String dest)
Description:

Use the Call method to make an outbound call. Use the SIP URI or a number to make a call to.

Usage:
outgoing = Phone.getInstance(this).createOutgoingCall();
outgoing.call(phoneNumberText.getText().toString());

Method: mute

public boolean mute()
Description:

Calling this method on the Outgoing object mutes the call.

Usage:
if(outgoing!=null) {
   outgoing.mute();
}

Method: unmute

public boolean unmute()
Description:

Calling this method on the Outgoing object unmutes the call.

Usage:
if(outgoing!=null) {
   outgoing.unmute();
}

Method: sendDigits

public boolean sendDigits(String digit)
Description:

Calling this method on the Outgoing object with the digits sends DTMF on that call. It is to be noted that DTMF input only supports 0-9 , * and # .

Usage:
if(outgoing!=null) {
   outgoing.sendDigits(dtmfText.getText().toString());
}

Method: hangup

public void hangup()
Description:

Calling this method on the Outgoing object disconnects the call.

Usage:
outgoing.hangup();

Class: Incoming

The Incoming class contains methods to handle an incoming call. The public void onIncomingCall(Incoming incoming) eventListener will receive an object of this class.

Following are the methods available in Incoming class:

Method: answer

public void answer()
Description:

Use this method to answer an incoming call.

Usage:
incoming.answer();

Method: mute

public boolean mute()
Description:

Use this method to mute the call.

Usage:
if (incoming != null) {
   incoming.mute();
}

Method: unmute

public boolean unmute()
Description:

Use this method to unmute the call. Calling this method on an already unmuted call won’t have any effect.

Usage:
if (incoming != null) {
   incoming.unmute();
}

Method: sendDigits

public boolean sendDigits(String digit)
Description:

Calling this method on the Incoming object with the digits sends DTMF on that call. It is to be noted that DTMF input only supports 0-9 , * and # .

Usage:
if (incoming != null) {
   incoming.sendDigits(dtmfText.getText().toString());
}

Method: hangup

public void hangup()
Description:

Call this method on the Incoming object to disconnect the call.

Usage:
incoming.hangup();

Method: reject

public void reject()
Description:

Call this method to reject the incoming call.

Usage:
incoming.reject();

Class: EventListener

Following are the methods available in EventListener class:

Method: onLogin

public void onLogin()
Description:

This method will be called when registration to an endpoint is successful.

Usage:
@Override
public void onLogin() {
   notifyLogin(true);
// notified that login is success and can proceed to other screens.
}

Method: onLoginFailed

public void onLoginFailed()
Description:

This method will be called when registration to an endpoint fails.

Usage:
@Override
public void onLoginFailed() {
   notifyLogin(false);
}

Method: onIncomingCall

public void onIncomingCall(Incoming incoming)
Description:

On an incoming call to a registered endpoint, this method receives an Incoming object.

Usage:
@Override
public void onIncomingCall(Incoming incoming) {
   // create call obj
   Call inCall = new Call.Builder()
           .setId(incoming.getCallId())
           .setType(Call.TYPE.INCOMING)
           .setState(Call.STATE.RINGING)
           .setContact(contactUtils.getContact(from(incoming.getFromContact(), incoming.getFromSip())))
           .setData(incoming)
           .build();
   addToCallStack(inCall);
   handler.postDelayed(ringingTimeoutRunnable, Call.CALL_RINGING_TIMEOUT); }

Method: onIncomingCallRejected

public void onIncomingCallRejected(Incoming incoming)
Description:

On an incoming call, if the call is rejected by the caller, this method will be triggered by the Incoming object.

Usage:
@Override
public void onIncomingCallRejected(Incoming incoming) {
   Call call = getCall(incoming.getCallId());
   if (call != null) {
       call.setState(Call.STATE.REJECTED);
       removeFromCallStack(call);
   }
   handler.removeCallbacks(ringingTimeoutRunnable);
}

Method: onIncomingCallHangup

public void onIncomingCallHangup(Incoming incoming)
Description:

On an incoming call, if the call is disconnected by the caller after being answered, this method will be triggered by the Incoming object.

Usage:
@Override
public void onIncomingCallHangup(Incoming incoming) {
   Call call = getCall(incoming.getCallId());
   if (call != null) {
       call.setState(Call.STATE.HANGUP);
       removeFromCallStack(call);
   }
   handler.removeCallbacks(ringingTimeoutRunnable);
}

Method: onIncomingDigitNotification

public void onIncomingDigitNotification(String digits)
Description:

On an active endpoint, this delegate will be called with the digit received on the call. Note: “*” and “#” are received as “-6” and “-13” respectively on the SDK. App need to explicitly convert these on this callback onIncomingDigitNotification(String digits).

Usage:
@Override
public void onIncomingDigitNotification(String digit) {
   if (TextUtils.isEmpty(digit)) return;
   notifyDTMF(digit.equals("-6") ? "*" : digit.equals("-13") ? "#" : digit);
}
Method: onOutgoingCall
public void onOutgoingCall(Outgoing outgoing)
Description:

This delegate will be called with the Outgoing object when an outgoing call is ringing.

Usage:
@Override
public void onOutgoingCall(Outgoing outgoing) {
   // create call obj local to your app or app logic when outgoing call is ringing.
   Call outCall = new Call.Builder()
           .setId(outgoing.getCallId())
           .setType(Call.TYPE.OUTGOING)
           .setState(Call.STATE.RINGING)
           .setContact(contactUtils.getContact(to(outgoing.getToContact())))
           .setData(outgoing)
           .build();
   addToCallStack(outCall);
   handler.postDelayed(ringingTimeoutRunnable, Call.CALL_RINGING_TIMEOUT);
}

Method: onOutgoingCallAnswered

public void onOutgoingCallAnswered(Outgoing outgoing)
Description:

This method will be called with the Outgoing object when an outgoing call is answered.

Usage:
@Override
public void onOutgoingCallAnswered(Outgoing outgoing) {
   Call call = getCall(outgoing.getCallId());
   if (call != null) call.setState(Call.STATE.ANSWERED);
   handler.removeCallbacks(ringingTimeoutRunnable);
   notifyCallStackChange(call);
}

Method: onOutgoingCallHangup

public void onOutgoingCallHangup(Outgoing outgoing);
Description:

This method will be triggered by the Outgoing object when an outgoing call is disconnected by the called number after the call has been answered.

Usage:
@Override
public void onOutgoingCallHangup(Outgoing outgoing) {
   Call call = getCall(outgoing.getCallId());
   if (call != null) {
       call.setState(Call.STATE.HANGUP);
       removeFromCallStack(call);
   }
   handler.removeCallbacks(ringingTimeoutRunnable);
}

Method: onOutgoingCallRejected

public void onOutgoingCallRejected(Outgoing outgoing);
Description:

This method will be triggered by the Outgoing object when an outgoing call is rejected by the called number.

Usage:
@Override
public void onOutgoingCallRejected(Outgoing outgoing) {
   Call call = getCall(outgoing.getCallId());
   if (call != null) {
       call.setState(Call.STATE.REJECTED);
       removeFromCallStack(call);
   }
   handler.removeCallbacks(ringingTimeoutRunnable);
}

Method: onOutgoingCallInvalid

public void onOutgoingCallInvalid(Outgoing outgoing);
Description:

This method would be triggered by the Outgoing object when an outgoing call is made to an invalid number.

Usage:
@Override
public void onOutgoingCallInvalid(Outgoing outgoing) {
   notifyCallStackChange(new Call.Builder().setState(Call.STATE.INVALID).build());
   handler.removeCallbacks(ringingTimeoutRunnable);
}

Setting up Push Notification

The following section explains on how to receive incoming calls on the Plivo Android SDK v2 using firebase. To receiving an incoming call, you must:

  1. Create project on Firebase.

  2. Register your app on Firebase.

  3. Add Firebase config file and SDK into your app.

  4. Copy Firebase project server key to Plivo Dashboard.

Let us see each of these steps in detail.

  1. Create project on Firebase
    • Click on “Add project”
    • Add project name and click on “Create project”.
  2. Register your app on Firebase
    • Go to Android section of your Project home page.
    • Register your Android package on Firebase
    • Click on “Register app”
  3. Add firebase config file and SDK into your app.
    • Download Firebase google-services.json file.
    • Move downloaded google-services.json into your Android app module root directory.
    • Click on “next”.
    • Make required changes to Gradle of your Android app as instructed.
    • Wait for verification to be completed, then continue to console.
  4. Copy firebase project Server key to Plivo Dashboard
    • In settings of the project, Server key are present under “Cloud Messaging” tab.
    • Add Server key to “Android Push Credentials” under settings, on Plivo Dashboard.

    Note: Only 1 server key can be added per account as of now.

Resources

FAQ and Best practices

  1. Any example app how to use the Plivo SDK to make calls? Answer:
  2. How to file support tickets or report issues? Please share support tickets or issues in below format so that it will help us debug issues quickly:

    Attach below details while raising tickets to Plivo Support

    • Description of use case trying to accomplish (like app backgrounded, on wifi / mobile data, lot of network fluctuations)
    • Plivo SDK Verbose Logs (Android application logs).
      • Pointers we will be looking for logs are like all the logs with tag ‘D/PlivoEndpoint’ or ‘E/PlivoEndpoint’
      • All SIP transactions like

        SIP/2.0 100 Trying

        Via: SIP/2.0/TLS 52.9.254.127:5061;received=52.9.254.127;branch=z9hG4bKc497.8ec67418aa83e5d7d0f48ad11f78026c.0

        Via: SIP/2.0/UDP 52.220.63.151:5080;rport=5080;received=52.220.63.151;branch=z9hG4bKKK6pv4Farvy9m

        Record-Route: <sip:52.9.254.127:5061;transport=tls;lr;r2=on;ftag=NN36BrBcQ48pK;did=8c6.4611>

        Record-Route: <sip:52.9.254.127;lr;r2=on;ftag=NN36BrBcQ48pK;did=8c6.4611>

        Call-ID: 62b89520-3410-11e9-90de-d1c5e59c76a4

        From: “android2181024115535” <sip:+654321@52.220.63.151>;tag=NN36BrBcQ48pK

        To: <sip:android1181024115518@52.9.254.127>

        CSeq: 725237 INVITE

        Content-Length: 0

    • Plivo callUUID (like Call-ID:352231d3-3ea9-40c8-8259-e4843f5b02fc)
    • Plivo SDK version
    • Plivo SDK methods call flows, eg:
      • endpoint.login();
      • outgoing.callH(num, headers);
    • Android device version (eg: android 8.0.1, android 9.0)
    • Android device model (eg: Samsung Galaxy A8 Plus)
  3. Best Practice: is to not use the deprecated methods, because these will be prone to crashes NoMethodError when removed in future.

  4. Best Practice: Use the deviceToken while logging in to get the incoming call as push notification, instead of using the background service to run forever in the background and observe for incoming calls.

  5. BestPractice: Always use endpoint.resetEndpoint() while logout, so that all the allocated memory resources will be deleted on the SDK.