https://d226lax1qjow5r.cloudfront.net/blog/blogposts/make-and-receive-phone-calls-in-android-apps-with-nexmo-in-app-voice-and-firebase-dr/Nexmo-FIrebase-Android-App-Voice.png

Firebaseを使ってAndroidアプリで電話をかけたり受けたりする

最終更新日 May 20, 2021

所要時間:2 分

Nexmo In-App Voiceを使えばNexmo Stitch Android SDKとWebRTC技術を使って、簡単に電話をかけたり受けたりすることができます。このチュートリアルでは、発信と着信が可能なシンプルなAndroidアプリの作り方をご紹介します。この機能は、顧客がアプリから離れることなく、カスタマーサービスに電話をかけたり受けたりしたい場合に使用できます。

アプリを立ち上げて実行するには、次のようにします。 Firebase Functionsをホストするために NCCOをホストし JWTを返します。

このブログ記事に従うには、JavaScriptの知識があり、Kotlinを使ってAndroidアプリを構築できる必要がある。

始める前に

始める前に必要なものがいくつかある。

Vonage API Account

To complete this tutorial, you will need a Vonage API account. If you don’t have one already, you can sign up today and start building with free credit. Once you have an account, you can find your API Key and API Secret at the top of the Vonage API Dashboard.

Firebase Functionを設定します。

まず、Firebaseファンクションプロジェクト用に新しいディレクトリを作成し、設定ファイルを格納します。

mkdir firebase-functions-nexmo-in-app-calling cd firebase-functions-nexmo-in-app-calling

新しいディレクトリが作成されたので、Firebase が提供する のセットアップ手順に従ってで提供されている手順に従い、新しいプロジェクトを作成します。

npm install -g firebase-tools firebase login firebase init functions

このプロジェクトでは、TypeScriptではなくJavaScriptを使うことにした。

私のように、コマンドラインからfirebaseのファンクションプロジェクトを作成できなかった場合は、以下のサイトを参照してください。 Firebaseコンソールにアクセスして新しいプロジェクトを作成し、コマンドラインから firebase use --addをコマンドラインから実行してください。

Firebase関数を編集する

Firebase Functions で使用するメソッドの最終バージョンは、Gitub のこのデモの にあります。要するに、3つのエンドポイントが必要です:

  1. NCCOをホストするアンサーURL

  2. Voice APIからイベントを取得するためのイベントURL。

  3. ユーザーがログインするためのJWTを返すURL

Firebaseの関数を編集するには、新しい関数の index.jsファイルを編集する必要があります。 functions/ディレクトリにあるファイルを編集する必要があります。 firebase init functions

まず、アンサーメソッドを見てみよう。

exports.answer = functions.https.onRequest((request, response) => {
  //use the `to` query parameter that Nexmo gives us to make a call.
  //if `to` is null, then we are receiving a call.
  var to = request.query.to
  var from = request.query.from

  var ncco = [];

  if (to) {
    ncco.push(
      {
        action: "talk",
        text: "Thank you for calling, you are now being connected."
      },
      {
        "action": "connect",
        "from": functions.config().nexmo.from_number,
        "endpoint": [
          {
            "type": "phone",
            "number": `${to}`
          }
        ]
      }
    )
  } else {
    ncco.push(
      {
        action: "talk",
        text: "You are being connected to the Customer."
      },
      {
        "action": "connect",
        "from": from,
        "endpoint": [
          {
            "type": "app",
            "user": "Customer"
          }
        ]
  
      })
  }
  response.json(ncco);
});

NexmoのVoice APIは1つのアプリケーションにつき1つの応答URLを使用するため、queryパラメータがnullの場合、着信コールを受け入れるためのNCCOを動的に表示することができます。 toを動的に表示できます。もし toクエリパラメータが でない場合でない場合は、発信のNCCOを表示します。

ユーザーにJWTを提供するためのエンドポイントは、非常に簡単です。私たちは Nexmo Nodeライブラリを使ってJWTを生成します。ライブラリを使用するには、パッケージをインストールする必要があります。

#package.jsonとindex.jsファイルがある/functionsディレクトリにいることを確認する npm install nexmo

