monacaアプリからTwilio Clientを使って電話をかけてみる

:::note alert
2023年5月1日を持ちまして、株式会社KDDIウェブコミュニケーションズのTwilioリセール事業が終了したため、本記事に記載されている内容は正確ではないことを予めご了承ください。
:::

![2015-07-13 17.41.39.jpg](https://qiita-image-store.s3.amazonaws.com/0/86046/cc75f175-27ed-343b-767c-740af0174cdb.jpeg)

# 目的
[Twilio Client](https://jp.twilio.com/docs/client)のJavaScript版（twilio.js）を使うと、ブラウザから簡単に電話をかけることができます。しかしtwilio.jsはスマホのブラウザでは使えないため、通常はAndroidもしくはiOS用のTwilio Client SDKを用いて、アプリとして実装する必要があります。この方法では、OS毎にアプリを作らなくてはいけないので、それぞれのOSごとの開発スキルが必要になります。
最近では、PhoneGap/Cordovaに代表されるような、HTML5で記述したマルチプラットフォームアプリケーション開発も広く利用されるようになったので、今回はその中でも[monaca](http://monaca.mobi)を使ったTwilio Clientの実装をやってみます。
今回利用するmonacaは、PhoneGap/Cordovaをベースに作られているため、Cordovaプラグインを使うことでHTML5ベースで作成したアプリケーションからもネイティブな機能を利用することができます。
monacaには、すでに基本的なCordovaプラグインが用意されていますが、Twilio Clientのプラグインはmonacaの標準機能にはないため、今回はすでにネット上で公開されているTwilio ClientのCordovaプラグインをmonacaようにカスタマイズして実装したいと思います。
なお、今回はAndroid版のみで電話をかけるところだけを実装します。
# 準備するもの
* Twilioのアカウント
* Twilioからアクセスが可能なWebサーバー
* monacaのアカウント（Goldプラン以上でないとカスタムCordovaプラグインが使えません）
* Androidの開発環境
* PhoneGap/Cordovaの開発環境
* Git環境
* Android実機

### Twilioアカウント
Twilioアカウントを持っていない方は、[こちら](https://jp.twilio.com/try-twilio/kddi-web)からサインアップしてください。一定の利用分は無料で使えます。なお、トライアルアカウントで利用する場合は、発信先番号をあらかじめ検証しておく必要があります。詳しくは[こちら](https://twilioforkwc.zendesk.com/entries/23590763)を参照してください。
アカウントを取得したら、[こちら](https://jp.twilio.com/user/account/setting)からAccountSIDとAuthTokenを確認しておきます。
また、ダイヤル発信するためには050番号を1つ取得しておく必要があります。
### Twilioからアクセスが可能なWebサーバー
今回は、Twilio Clientが発信する際に利用するケイパビリティトークンを発行するためと、アプリから発信するためのTwiMLを取得するために利用します。どちらも同じサーバーで実装できますが、ネット上で公開されている必要があります。
### monacaのアカウント
今回作成するアプリでは、オリジナルCordovaプラグインを利用するため、monacaのプランがGOLD以上でないとできません。プランの詳細は[こちら](https://monaca.mobi/ja/pricing)を参照してください。
### PhoneGap/Cordovaの開発環境
今回はこの部分については深く説明はしませんので、以下のリンクを参照して各自でセットアップしてください。
[Cordovaを用いた開発環境を構築する](http://www.buildinsider.net/mobile/bookhtml5hybrid/0401)
### Androidの開発環境
今回は、Androidアプリを直接作成することはありませんが、プラグインの作成時にAndroidのサポートライブラリが必要となります。サポートライブラリは、[Android SDK Manager](http://developer.android.com/tools/help/sdk-manager.html)を使ってダウンロードすることができるので、最低限[Android SDK](http://developer.android.com/sdk/installing/index.html)は準備しておいてください。
### Git環境
Cordovaプラグインの準備や再構築などでGit環境を利用します。もしGitが使える環境になっていない場合は、以下のリンクを参照して準備をしておいてください。
[Gitインストールを１分で済ませる【Mac編】](http://www.tettori.net/post/1491/)
[WindowsにGit環境をインストールする](http://codezine.jp/article/detail/7077)
### Android実機
Cordova自体はAndroid2.xからでも利用可能ですが、とりあえず今回はAndroid4.x以上の実機でテストを行います。

# 手順
1. Twilio ClientのCordovaプラグインをダウンロードする。
2. Twilio SDK for Androidをダウンロードする。
3. Android Support Library V4をダウンロードする。
4. Twilio ClientのCordovaプラグインをカスタマイズする。
5. WebサーバーにトークンとTwiMLを書き出す準備をする。
6. monaca上でアプリを新規作成する。
7. 作成したプラグインをmonacaにインストールする。
8. アプリケーションをビルドして、実機でテストする。

## Twilio ClientのCordovaプラグインをダウンロードする
まずはローカルの作業フォルダに移動し、以下のコマンドを使って最新のTwilio Client Cordovaプラグインを取得しましょう。
`git clone https://github.com/jefflinwood/twilio_client_phonegap.git`
## Twilio SDK for Androidをダウンロードする
以下のサイトから、Android用のSDK（Zipバージョン）をダウンロードします。
[Android SDK](https://jp.twilio.com/docs/client/android)
ダウンロードしたZipファイルを解凍して、libsフォルダに入っているファイルをすべて、先ほどダウンロードしたCordovaプラグインのsrc/androidフォルダにコピーします。
コピー後のプラグインのフォルダは以下のような感じになっていると思います。
![スクリーンショット 2015-07-12 16.48.51.png](https://qiita-image-store.s3.amazonaws.com/0/86046/67a68877-7ac9-527a-948b-42d7e6d1f36d.png)
## Android Support Library V4をダウンロードする
今回のCordovaプラグインで利用するTwilio Clientは、Android Support Library V4を利用します。そのため、あらかじめAndroid Support Library V4をダウンロードしておく必要があります。
ダウンロードは、Android SDK Managerを用いて行います。
Eclipse+ADTの環境をインストールしている方は、EclipseのWindowメニューから「Android SDK Manager」を起動します。Android Studioをインストールしている方は、ToolsメニューのAndroidから、「Android SDK Manager」を選択します。
Android SDKのみをインストールしている方は、Windows環境ならば「SDK Manager.exe」を起動します。Mac環境ならば、`android sdk`コマンドでSDK Managerが起動します。
![スクリーンショット 2015-07-13 13.39.51.png](https://qiita-image-store.s3.amazonaws.com/0/86046/d7213786-5e20-9fae-8fe5-2fb7b2bd3c4e.png)
Android Support Library V4は、Extrasの中のAndroid Support Libraryをインストールすることでダウンロードされます（上図の赤枠参照）。なお、Android Support Libraryは21.0.3以上のバージョンが必要です。
ダウンロードが完了すると、Android SDKをインストールしたフォルダ（Android SDK Managerの上部にパスが表示されています）のextras/android/support/v4の中に、android-support-v4.jarというファイルができますので、そのファイルを先ほどダウンロードしたCordovaプラグインのsrc/androidの中にコピーします。
この時点で、Cordovaプラグインは以下のようになっているはずです。
![スクリーンショット 2015-07-13 13.54.41.png](https://qiita-image-store.s3.amazonaws.com/0/86046/3be321b8-889c-0790-230c-9e26229e6961.png)

## Twilio ClientのCordovaプラグインをカスタマイズする
今回はmonacaでCordovaプラグインを使うため、Twilio Clientが利用するいくつかのライブラリ（先ほどCordovaプラグインフォルダにコピーしておいたもの）をプラグインに包含させる必要があります。そのために、Cordovaプラグインのフォルダ内にあるplugin.xmlを編集します。
1. assetタグをコメントアウトし、代わりにjs-moduleタグを以下のように記述します。
![スクリーンショット 2015-07-12 16.52.38.png](https://qiita-image-store.s3.amazonaws.com/0/86046/1c1c52eb-70f9-19b2-2bcd-ccf5a7ee5ef0.png)
2. android用のplatformタグ内に、以下のようにsource-fileタグを6つ記述します。
![スクリーンショット 2015-07-13 13.59.42.png](https://qiita-image-store.s3.amazonaws.com/0/86046/eb02ab08-17f2-0745-5893-d7618795c2db.png)

## WebサーバーにトークンとTwiMLを書き出す準備をする
Twilio Clientで電話の発信を行うためには、次の2つのステップが必要です。
1. ダイヤルする相手を指定する[TwiML](https://jp.twilio.com/docs/api/twiml)を準備する。
2. 準備したTwiMLを使って発信を行うための[ケイパビリティトークン](https://jp.twilio.com/docs/client/capability-tokens)を生成する。
### TwiMLの準備
ダイヤルするためのTwiMLを生成します。今回はあらかじめ発信先を決め打ちしますが、実際は動的にダイヤル先を変更するようにしても構いません。
Twilioからダイヤルするには、[Dial動詞](https://jp.twilio.com/docs/api/twiml/dial)を使います。
今回は最低限のTwiMLにしますので、例えば以下のようなXMLを返すようにWebサーバーに設定を行っておきます。

```xml:Dial動詞
<?xml version="1.0" encoding="UTF-8"?>
<Response>
    <Dial callerId="Twilioで取得した050番号">発信先番号</Dial>
</Response>
```
TwiMLを作成する時の注意点として、callerIdにはTwilioで取得した050番号を+81から始まる国際番号形式（たとえば、050-1234-5678の場合は、+815012345678）で指定することと、発信先番号も同じく+81から始まる国際番号形式で指定することです。
### TwiMLアプリケーションの設定
次に、このTwiMLを取得するURLを使って、Twilio上でTwiMLアプリケーションを作成します。
Twilioにログインし、ツールメニューからTWIML APPSを選択します。
![スクリーンショット 2015-07-12 21.04.23.png](https://qiita-image-store.s3.amazonaws.com/0/86046/742526db-692e-ec5c-6f58-558f14be74a7.png)

右側にある「TwiML Appを作成する」ボタンを押します。

![スクリーンショット 2015-07-12 21.06.49.png](https://qiita-image-store.s3.amazonaws.com/0/86046/3bc33c95-ca03-eadd-7817-35c68eaee78c.png)
プロパティ欄のフレンドリーネームには、なにか適当な名前を入れます。
さらに、音声通話のRequest URL欄に、先ほどTwiMLを取得するためのURLを記入します。この時、右側のトグルボタンでGETかPOSTを選択します。どちらにするかはTwiMLをダウンロードさせるWebサーバーの実装に依存します。
最後に「保存」ボタンを押します。

![スクリーンショット 2015-07-12 21.11.52.png](https://qiita-image-store.s3.amazonaws.com/0/86046/5e122e9e-f92e-682f-1e65-0b5629606e9b.png)

保存が成功するとTwiML APP Sidが付与されるので、APから始まるSidを記録しておきます（上図で赤丸で囲った部分）。

### ケイパビリティトークンの生成
ケイパビリティトークンとは、Twilio Clientが発着信をするときに利用するトークンで、Twilioアカウントを使って動的に生成することができます。ここに関しては、サーバーサイドの言語によって生成方法が異なりますので、以下のURLを参考にしてください。
[Twilioクライアントケイパビリティトークン](https://jp.twilio.com/docs/client/capability-tokens)
今回はアプリから発信をするので、Outgoingを許可したトークンを作成する必要があります。
例えば、Node.jsで作成する場合、以下の様なコードになります。

```Node.js
var twilio = require('twilio');
var capability = new twilio.Capability(ACCOUNT_SID, AUTH_TOKEN);

capability.allowClientOutgoing('TwiML APP SID');
var token = capability.generate();
```

「TwiML APP SID」の部分には先ほどTwilio上で作成したTwiMLのSIDを入れます。また、「ACCOUNT_SID」と「AUTH_TOKEN」はTwilioアカウントから取得したものを利用します。

## monaca上でアプリを新規作成する
monacaにログインし、新しいプロジェクトを作成します。今回はmonaca.io（クラウド）を使い、ひな形として「最小限のテンプレート」を選択します。
![スクリーンショット 2015-07-12 21.59.12.png](https://qiita-image-store.s3.amazonaws.com/0/86046/e3444316-6747-f007-afc8-8f4b566cb026.png)
プロジェクト名と説明を適当に入れて、プロジェクトを作成します。

### index.htmlの書き換え
以下のコードで、index.htmlを書き換えてください。

```index.html
<!DOCTYPE HTML>
<html>
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
    <script src="components/loader.js"></script>
    <script src="components/phoneApp.js"></script>
    <link rel="stylesheet" href="components/loader.css">
    <link rel="stylesheet" href="css/style.css">
    <script>
    </script>
</head>
<body>
    <div data-role="page" data-control-title="Home" id="homePage">
        <div data-theme="a" data-role="header">
            <h3>monacaでTwilio Client</h3>
        </div>
        <div data-role="content">
            <h3>Status</h3>
            <div id="statusMessage" data-controltype="textblock">
                <p><b>Status message...</b></p>
            </div>
            <hr style="height:3px; background-color:#ccc; border:0; margin-top:12px; margin-bottom:12px;">
            <a id="dialButton" data-role="button" data-theme="a" href="#">発信する</a>
            <a id="hangupButton" data-role="button" data-theme="a" href="#" style="display:none;">切断する</a>
        </div>
    </div>
</body>
</html>
```

### phoneApp.jsの作成
monacaプロジェクトのwwwフォルダ内に、phoneApp.jsというファイル作成し、以下のコードを貼り付けます。なお、コードの最後の方に、ケイパビリティトークンをダウンロードするURLを記載する必要がありますので、そこは皆さんの環境に置き換えてください。

```phoneApp.js
$(document).ready(function(){

    var tokenRequest    = new XMLHttpRequest();
    tokenRequest.onload = function() {

        Twilio.Device.setup(tokenRequest.responseText);
        var connection=null;

        $("#dialButton").click(function() {
            params = { "tocall" : ''};
            connection = Twilio.Device.connect(params);
        });

        $("#hangupButton").click(function() {
            Twilio.Device.disconnectAll();
        });

        Twilio.Device.ready(function (device) {
            $('#statusMessage').text('Ready to start call');
        });

        Twilio.Device.incoming(function (conn) {
            if (confirm('Accept incoming call from ' + conn.parameters.From + '?')){
                connection=conn;
                conn.accept();
            }
        });

        Twilio.Device.offline(function (device) {
            //$('#statusMessage').text('Offline');
        });

        Twilio.Device.error(function (error) {
            $('#statusMessage').text(error);
        });

        Twilio.Device.connect(function (conn) {
            $('#statusMessage').text("Successfully established call");
            $('#dialButton').toggle();
            $('#hangupButton').toggle();
        });

        Twilio.Device.disconnect(function (conn) {
            $('#statusMessage').text("Call ended");
            $('#dialButton').toggle();
            $('#hangupButton').toggle();
        });
    };

    tokenRequest.open('GET', 'ここにTokenをダウンロードするURL');
    tokenRequest.send();

});
```

### JQueryの設定
このアプリでは、jQuery Mobileを利用しているため、monacaのビルド設定のJS/CSSコンポーネントの追加と削除で、jQuery Mobile（自動的にjQueryもインストールされます）を追加しておきます。
![スクリーンショット 2015-07-13 18.11.24.png](https://qiita-image-store.s3.amazonaws.com/0/86046/9dfde889-2dd9-ff2b-f39e-e2f3b075eb12.png)


## 作成したプラグインをmonacaにインストールする
Cordovaプラグインをmonacaにインストールします。
先ほどカスタマイズをしたCordovaプラグインの作業フォルダ（twilio_client_phonegap）に移動します。

まずは、変更した内容をコミットします。
`git add .`
`git commit -m 'Twilio Client Plugin commit'`

zipアーカイブを作成します。
`git archive --format=zip HEAD -o ../twilio_client_phonegap.zip`
これで、作業フォルダの上位フォルダにtwilio_client_phonegap.zipというプラグインが完成します。

次に、このプラグインをmonacaに読み込みます。
monacaの設定メニューから「Cordovaプラグインの管理...」を選びます。
Cordovaのバージョンを4.1.0に変更します。
さらに、「Cordovaプラグインのインポート」ボタンを押します。
先ほど作成したZipファイルを選択して、プラグインを追加します。
![スクリーンショット 2015-07-13 18.20.55.png](https://qiita-image-store.s3.amazonaws.com/0/86046/3f4fc58a-267a-f834-5fe8-55d2f0398655.png)

追加が無事に終了すると、monacaのプロジェクトツリー画面にpluginsフォルダができていることが確認できます。また、その中のsrc/androidには、先ほどプラグインをカスタマイズした際にコピーしておいたjarファイルなどが含まれていることも確認できます。
![スクリーンショット 2015-07-13 18.22.10.png](https://qiita-image-store.s3.amazonaws.com/0/86046/f953e184-fcba-7859-c2e8-2e7c4f2fbf65.png)

## アプリケーションをビルドして、実機でテストする
最後に実機を使ってテストしてみましょう。
まずはアプリケーションをビルドしますので、monacaのビルドメニューから「Androidアプリのビルド」を選択します。
ビルドの種類を選択しますが、今回はオリジナルのCordovaプラグインを使っているため「デバッガーのビルド」を選択します。
![スクリーンショット 2015-07-13 18.26.19.png](https://qiita-image-store.s3.amazonaws.com/0/86046/a1e0b1e8-6ea3-79a9-313d-f438b0bb8830.png)
「次へ」を選択してしばらく待つと、出来上がったデバッガーアプリをダウンロードする画面が表示されるので、いずれかの方法でアプリを実機にダウンロードしてテストをしてみてください。

#まとめ
今回は、Twilio ClientのCordovaプラグインをカスタマイズして、monacaで実行してみました。
実際に使ってみるとわかりますが、Cordovaプラグインのイベントハンドリングがおかしいのか、一度アプリを終了してから再度起動すると、発信したあとに切断ボタンが表示されなくなります。このあたりは、今後改善されていくと思いますが、ひとまずはmonacaからもTwilioが使えるというサンプルになれば幸いです。

参考サイト
* [twilio_client_phonegap(GitHub)](https://github.com/jefflinwood/twilio_client_phonegap)
* [Setting up Mobile Apps with Twilio and PhoneGap(PDF)](http://www.jefflinwood.com/wp-content/uploads/2015/05/InstallingTwilioPhoneGapPluginV1.pdf)