Get Started

Twilio Client for iOS Quickstart Tutorial

Receiving Incoming Connections

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 iOS Simulator (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 delegate methods.
  3. Write some TwiML to <Dial> your named <Client>.

First, start by modifying your auth.php file to accept a client name parameter ("clientName"):

auth.php
<?php

include 'Services/Twilio/Capability.php';

// Find your credentials at twilio.com/user/account
$accountSid = "ACXXXXXXXXXXXXXXXX";
$authToken = "abc123abcdef"; 
$appSid = "APXXXXXXXXXXXXXXXXXXXXXXXXX"; // Your application sid

$clientName = $_REQUEST["clientName"]; // The client name for incoming connections
$capability = new Services_Twilio_Capability($accountSid, $authToken);

// This allows incoming connections as $clientName:
$capability->allowClientIncoming($clientName);

// This allows outgoing connections to $appSid with the 
// "From" parameter being $clientName 
$capability->allowClientOutgoing($appSid, array(), $clientName);

// This returns a token to use with Twilio based on 
// the account and capabilities defined above 
$token = $capability->generateToken();
echo $token;
?>

And change MonkeyPhone.m to pass this client name to the PHP file when it starts up. (In a real app, you would pass a username password combination from UITextFields, but we'll omit this for simplicity.)

MonkeyPhone.m
-(id)init
{
    if ( self = [super init] )
    {
        NSURL* url = [NSURL URLWithString:@"http://companyfoo.com/auth.php?clientName=jenny"];

// … code omitted
    }
    return self;
}

TCDevice announces the important events to an object that implements the TCDeviceDelegate protocol:

-(void)deviceDidStartListeningForIncomingConnections:(TCDevice*)device

  • callback for when the device is successfully registered with Twilio.

-(void)device:(TCDevice*)device didStopListeningForIncomingConnections:(NSError*)error

  • callback for when the device is no longer listening for incoming connections due to error or a call to -[TCDevice unlisten].

-(void)device:(TCDevice*)device didReceiveIncomingConnection:(TCConnection*)connection

  • callback for when a client receives an incoming connection

We'll modify the MonkeyPhone to implement these methods:

MonkeyPhone.h
#import <Foundation/Foundation.h>
#import "TCDevice.h"
#import "TCConnection.h"
#import "TCDeviceDelegate.h"

@interface MonkeyPhone : NSObject<TCDeviceDelegate>
{
@private
    TCDevice* _device;
    TCConnection* _connection;
}

-(void)connect:(NSString*)phoneNumber;
-(void)disconnect;

-(void)deviceDidStartListeningForIncomingConnections:(TCDevice*)device;
-(void)device:(TCDevice*)device didStopListeningForIncomingConnections:(NSError*)error;
-(void)device:(TCDevice*)device didReceiveIncomingConnection:(TCConnection*)connection;

@end

Next register the instance of MonkeyPhone to be the TCDevice's delegate during -(id)init:

MonkeyPhone.m
-(id)init
{

// … code omitted
            
    if (httpResponse.statusCode == 200)
    {
        NSString* capabilityToken = [[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding] autorelease];
        _device = [[TCDevice alloc] initWithCapabilityToken:capabilityToken delegate:self];
    }

// … code omitted

return self;
}

Finally, implement -(void)device:(TCDevice*)device didReceiveIncomingConnection:(TCConnection*)connection and have it accept the incoming connection when we get the callback. Note that we go ahead and disconnect any existing connection first.

MonkeyPhone.m
-(void)device:(TCDevice*)device didReceiveIncomingConnection:(TCConnection*)connection
{
    if ( _connection )
    {
        [self disconnect];
    }
    _connection = [connection retain];
    [_connection accept];
}

For completeness, implement the remaining two delegate methods to print out the various state transitions and any errors (note that device:didIncomingListenerBecomeOffline: is a @required method for the delegate):

MonkeyPhone.m
-(void)deviceDidStartListeningForIncomingConnections:(TCDevice*)device
{
NSLog(@"Device is now listening for incoming connections");
}

-(void)device:(TCDevice*)device didStopListeningForIncomingConnections:(NSError*)error
{
    if ( !error )
    {
        NSLog(@"Device is no longer listening for incoming connections");
    }
    else
    {
    NSLog(@"Device no longer listening for incoming connections due to error: %@", [error localizedDescription]);
}
}

If you compile and run the app, it's now ready to receive incoming calls! Now we need to provision a Twilio phone number, and configure the Voice URL to point to a simple TwiML file which we will create and name: call-jenny.xml.

call-jenny.xml
<?xml version="1.0" encoding="utf-8" ?>
<Response>
    <Dial>
        <Client>jenny</Client>
    </Dial>
</Response>

If you put this file at the root of your companyfoo.com web site, you can change your Voice URL for your Twilio App to be http://companyfoo.com/call-jenny.xml.

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

Ready to put it all together?


Next: Making Calls In and Out of Your App »