ライブラリのインストール後、すべてが正しく動作していることを確認するには package.jsonファイルを検査することで、すべてが正しく動作していることを確認できる。以下のようになるはずだ:

"dependencies": {
    "firebase-admin": "~5.12.1",
    "firebase-functions": "^1.0.3",
    "nexmo": "^2.3.2"
  }

Nexmo Nodeライブラリがインストールされたら、jwtエンドポイントで次のように使用して、有効な user_jwt.

exports.jwt = functions.https.onRequest((request, response) => {
    response.json({
      user_jwt: Nexmo.generateJwt("private.key", {
        application_id: functions.config().nexmo.application_id,
        sub: "Customer",
        exp: new Date().getTime() + 86400,
        acl: adminAcl
      })
    });
});

Firebaseの関数ができたので、次はVonageのアプリケーションを作ってみよう。

Firebase関数をデプロイする

Firebase Functions が書き終わったので、Firebase プロジェクトをデプロイします。Functions をデプロイすると、Firebase がアンサーとイベントのエンドポイントの URL を教えてくれます。これらの URL を使って Vonage アプリケーションを作成します。

#このチュートリアルの最初に作成したfirebase-functions-nexmo-in-app-calling/ディレクトリにいることを確認する firebase deploy --only functions

関数[answer]:作成操作に成功しました。関数のURL(answer):https://your-project-name.cloudfunctions.net/answer ✔ functions[event]:作成操作に成功しました。関数URL(イベント):https://your-project-name.cloudfunctions.net/event ✔ functions[jwt]:functions[jwt]:作成に成功しました。関数URL(jwt):https://your-project-name.cloudfunctions.net/jwt

Vonageアプリケーションを設定します。

アプリケーションを作成するには、まずこのコマンドでVonage CLIをグローバルにインストールします:

npm install @vonage/cli -g

次に、Vonage API キーとシークレットを使って CLI を設定します。この情報は 開発者ダッシュボード.

vonage config:set --apiKey=VONAGE_API_KEY --apiSecret=VONAGE_API_SECRET

では、前のセクションでFirebaseが提供してくれたアンサーとイベントURLを使います。

# Ensure you're in the firebase-functions-nexmo-in-app-calling/ directory we created at the beginning of this tutorial
vonage apps:create 
✔ Application Name … ruling_narwhal
✔ Select App Capabilities › Voice
✔ Create voice webhooks? … yes
✔ Answer Webhook - URL … https://your-project-name.cloudfunctions.net/answer
✔ Answer Webhook - Method › POST
✔ Event Webhook - URL … https://your-project-name.cloudfunctions.net/event
✔ Event Webhook - Method › POST
✔ Allow use of data for AI training? Read data collection disclosure - https://help.nexmo.com/hc/en-us/articles/4401914566036 … no
Creating Application... done
Application Name: ruling_narwhal

秘密鍵は作成したfunctionsディレクトリに保存されます。鍵はプロジェクトと同じ名前になります。

アプリケーションIDを記録し、秘密鍵を "functions "ディレクトリに保存する。その際 your_private_key_name.key.nexmo-appファイルを .gitignore.

ベストプラクティスに従って、Firebase CLI経由でFirebaseの環境変数を保存します。Firebaseのドキュメントに に環境設定の概要があります。

ここで、firebase CLIを使って、VonageのアプリケーションIDをfirebase configに保存する必要がある。

firebase functions:config:set nexmo.application_id="aaaaaa-bbbb-cccc-dddd-0123456789ab"

注意:Firebaseは設定変数のキーを小文字にすることを要求しているので、変数名にはスネークケースを使用する。

お望みであれば、Vonage アプリケーションの .nexmo-appファイルにある秘密鍵文字列をアップロードすることもできます。 your_private_key_name.keyとしてアップロードすることもできます。

電話番号とユーザーをアプリケーションにリンク

さて、関数が書けたので、ユーザーがその番号から発信し、誰かがその番号にダイヤルするたびにAndroidアプリで着信を受け取れるように、番号を購入する必要があります。また、その番号をVonageアプリにリンクさせる必要があります。

