
Compartilhar:
Chris é Developer Advocate na Nexmo, onde ajuda desenvolvedores a utilizar sua plataforma global de comunicações. Quando não está em conferências, é possível encontrá-lo viajando pelo mundo.
Faça e receba chamadas em aplicativos Android com o Firebase
Com Nexmo In-App Voice, você pode facilmente fazer e receber chamadas telefônicas com o SDK do Nexmo Stitch para Android e a tecnologia WebRTC. Neste tutorial, mostraremos como criar um aplicativo Android simples capaz de fazer chamadas e receber chamadas. Essa funcionalidade pode ser utilizada quando os clientes desejam fazer e receber chamadas para o atendimento ao cliente sem sair do aplicativo.
Para colocar o aplicativo em funcionamento, vamos usar o Firebase Functions para hospedar o NCCO e retornar um JWT para que os usuários possam fazer login.
Para acompanhar esta postagem do blog, você deve ter algum conhecimento de JavaScript e ser capaz de desenvolver um aplicativo para Android usando Kotlin.
Antes de começarmos
Há algumas coisas de que você vai precisar antes de começarmos.
Account da Vonage
Configure a função do Firebase.
Primeiro, vamos criar um novo diretório para o nosso projeto de funções do Firebase e para armazenar nossos arquivos de configuração.
mkdir firebase-functions-nexmo-in-app-calling cd firebase-functions-nexmo-in-app-calling
Agora que um novo diretório foi criado, podemos seguir as instruções de configuração fornecidas pelo Firebase e criar um novo projeto.
npm install -g firebase-tools firebase login firebase init functions
Para este projeto, optei por usar JavaScript em vez de TypeScript.
Se, assim como eu, você não conseguiu criar um projeto de funções do Firebase a partir da linha de comando, pode acessar o Console do Firebase para criar um novo projeto e, em seguida, execute firebase use --add a partir da sua linha de comando.
Editar as funções do Firebase
Você pode conferir a versão final dos métodos que usaremos para as Funções do Firebase no repositório desta demonstração no GitHub. Resumindo, precisamos de três endpoints:
Um URL de resposta que hospedará o NCCO
Uma URL de evento para capturar eventos da Voice API
Uma URL para gerar um JWT com o qual os usuários possam fazer login
Para editar as funções do Firebase, precisaremos editar o index.js arquivo no novo functions/ diretório que o Firebase criou depois que executamos firebase init functions
Vamos começar dando uma olhada no método Answer
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);
});Como a Voice API da Nexmo utiliza uma URL de resposta por aplicativo, podemos exibir dinamicamente o NCCO para aceitar uma chamada recebida caso o to parâmetro de consulta for nulo. Se o to parâmetro de consulta for não for nulo, exibiremos o NCCO para realizar uma chamada de saída.
Nosso endpoint para fornecer um JWT aos usuários é bastante simples. Usaremos a biblioteca Nexmo para Node para gerar um JWT. Para usar a biblioteca, precisaremos instalar o pacote.
#Certifique-se de estar no diretório /functions, onde estão os arquivos package.json e index.js: npm install nexmo
Após instalar a biblioteca, você pode verificar se tudo está funcionando corretamente examinando o package.json arquivo. Ele deve ter a seguinte aparência:
"dependencies": {
"firebase-admin": "~5.12.1",
"firebase-functions": "^1.0.3",
"nexmo": "^2.3.2"
}Depois que a biblioteca Nexmo Node estiver instalada, podemos usá-la no endpoint jwt desta forma para retornar um 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
})
});
});Agora que criamos nossas funções do Firebase, vamos criar um aplicativo da Vonage.
Implantar a função do Firebase
Agora que as funções do Firebase foram criadas, podemos implantar o projeto do Firebase. Após a implantação das funções, o Firebase nos fornecerá as URLs dos nossos endpoints de resposta e de evento. Podemos usar essas URLs para criar nosso aplicativo Vonage.
#Certifique-se de estar no diretório firebase-functions-nexmo-in-app-calling/ que criamos no início deste tutorial: firebase deploy --only functions
✔ functions[answer]: Operação de criação bem-sucedida. URL da função (resposta): https://your-project-name.cloudfunctions.net/answer ✔ functions[event]: Operação de criação bem-sucedida. URL da função (event): https://your-project-name.cloudfunctions.net/event ✔ funções[jwt]: Operação de criação bem-sucedida. URL da função (jwt): https://your-project-name.cloudfunctions.net/jwt
Configure o aplicativo da Vonage.
Para criar uma aplicação, primeiro instale a CLI da Vonage globalmente com este comando:
npm install @vonage/cli -gEm seguida, configure a CLI com sua chave e seu segredo da API da Vonage. Você pode encontrar essas informações no Painel do Desenvolvedor.
vonage config:set --apiKey=VONAGE_API_KEY --apiSecret=VONAGE_API_SECRETAgora vamos usar a resposta e a URL do evento que o Firebase nos forneceu na seção anterior.
# 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_narwhalSua chave privada é salva no diretório “functions” que você criou. A chave terá o mesmo nome do seu projeto.
Anote o ID do aplicativo e salve a chave privada no diretório “functions”. Recomendo que você adicione o your_private_key_name.key e .nexmo-app arquivos com suas credenciais ao seu .gitignore.
Seguindo as melhores práticas, vamos armazenar algumas variáveis de ambiente da configuração do Firebase por meio da CLI do Firebase. A documentação do Firebase contém uma visão geral sobre a configuração do ambiente.
Agora precisamos armazenar o ID do aplicativo da Vonage na configuração do Firebase por meio da CLI do Firebase.
firebase functions:config:set nexmo.application_id="aaaaaaaa-bbbb-cccc-dddd-0123456789ab"
Observação: o Firebase exige que as chaves das variáveis de configuração estejam em letras minúsculas; portanto, usaremos o formato “snake case” para os nomes das nossas variáveis.
Se desejar, você pode enviar a sequência da chave privada encontrada no .nexmo-app arquivo do seu aplicativo Vonage como uma variável de configuração do Firebase, em vez de enviar o arquivo inteiro your_private_key_name.key arquivo inteiro para as funções do Firebase.
Associar um número de telefone e um usuário ao nosso aplicativo
Agora que nossas funções já estão prontas, precisamos adquirir um número para que nossos usuários possam fazer chamadas de saída a partir desse número e receber chamadas de entrada em seu aplicativo Android sempre que alguém ligar para esse número. Também precisamos vincular o número ao nosso aplicativo da Vonage.
Você pode alugar um número da Vonage usando o comando a seguir (substituindo o código do país pelo seu). Por exemplo, se você estiver nos EUA, substitua GB por US:
Agora, vincule o número ao seu aplicativo:
vonage apps:link --number=VONAGE_NUMBER APP_ID Configurar o projeto Android
Se você quiser ver o projeto finalizado do nosso aplicativo para Android, pode acessar o código-fonte no GitHub.
Primeiro, precisamos adicionar as bibliotecas necessárias. Vamos usar o SDK do Nexmo Stitch para Android, o Retrofit e o Moshi Converter do Retrofit.
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"
}Vamos usar o Retrofit para fazer uma GET solicitação ao endpoint JWT da função do Firebase que a CLI do Firebase nos forneceu.
//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) Adicionar a atividade de login
Depois de configurar o Retrofit, podemos usá-lo para recuperar um JWT do endpoint da função JWT do Firebase no LoginActivity. Aqui, vou mostrar o caminho ideal em que recuperamos o JWT do usuário e o usamos para fazer login no SDK do Nexmo Stitch para Android. O layout dessa Activity está disponível no 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()
}
} Adicionar a atividade de chamada
Vamos adicionar um layout simples para inserir números de telefone, iniciar e encerrar chamadas. O layout para essa atividade está disponível no GitHub. Assim como antes, vou mostrar o fluxo normal de fazer e receber uma ligação.
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")
}
}
})
}
}Como você pode ver, o SDK do Nexmo Stitch cuida da parte mais trabalhosa de fazer e atender chamadas telefônicas.
Como isso funciona?
Receber uma ligação
Quando um usuário liga para o número que adquirimos na seção anterior, a Nexmo consultará o NCCO em nossa URL de resposta em https://your-project-name.cloudfunctions.net/answer . O NCCO terá a seguinte aparência:
[
{
"action":"talk",
"text":"You are being connected to the Customer."
},
{
"action":"connect",
"endpoint":[
{
"type":"app",
"user":"Customer"
}
]
}
]Este NCCO encaminhará a chamada para o usuário “Cliente” que criamos em nosso aplicativo com o SDK do Stitch. O aplicativo se encarregará de atender a chamada, anexando o Call Listener em attachIncomingCallListener() Para simplificar, vamos atender a chamada automaticamente, mas você pode implementar uma interface de usuário e uma lógica que permitam ao usuário atender ou reject() a chamada.
Fazer uma ligação
Se o usuário optar por fazer uma chamada, trataremos disso no callPhone() método. Por exemplo, se nosso método fosse chamado assim:
client.callPhone("14155550100", callback)Então, o client.callPhone(phoneNumber, callback) método no SDK do Nexmo Stitch para Android usará a API do Stitch para enviar GET uma solicitação à sua URL de resposta https://your-project-name.cloudfunctions.net/answer com os seguintes parâmetros de consulta:
?from=16625461410\ &to=14155550100\ &conversation_uuid=CON-4e977dab-2abc-42b5-bf64-d468d4763e54\ &uuid=0666edbe58077d826944a7c1913da2b0
Podemos usar o to parâmetro para retornar dinamicamente um NCCO que informa à Nexmo qual número de telefone deve ser chamado. A API do Stitch receberá a seguinte resposta NCCO:
[
{
"action":"talk",
"text":"Thank you for calling, you are now being connected."
},
{
"action":"connect",
"from":"12013753230",
"endpoint":[
{
"type":"phone",
"number":"14155550100"
}
]
}
]Nesse caso, o from número é aquele que alugamos da Nexmo e definimos como nexmo.from_number com as variáveis de configuração do Firebase. O valor na number chave na endpoint matriz é o número para o qual nosso usuário deseja ligar.
Experimente você mesmo
O repositório deste projeto de exemplo contém o código-fonte tanto do Firebase Functions quanto do aplicativo de exemplo para Android. Clone o projeto para conferir por conta própria!
E agora?
Agora que você já aprendeu a fazer e receber chamadas telefônicas com o Nexmo In-App Voice , você também pode saber mais sobre o In-App Messaging.
Para obter detalhes mais aprofundados sobre o que o SDK do Nexmo Stitch para Android abrange, você pode ler a documentação do SDK online.
Nossa Voice API também oferece outras possibilidades além de apenas conectar e receber chamadas! Acesse nossa documentação para saber mais sobre como gravar chamadas, reproduzir áudio durante as chamadas e muito mais.