Para verificar números de telefone automaticamente, é preciso implementar as partes do cliente e do servidor do fluxo de verificação. Este documento descreve como implementar a parte do cliente em um app Android.
Para iniciar o fluxo de verificação do número de telefone em um app Android, envie o número de telefone ao servidor de verificação e chame a API SMS Retriever para começar a ouvir uma mensagem SMS com um código de uso único do app. Depois de receber a mensagem, envie o código único de volta ao servidor para concluir o processo de verificação.
Antes de começar
Para preparar o app, siga as etapas nas seções a seguir.
Pré-requisitos do app
O arquivo de build do app precisa usar estes valores:
- uma minSdkVersion de 19 ou mais;
- Uma compileSdkVersion de 28 ou mais recente.
Configurar o app
No arquivo build.gradle no nível do projeto, inclua o repositório Maven do Google
e o repositório Maven central
nas seções buildscript
e allprojects
:
buildscript {
repositories {
google()
mavenCentral()
}
}
allprojects {
repositories {
google()
mavenCentral()
}
}
Adicione a dependência do Google Play Services
para a API SMS Retriever ao arquivo de build do Gradle do módulo,
que geralmente é app/build.gradle
:
dependencies {
implementation 'com.google.android.gms:play-services-auth:20.5.0'
implementation 'com.google.android.gms:play-services-auth-api-phone:18.0.1'
}
1. Obter o número de telefone do usuário
Você pode conseguir o número de telefone do usuário da maneira apropriada para seu app. Muitas vezes, é melhor usar o seletor de dica para solicitar que o usuário escolha os números de telefone armazenados no dispositivo e, assim, não ter que digitar manualmente um número de telefone. Para usar o seletor de dica:
// Construct a request for phone numbers and show the picker
private void requestHint() {
HintRequest hintRequest = new HintRequest.Builder()
.setPhoneNumberIdentifierSupported(true)
.build();
PendingIntent intent = Auth.CredentialsApi.getHintPickerIntent(
apiClient, hintRequest);
startIntentSenderForResult(intent.getIntentSender(),
RESOLVE_HINT, null, 0, 0, 0);
}
// Obtain the phone number from the result
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == RESOLVE_HINT) {
if (resultCode == RESULT_OK) {
Credential credential = data.getParcelableExtra(Credential.EXTRA_KEY);
// credential.getId(); <-- will need to process phone number string
}
}
}
2. Iniciar o recuperador de SMS
Quando você estiver pronto para verificar o número de telefone do usuário, receba uma instância do objeto SmsRetrieverClient
, chame startSmsRetriever
e anexe os listeners de sucesso e falha à tarefa de recuperação de SMS:
// Get an instance of SmsRetrieverClient, used to start listening for a matching
// SMS message.
SmsRetrieverClient client = SmsRetriever.getClient(this /* context */);
// Starts SmsRetriever, which waits for ONE matching SMS message until timeout
// (5 minutes). The matching SMS message will be sent via a Broadcast Intent with
// action SmsRetriever#SMS_RETRIEVED_ACTION.
Task<Void> task = client.startSmsRetriever();
// Listen for success/failure of the start Task. If in a background thread, this
// can be made blocking using Tasks.await(task, [timeout]);
task.addOnSuccessListener(new OnSuccessListener<Void>() {
@Override
public void onSuccess(Void aVoid) {
// Successfully started retriever, expect broadcast intent
// ...
}
});
task.addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(@NonNull Exception e) {
// Failed to start retriever, inspect Exception for more details
// ...
}
});
A tarefa de recuperação de SMS detectará por até cinco minutos uma mensagem SMS que contém uma string exclusiva que identifica seu aplicativo.
3. Enviar o número de telefone ao seu servidor
Depois de receber o número de telefone do usuário e começar a ouvir mensagens SMS, envie o número de telefone do usuário para seu servidor de verificação usando qualquer método (geralmente com uma solicitação HTTPS POST).
Seu servidor gera uma mensagem de verificação e a envia por SMS para o número de telefone especificado. Consulte Executar a verificação por SMS no servidor.
4. Receber mensagens de verificação
Quando uma mensagem de verificação é recebida no dispositivo do usuário, o Play Services
transmite explicitamente ao app uma intent SmsRetriever.SMS_RETRIEVED_ACTION
,
que contém o texto da mensagem. Use um BroadcastReceiver
para receber
essa mensagem de verificação.
No gerenciador onReceive
do BroadcastReceiver
, extraia o texto da mensagem de verificação dos extras do intent:
/**
* BroadcastReceiver to wait for SMS messages. This can be registered either
* in the AndroidManifest or at runtime. Should filter Intents on
* SmsRetriever.SMS_RETRIEVED_ACTION.
*/
public class MySMSBroadcastReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
if (SmsRetriever.SMS_RETRIEVED_ACTION.equals(intent.getAction())) {
Bundle extras = intent.getExtras();
Status status = (Status) extras.get(SmsRetriever.EXTRA_STATUS);
switch(status.getStatusCode()) {
case CommonStatusCodes.SUCCESS:
// Get SMS message contents
String message = (String) extras.get(SmsRetriever.EXTRA_SMS_MESSAGE);
// Extract one-time code from the message and complete verification
// by sending the code back to your server.
break;
case CommonStatusCodes.TIMEOUT:
// Waiting for SMS timed out (5 minutes)
// Handle the error ...
break;
}
}
}
}
Registre esse BroadcastReceiver
com o filtro de intent com.google.android.gms.auth.api.phone.SMS_RETRIEVED
(o valor da constante SmsRetriever.SMS_RETRIEVED_ACTION
) e a permissão com.google.android.gms.auth.api.phone.permission.SEND
(o valor da constante SmsRetriever.SEND_PERMISSION
) no arquivo AndroidManifest.xml
do seu aplicativo, como no exemplo a seguir, ou usando dinamicamente Context.registerReceiver
.
<receiver android:name=".MySMSBroadcastReceiver" android:exported="true"
android:permission="com.google.android.gms.auth.api.phone.permission.SEND">
<intent-filter>
<action android:name="com.google.android.gms.auth.api.phone.SMS_RETRIEVED"/>
</intent-filter>
</receiver>
5. Enviar o código único da mensagem de verificação para seu servidor
Agora que você tem o texto da mensagem de verificação, use uma expressão regular ou outra lógica para receber o código de uso único da mensagem. O formato do código único depende de como você os implementou no servidor.
Por fim, envie o código único para seu servidor por uma conexão segura. Quando o servidor recebe o código único, ele registra que o número de telefone foi verificado.
Opcional: salvar o número de telefone com o Smart Lock para senhas
Opcionalmente, depois que o usuário verificar o número de telefone, você poderá solicitar que ele salve essa conta com o Smart Lock para senhas para que ela fique disponível automaticamente em outros apps e em outros dispositivos sem precisar digitar ou selecionar o número de telefone novamente:
Credential credential = new Credential.Builder(phoneNumberString)
.setAccountType("https://signin.example.com") // a URL specific to the app
.setName(displayName) // optional: a display name if available
.build();
Auth.CredentialsApi.save(apiClient, credential).setResultCallback(
new ResultCallback() {
public void onResult(Result result) {
Status status = result.getStatus();
if (status.isSuccess()) {
Log.d(TAG, "SAVE: OK"); // already saved
} else if (status.hasResolution()) {
// Prompt the user to save
status.startResolutionForResult(this, RC_SAVE);
}
}
});
Depois que o usuário reinstalar o app ou instalá-lo em um novo dispositivo, você poderá recuperar o número de telefone salvo sem precisar perguntar novamente ao usuário:
// On the next install, retrieve the phone number
mCredentialRequest = new CredentialRequest.Builder()
.setAccountTypes("https://signin.example.com") // the URL specific to the developer
.build();
Auth.CredentialsApi.request(apiClient, mCredentialRequest).setResultCallback(
new ResultCallback<CredentialRequestResult>() {
public void onResult(CredentialRequestResult credentialRequestResult) {
if (credentialRequestResult.getStatus().isSuccess()) {
credentialRequestResult.getCredential().getId(); // this is the phone number
}
}
});
// Then, initiate verification and sign the user in (same as original verification logic)