Vonageから電話番号をレンタルするには、次のコマンドを使用します(国コードをあなたのコードに置き換えてください)。例えば、アメリカにいる場合は、次のように置き換えます。 GBUS:

vonage numbers:search US vonage numbers:buy [NUMBER] [COUNTRYCODE]

その番号をアプリにリンクさせる:

vonage apps:link --number=VONAGE_NUMBER APP_ID

Androidプロジェクトのセットアップ

Androidアプリの完成したプロジェクトをご覧になりたい方は、GitHubでソースコードをご覧いただけます。 GitHubのソースコードをご覧ください。

まずは必要なライブラリを追加します。ここではNexmo Stitch Android SDK、Retrofit、そしてRetrofitのMoshi Converterを使います。

dependencies {
  implementation 'com.nexmo:stitch:1.8.0'
  implementation 'com.squareup.retrofit2:retrofit:2.4.0'
  implementation "com.squareup.retrofit2:converter-moshi:2.4.0"
}

私たちは レトロフィットを使って GETFirebase CLI が提供してくれた Firebase 関数の JWT エンドポイントにリクエストします。

//FirebaseFunctionService.kt
interface FirebaseFunctionService {
    @GET("jwt")
    fun getJWT(): Call<UserJWT>
}


//RetrofitClient.kt
var retrofitClient = Retrofit.Builder()
        .baseUrl("https://your-project-name.cloudfunctions.net/")
        .addConverterFactory(MoshiConverterFactory.create())
        .build()

var retrofitService = retrofitClient.create<FirebaseFunctionService>(FirebaseFunctionService::class.java)

ログインアクティビティの追加

Retrofitをセットアップしたら、それを使ってJWT Firebase関数のエンドポイントからJWTを取得します。 LoginActivity.ここでは ハッピーパスユーザーJWTを取得し、それを使ってNexmo Stitch Android SDKにログインしたときのハッピーパスを示します。 このアクティビティのレイアウトはGitHubにあります。.

class LoginActivity : BaseActivity(), RequestHandler<User>, Callback<UserJWT> {
    override fun onCreate(savedInstanceState: Bundle?) {
        ...
        loginBtn.setOnClickListener {
            login()
        }
    }

    private fun login() {
        showProgress(true)
        retrofitService.getJWT().enqueue(this)
    }

    //Successfully retrieved a JWT from the Firebase Function endpoint
    override fun onResponse(call: Call<UserJWT>?, response: Response<UserJWT>?) {
        val jwt = response?.body()?.user_jwt
        client.login(jwt, this)
    }

    //User successfully logged in with the Nexmo Stitch SDK
    override fun onSuccess(result: User?) {
        goToCallActivity()
    }

}

コールアクティビティの追加

電話番号の入力、電話の開始、終了のためのシンプルなレイアウトを追加します。 このアクティビティのレイアウトはGitHubにあります。.前回と同じように、電話をかけたり受けたりする幸せな経路を示します。

class CallActivity : BaseActivity(), RequestHandler<Call> {
    private var currentCall: Call? = null
    private lateinit var client: ConversationClient

    override fun onCreate(savedInstanceState: Bundle?) {
        ...
        client = Stitch.getInstance(this).conversationClient

        attachIncomingCallListener()
        callControlBtn.setOnClickListener { callPhone() }
    }

    private fun attachIncomingCallListener() {
        //Listen for incoming calls
        client.callEvent().add({ incomingCall ->
            logAndShow("answering Call")
            //Answer an incoming call
            incomingCall.answer(object : RequestHandler<Void> {
                override fun onError(apiError: NexmoAPIError) {
                    logAndShow("Error answer: " + apiError.message)
                }

                override fun onSuccess(result: Void) {
                    currentCall = incomingCall
                    attachCallStateListener(incomingCall)
                    showHangupButton()
                }
            })
        })
    }

    private fun attachCallStateListener(incomingCall: Call) {
        //Listen for incoming member events in a call
        val callEventListener = ResultListener<CallEvent> { message ->
            logAndShow("callEvent : state: " + message.state + " .content:" + message.toString())
        }
        incomingCall.event().add(callEventListener)
    }


