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:
First, start by modifying your auth.php file to accept a client name parameter ("clientName"):
<?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.)
-(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
-(void)device:(TCDevice*)device didStopListeningForIncomingConnections:(NSError*)error
-[TCDevice unlisten].-(void)device:(TCDevice*)device didReceiveIncomingConnection:(TCConnection*)connection
We'll modify the MonkeyPhone to implement these methods:
#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:
-(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.
-(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):
-(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.
<?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?