ボクココ

少人数でのサービス開発運営に関するテックブログ

Twilio Voice JavaScript 2.0 以降での複数着信の受け取り方

ども、@kimihom です。

f:id:cevid_cpp:20220226191000j:plain

Twilio コミュニティの中で、「1本目の着信が来た後、続けて2本目の着信が来たときに、1本目の着信を出られるようにしたい」というケースで質問をいただいた。まさにそのケースの対応を自分も実装したので、コードを含めて説明していければと思う。

Twilio Voice JavaScript SDK の変更

まず、v1 から v2 への 大枠の変更は以下の記事にまとめてある。

www.bokukoko.info

"Device 実装の変更" がさっと書いてあるが、これが実装する上では最も大きな影響を与えている。

個人的には以下の違いが最も大きいと感じている。

  • v1: 着信が来た順で最新の着信のみを受け取れていた
  • v2: 着信が複数来たときに、そのどの着信を出るかを選択できるようになった

この影響もあり、どうやら執筆時点で Twilio Voice JavaScript SDK のサンプルアプリでは、最もシンプルに着信を表示するだけの実装になっているようだ。

ではどう実装していくか、詳細をコードを含めて説明していく。

初期化コード

まず答えから書くと、"着信を受けているCallをJavaScript内で管理する" ということになる。

具体的なサンプルコードを書いてみる。

let token = getToken(); // access token
let activeCall = null; // 現在アクティブなCall
let activeIncomingCalls = {} // 現在着信を受けているCall

function initTwilioClient(token) {
  const twilio = new Twilio.Device(token);

  twilio.on('registering', device => {
    console.log("Device登録中");
  });
  twilio.on('registered', device => {
    console.log("Device登録完了");
  });
  twilio.on('unregistered', call => {
    console.log("Device登録解除");
  });
  twilio.on('incoming', handleIncomingCall);
  twilio.on('error', handleErrorCall);
  twilio.register();
};

もちろん、各イベントの中で UI の更新などが必要になってくる。ただし、上記コードで今回の "複数着信の受け取り方" を示す上では十分である。

では肝心の handleIncomingCall をどうするか。以下となる。

function handleIncomingCall(call) {
  activeIncomingCalls[call.parameters.CallSid] = call;

  call.on("accept", handleAcceptedCall);
  call.on("disconnect", handleDisconnectedCall);
  call.on("cancel", () => {
    handleCanceledCall(call);
  });
  call.on("reject", () => {
    handleRejectedCall(call);
  });
  call.on('error', handleErrorCall);

  if (activeCall) return;
  activeCall = call;
  showIncoming(); // 着信中のUIをactiveCallを使って表示
}

上記コードで、今着信が来ている activeIncomingCalls に1件目、2件目の着信が連続できてもそれぞれがハッシュとして保存できるようになった。そして、それぞれのイベントを事前に定義している。

この状態で1件目の着信で activeCall 登録される。2件目の着信は、既に activeCall が存在するので、UI を変えないような実装にしている。

※このようにHashで管理しているので、現在着信が来ている通話を一覧表示して、好きな着信を選択して出る UI を実現することも可能!

ただし、これで完成ではない。このままだと、着信通話が相手がそのまま電話を切ったり、こちらで拒否したりする場合に着信表示が出続ける問題が発生してしまう。activeIncomingCalls を適切に管理する必要がある。

function removeActiveIncomingCall(call) {
  delete activeIncomingCalls[call.parameters.CallSid];
}
function handleDisconnectedCall(call) {
  removeActiveIncomingCall(call);
  tryShowIncomingCall();
  // ...
}
function handleCanceledCall(call) {
  removeActiveIncomingCall(call);
  // ...
}
function handleRejectedCall(call) {
  removeActiveIncomingCall(call);
  // ...
}

それぞれの終了イベント時に、ハッシュの中で対象の通話を削除するようにしよう。これで、新しい着信のみが表示されるようになる。

tryShowIncomingCall というメソッドがちょろっとある。これは任意ではあるけど、一件目の着信が来て、通話が終わった後に既に他の着信が来てたときの対応も可能となる。

  function tryShowIncomingCall() {
    const obj = Object.keys(activeIncomingCalls);
    if (obj.length == 0) return; // もし他の着信がなければ終了

    activeCall = activeIncomingCalls[obj[0]]; // Hash最初のを表示
    showIncoming(); // 着信中のUIをactiveCallを使って表示
  }

終わりに

今回は Twilio Voice JavaScript 2.0 以降での複数着信の受け取り方 について、実際のコードを含めて解説した。

いろいろなイベントがあって、それらを一つ一つテストするのは大変だけど、v2 からはより柔軟な着信管理ができるようになっている。

この記事が参考になれば幸いだ。