    private fun callPhone() {
        val phoneNumber = phoneNumberInput.text.toString()

        client.callPhone(phoneNumber, object : RequestHandler<Call> {
            override fun onError(apiError: NexmoAPIError) {
                logAndShow("Cannot initiate call: " + apiError.message)
            }

            override fun onSuccess(result: Call) {
                currentCall = result
                showHangupButton()

                when (result.callState) {
                    Call.CALL_STATE.STARTED -> logAndShow("Started")
                    Call.CALL_STATE.RINGING -> logAndShow("Ringing")
                    Call.CALL_STATE.ANSWERED -> logAndShow("Answered")
                    else -> logAndShow("Error attaching call listener")
                }

            }
        })
    }

}

ご覧のように、Nexmo Stitch SDKは電話の発信と応答という大変な仕事をこなしてくれます。

どのように機能するのか?

電話を受ける

ユーザーが前節で購入した番号に電話をかけると、NexmoはNCCOをアンサーURLの https://your-project-name.cloudfunctions.net/answer.NCCOは次のように表示される:

[  
   {  
      "action":"talk",
      "text":"You are being connected to the Customer."
   },
   {  
      "action":"connect",
      "endpoint":[  
         {  
            "type":"app",
            "user":"Customer"
         }
      ]
   }
]

このNCCOは、Stitch SDKを使ってアプリ内に作成した "Customer "ユーザーに電話をかけます。のCall Listenerをアタッチすることで、アプリが呼び出しに応答する処理を行います。 attachIncomingCallListener()簡単のため、ここでは自動的に電話に出ることにしますが、ユーザーが電話に出たり、電話に出なかったりできるように、UIとロジックを実装することもできます。 reject()を実装することができます。

電話をかける

ユーザーが電話をかけることを選択した場合、それを callPhone()メソッドで処理します。例えば、私たちのメソッドがこのように呼び出されたとします:

client.callPhone("14155550100", callback)

では client.callPhone(phoneNumber, callback)メソッドメソッドは、Stitch APIを使用して、以下のクエリパラメータであなたの回答URL にリクエストします。 GETを使用し、以下のクエリパラメータで https://your-project-name.cloudfunctions.net/answer にリクエストします:

?from=16625461410\ &to=14155550100\ &conversation_uuid=CON-4e977dab-2abc-42b5-bf64-d468d4763e54\ &uuid=0666edbe58077d826944a7c1913da2b0

この toパラメータを使って、Nexmoにどの電話番号に電話をかけるかを伝えるNCCOを動的に返すことができます。Stitch APIは以下のようなNCCOレスポンスを見ることになる:

[  
   {  
      "action":"talk",
      "text":"Thank you for calling, you are now being connected."
   },
   {  
      "action":"connect",
      "from":"12013753230",
      "endpoint":[  
         {  
            "type":"phone",
            "number":"14155550100"
         }
      ]
   }
]

この場合 fromとして設定した番号です。 nexmo.from_numberに設定した番号です。の値は number配列の endpoint配列のkeyの値は、ユーザーが電話をかけたい番号です。

自分で試してみる

このサンプルプロジェクトのリポジトリには Firebase Functions と Android Sample app の両方のソースコードが含まれています。プロジェクトをクローンして確認してください!

次はどうする?

で電話をかけたり受けたりする方法を学びました。 Nexmo In-App Voiceでの電話のかけ方と受け方アプリ内メッセージング アプリ内メッセージング.

Nexmo Stitch Android SDKの詳細については、以下のドキュメントをご覧ください。 SDKドキュメント.

私たちの Voice APIは、単に通話を接続したり受信したりするだけでなく、他の可能性も提供しています!通話の録音、音声ストリームの再生など、詳しくはドキュメントをご覧ください。

シェア:

https://a.storyblok.com/f/270183/150x150/a3d03a85fd/placeholder.svg
Chris Guzmanヴォネージの卒業生

クリスはNexmoのデベロッパー・アドボケイトとして、デベロッパーがグローバル・コミュニケーション・プラットフォームを使えるようにサポートしている。カンファレンスに出席していないときは、世界中を歩き回っている。