Next, open the "HelloMonkey" project in Eclipse (File -> Import -> General -> Existing Projects into Workspace).
The HelloMonkey app is very simple, presenting "Dial" and "Hangup" buttons, and
a text field for who the app should call. The user interface elements have
already been wired up to the HelloMonkeyActivity class but don't actually do
anything (yet).
First let's run through the code and figure out what everything does.
The MonkeyPhone class is going to be our central coordinator object that
talks to the Twilio Client APIs, and this is where the bulk of the
functionality will live.
The MonkeyPhoneActivity class is the Android application's main Activity
that will instantiate MonkeyPhone and respond to user input events.
The HttpHelper class is a simple wrapper around Apache HttpClient (included
with the Android SDK) that'll make it easier to fetch HTTP URLs. In your real
application, you'll want to do something similar, but handle downloading
asynchronously, in another thread, to avoid blocking the main UI thread.
Before doing anything, you must first initialize the Twilio Client SDK. This
happens asynchronously, and you'll get notified via a Listener when the SDK
is up and running. The call to Twilio.initialize() in the constructor of
MonkeyPhone takes care of this. You'll get notified of success or failure
via the Twilio.InitListener interface, which the MonkeyPhone class also
implements.
In the onInitialized() method, we create an instance of the
com.twilio.client.Device class using the factory method
Twilio.createDevice(). An instance of Device represents a soft "device"
that knows how to speak to Twilio services. You'll use a Device to
initiate outgoing calls and listen for incoming calls. Here's what the base
MonkeyPhone class looks like:
import com.twilio.client.Device;
import com.twilio.client.Twilio;
public class MonkeyPhone implements Twilio.InitListener
{
public MonkeyPhone(Context context)
{
Twilio.initialize(context, this /* Twilio.InitListener */);
}
@Override /* Twilio.InitListener method */
public void onInitialized()
{
Log.d(TAG, "Twilio SDK is ready");
try {
String capabilityToken = HttpHelper.httpGet("http://companyfoo.com/auth.php");
device = Twilio.createDevice(capabilityToken, null /* DeviceListener */);
} catch (Exception e) {
Log.e(TAG, "Failed to obtain capability token: " + e.getLocalizedMessage());
}
}
@Override /* Twilio.InitListener method */
public void onError(Exception e)
{
Log.e(TAG, "Twilio SDK couldn't start: " + e.getLocalizedMessage());
}
@Override
protected void finalize()
{
if (device != null)
device.release();
}
}
Note that the URL we're fetching is on a server called "companyfoo.com".
You'll want to change that URL to point to where you stored auth.php on
your server.
For the security of your Twilio Account, you should never store a capability token string or your Twilio AuthToken as a part of the app you distribute on the Android Market.
The HelloMonkeyActivity class is pretty simple at this point: all it does
is set up the UI view, fetch some widget references, and instantiate an
instance of MonkeyPhone:
public class HelloMonkeyActivity extends Activity implements View.OnClickListener
{
private MonkeyPhone phone;
private EditText numberField;
@Override
public void onCreate(Bundle bundle)
{
super.onCreate(bundle);
setContentView(R.layout.main);
phone = new MonkeyPhone(getApplicationContext());
ImageButton dialButton = (ImageButton)findViewById(R.id.dialButton);
dialButton.setOnClickListener(this);
ImageButton hangupButton = (ImageButton)findViewById(R.id.hangupButton);
hangupButton.setOnClickListener(this);
numberField = (EditText)findViewById(R.id.numberField);
}
@Override
public void onClick(View view)
{
if (view.getId() == R.id.dialButton)
phone.connect();
}
}
Important note: we recommend that you pass Application context (and not
Activity context) to Twilio SDK functions. The SDK internals that need
a reference to a Context instance will likely live beyond the lifecycle of
any individual Activity. See the article
Avoiding Memory Leaks
for more information on why this matters.
There's one more thing that we need to do before it will run. Due to how
Android handles background apps, the SDK uses an Android Service behind
the scenes. This service needs to be declared in your
AndroidManifest.xml file inside the <application> tag like so:
<!-- ... other XML stuff... -->
<application
android:icon="@drawable/ic_launcher"
android:label="@string/app_name">
<activity
android:label="@string/app_name"
android:name="com.twilio.example.hellomonkey.HelloMonkeyActivity"
android:screenOrientation="portrait">
<intent-filter >
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service
android:name="com.twilio.client.TwilioClientService"
android:exported="false" />
</application>
<!-- ... other XML stuff... -->
Take special note of the android:exported="false" attribute. This is
necessary to avoid interfering with other applications built using the
Twilio Client SDK. The SDK will refuse to initialize if it detects
that this attribute is missing.
While you have the manifest open, take a look at the <uses-permission>
tags. These are all required when using the Twilio Client SDK, so don't
forget to add them to your own applications.
If you compile and run this code, you should see the following:

Now we've got an app that can create outgoing connections and receive incoming connections.
For the time being we'll focus on making an outgoing connection. The connection will call a Twilio sample application that responds with a friendly greeting.
In this section of the Quickstart, we'll be:
MonkeyPhone able to call out, andLet's add a method to MonkeyPhone to initiate a connection. We'll keep track
of the connection we've created as a member variable of type Connection. To
make a connection, we call the Device.connect() method. Just pass in null
parameters and a null listener for the moment; we'll do more with these
arguments later.
import com.twilio.client.Connection;
import com.twilio.client.Device;
import com.twilio.client.Twilio;
public class MonkeyPhone implements Twilio.InitListener
{
private Device device;
private Connection connection;
/* ... other methods ... */
public void connect()
{
connection = device.connect(null /* parameters */, null /* ConnectionListener */);
if (connection == null)
Log.w(TAG, "Failed to create new connection");
}
@Override
protected void finalize()
{
if (connection != null)
connection.disconnect();
if (device != null)
device.release();
}
}
Note that we do a null check on the returned Connection object after
calling connect(). There are some cases where creating a new connection
can fail.
If you take a look at HelloMonkeyActivity, you'll notice it has a member
variable called phone of type MonkeyPhone. When the activity is launched,
it initializes a MonkeyPhone object and sets it as the value of the phone
member.
There's also an empty onClick() handler for the dial and hangup buttons.
When the dial button is pressed, we (obviously) want to dial out. Let's use
the MonkeyPhone instance to do that:
HelloMonkeyActivity.java:
public class HelloMonkeyActivity extends Activity implements View.OnClickListener
{
private MonkeyPhone phone;
/* ... other methods ... */
@Override
public void onClick(View view)
{
if (view.getId() == R.id.dialButton)
phone.connect();
}
}
If you now compile the app and run it, you should be able to click the "Dial" button and hear the greeting. Awesome!
Wouldn't it be nice if you could also hang up on a connection if you don't want to hear the whole thing? Let's go do that now.