まずは、レイアウトの作成ですが、以下のウィジェットを配置します。
以下のような画面レイアウトを作りましょう(レイアウトの作成方法は割愛します)。
次にActivityを以下のように実装します。
package jp.classmethod.android.sample.twiliophone;
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.support.v4.content.Loader;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.EditText;
import com.twilio.client.Device;
import com.twilio.client.Twilio;
public class MainActivity extends FragmentActivity
implements OnClickListener, Twilio.InitListener {
private static final String TAG = HelloTwilioActivity.class.getSimpleName();
private Device mDevice;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_hello_twilio);
// Connectボタン
findViewById(R.id.connect).setOnClickListener(this);
findViewById(R.id.dial).setOnClickListener(this);
// Twilioクライアントを初期化する
Twilio.initialize(getApplicationContext(), this);
}
/*
* Twilio.InitListener method
*/
@Override
public void onInitialized() {
Log.d(TAG, "Twilioクライアントの初期化が完了しました");
}
@Override
public void onError(Exception e) {
Log.e(TAG, "エラーが発生しました:" + e.getLocalizedMessage());
}
@Override
public void onClick(View v) {
switch (view.getId()) {
case R.id.connect:
// TwiMLアプリサーバに接続する処理
break;
case R.id.dial:
// Twilioに接続する処理
break;
}
}
}
Twilio.initializeメソッドで初期化するところなどは前回と同様です。Twilio.InitListenerのonInitialized()メソッドが呼び出されたらTwilio Client SDKが使える状態になります。Twilioアプリケーションサーバに接続する処理を実行するためのButton電話をかける(Twilioに接続する)処理を実行するためのButtonにOnClickListenerをセットし、onClickメソッドでそれぞれの処理が実行できるような形まで実装します。
Deviceクラスを取得する非同期クラスを実装しましょう。AsyncTaskLoaderを継承した「DeviceLoader」クラスを新規作成し、以下のように実装します。
package jp.classmethod.android.sample.twiliophone;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.util.EntityUtils;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.support.v4.content.AsyncTaskLoader;
import android.util.Log;
import com.twilio.client.Device;
import com.twilio.client.Twilio;
public class DeviceLoader extends AsyncTaskLoader<Device> {
private static final String TAG = DeviceLoader.class.getSimpleName();
private String mClientName;
public DeviceLoader(Context context, String clientName) {
super(context);
mClientName = clientName;
}
@Override
public Device loadInBackground() {
try {
// ケイパビリティトークンを取得する
String url = "http://YOUR-APP-NAME.herokuapp.com/auth?name=" + mClientName;
HttpClient httpClient = new DefaultHttpClient();
HttpGet get = new HttpGet(url);
HttpResponse res = httpClient.execute(get);
HttpEntity entity = res.getEntity();
String token = EntityUtils.toString(entity);
Log.d(TAG, "トークン:" + token);
// Twilioにデバイスを登録する
Device device = Twilio.createDevice(token, null);
// 着信を受けるためのIntentを生成してセットする
Intent intent = new Intent(getContext(), IncomingActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(getContext(), 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
device.setIncomingIntent(pendingIntent);
return device;
} catch (Exception e) {
Log.e(TAG, "エラー:" + e.getLocalizedMessage());
}
return null;
}
}
Deviceクラスを取得するにはケイパビリティトークンが必要ですので、TwiMLアプリサーバで作成した認証用APIを呼び出し、取得します。このときリクエストパラメータにクライアント名を渡す必要がありますが、EditTextで入力されたクライアント名が受け取れるよう、コンストラクタ引数に追加しておきます。
Twilio.createDevice()メソッドを呼び出し、Deviceインスタンスを取得します。引数には認証用APIから取得したケイパビリティトークンを渡します。このDeviceインスタンスを使ってTwilioに接続(電話の発信)することになります。
DeviceインスタンスのsetIncomingIntent()メソッドを使って、着信があったときに呼び出されるPendingIntentをセットします。PendingIntentから呼び出されるActivityはIncomingActivityをセットしていますが、このクラスは後で実装します。
以上でDeviceLoaderクラスの実装が終わりました。
続いて、MainActivityの実装に戻り、接続用のボタンと発信用のボタンをタップしたときの処理を実装しましょう。
@Override
public void onClick(View view) {
switch (view.getId()) {
// Twilioに登録する
case R.id.connect:
// 入力されたクライアント名をパラメータに設定する
EditText clientName = (EditText) findViewById(R.id.client_name);
Bundle bundle = new Bundle();
bundle.putString("name", clientName.getText().toString());
// TwilioPhoneLoaderを呼び出す
getSupportLoaderManager().initLoader(TWILIO_PHONE_LOADER, bundle, this);
break;
}
// 電話をかける
case R.id.dial:
// 入力されたクライアント名をパラメータに設定する
EditText to = (EditText) findViewById(R.id.dial_name);
HashMap<String, String> params = new HashMap<String, String>();
params.put("name", to.getText().toString());
// 電話をかける
mDevice.connect(params, null);
break;
}
}
/*
* LoaderCallbacks method
*/
@Override
public Loader<Device> onCreateLoader(int id, Bundle bundle) {
DeviceLoader loader = new DeviceLoader(getApplicationContext(), bundle.getString("name"));
loader.forceLoad();
return loader;
}
@Override
public void onLoadFinished(Loader<Device> loader, Device device) {
Log.d(TAG, "デバイスの準備が完了しました");
mDevice = device;
getSupportLoaderManager().destroyLoader(TWILIO_PHONE_LOADER);
}
@Override
public void onLoaderReset(Loader<Device> loader) {
}
接続用ボタン(ここでは「connect」というIDのボタン)をタップしたときは、DeviceLoaderを呼び出すように実装します。DeviceLoaderのコールバックを受け取るためにLoaderCallbacksを実装し、onCreateLoader()でDeviceLoaderをインスタンス化し、非同期処理を実行します。onLoadFinished()でDeviceインスタンスを受け取り、メンバ変数として保持します。
発信用ボタン(ここでは「dial」というIDのボタン)をタップしたときは、Deviceインスタンスのconnect()メソッドを呼び出し、Twilioに接続します。ここでTwilioに接続することで、Twilio側ではTwiMLアプリのTwiMLを返すAPIを呼び出し、TwiMLに記載された命令を実行してくれます。第1引数に渡しているHashMapインスタンスはリクエストパラメータです。TwiMLを返すAPIを呼び出すときのリクエストパラメータとして使われます。
以上でTwilioに認証しDeviceインスタンスを受け取る処理、そしてDeviceインスタンスを使ってTwilioに接続する処理の実装が終わりました。
Copyright © ITmedia, Inc. All Rights Reserved.