Twilio Client for Android Quickstart Tutorial

Receiving Incoming Calls

Now, that we know how to initiate connections from your app, it's time for your app to start receiving incoming connections. By the end of this tutorial, you will be able to call in to your device using the Android Emulator (or vice-versa). Hold on tight...

To receive incoming connections, we'll do the following things:

  1. Give the app client a name and "register" it with Twilio.
  2. Add callbacks to notify your app of incoming connections via listener methods.

Change your code to pass this client name to your application server when it starts up. (In a real app, you would likely pass a username/password combination that the user would enter, but we'll omit this for simplicity.)

Device announces the important events to an object that implements the DeviceListener interface:

public void onStartListening(Device inDevice);

  • callback for when the device is successfully registered with Twilio

public void onStopListening(Device inDevice);

  • callback for when the device is no longer listening for incoming connections due to an explicit request to stop

public void onStopListening(Device inDevice, int inErrorCode, String inErrorMessage);

  • callback for when the device is no longer listening for incoming connections due to an error

We'll modify MonkeyPhone to implement these methods. First, we'll declare the interface and register the instance of MonkeyPhone to be the Device's listener when we create it, and then we'll define the three DeviceListener methods. We don't need to take any action here, but we'll log the various state transitions and any errors.

MonkeyPhone.java
public class MonkeyPhone implements Twilio.InitListener, DeviceListener
{
    /* ... other methods ... */
    private Device device;
    private Connection connection;

    /* Twilio.InitListener method */
    @Override
    public void onInitialized()
    {
        Log.d(TAG, "Twilio SDK is ready");

        try {
            String capabilityToken = HttpHelper.httpGet(""http://companyfoo.com/token?client=jenny");
            device = Twilio.createDevice(capabilityToken, this);
        } catch (Exception e) {
        Log.e(TAG, "Failed to obtain capability token: " + e.getLocalizedMessage());
    }

    /* ... other methods ... */

    @Override /* DeviceListener method */
    public void onStartListening(Device inDevice)
    {
        Log.i(TAG, "Device is now listening for incoming connections");
    }

    @Override /* DeviceListener method */
    public void onStopListening(Device inDevice)
    {
        Log.i(TAG, "Device is no longer listening for incoming connections");
    }

    @Override /* DeviceListener method */
    public void onStopListening(Device inDevice, int inErrorCode, String inErrorMessage)
    {
        Log.i(TAG, "Device is no longer listening for incoming connections due to error " +
        inErrorCode + ": " + inErrorMessage);
    }

}

Actually accepting the incoming connection is a little bit more work. You might want to glance at the section of the faq page that deals with incoming connections for some background on why this is the case. What it boils down to is:

  1. Create a PendingIntent that can activate HelloMonkeyActivity.
  2. Register this PendingIntent using Device.setIncomingIntent().
  3. Provide a hook in MonkeyPhone to handle the incoming call.
  4. Implement onNewIntent() in HelloMonkeyActivity to update the activity's Intent.
  5. Implement onResume() in HelloMonkeyActivity to check to see if we have an incoming connection, and handle it if so.

So for the first half:

MonkeyPhone.java
/* Twilio.InitListener method */
@Override
public void onInitialized()
{
    Log.d(TAG, "Twilio SDK is ready");

    try {
        String capabilityToken = HttpHelper.httpGet("http://companyfoo.com/token?client=jenny");
        device = Twilio.createDevice(capabilityToken, this);

        Intent intent = new Intent(context, HelloMonkeyActivity.class);
        PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
        device.setIncomingIntent(pendingIntent);
    } catch (Exception e) {
        Log.e(TAG, "Failed to obtain capability token: " + e.getLocalizedMessage());
    }
}

/* ... other methods ... */

public void handleIncomingConnection(Device inDevice, Connection inConnection)
{
    Log.i(TAG, "Device received incoming connection");
    if (connection != null)
        connection.disconnect();
    connection = inConnection;
    connection.accept();
}

And for the second half:

HelloMonkeyActivity.java
@Override
public void onNewIntent(Intent intent)
{
    super.onNewIntent(intent);
    setIntent(intent);
}

@Override
public void onResume()
{
    super.onResume();

    Intent intent = getIntent();
    Device device = intent.getParcelableExtra(Device.EXTRA_DEVICE);
    Connection connection = intent.getParcelableExtra(Device.EXTRA_CONNECTION);
    if (device != null && connection != null) {
        intent.removeExtra(Device.EXTRA_DEVICE);
        intent.removeExtra(Device.EXTRA_CONNECTION);
        phone.handleIncomingConnection(device, connection);
    }
}

If you compile and run the app, it's now ready to receive incoming calls. Now, we need to provision a Twilio phone number, (or use an existing one) and configure the Voice URL to point to your application server: http://{your app's url}/call.

Call your Twilio number and you should be connected to your device (or Android Emulator, whichever you're running), which will automatically answer the call. Start talkin'.

Ready to put it all together?


Next: Making Calls in/out of your App »

fonts-loaded