Todos hemos visto, sobretodo en los procesos de registro, como al recibir un SMS con un código en Android no es necesario copiarlo y pegarlo, la App solita es capaz de procesar el contenido del SMS y actuar autónomamente; pues bien hoy les enseñaré como hacer dicha magia en Android, realmente no es tan complicado, comenzamos.

 

Primero que nada hay que definir en el manifest de nuestro proyecto la clase que se encargará de procesar la recepción del SMS

<receiver android:name=".Receiver.SmsBroadcastReceiver" android:exported="true">
    <intent-filter>
        <action android:name="com.google.android.gms.auth.api.phone.SMS_RETRIEVED"/>
    </intent-filter>
</receiver>



Como siguiente paso, debemos crear la clase SMSBroadCasrReceiver y definir las acciones que haremos, empezando por extender nuestra clase de la clase BroadcastReceiver, definir un objeto OTPReceiveListener que nos ayudara a recibir los eventos, un constructor para inicializar nuestros objetos, y redefinir la función onReceive donde colocaremos las acciones que debemos definir. Por último definimos las funciones de interface que ocuparemos en nuestra actividad.


import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;

import com.google.android.gms.auth.api.phone.SmsRetriever;
import com.google.android.gms.common.api.CommonStatusCodes;
import com.google.android.gms.common.api.Status;


public class SmsBroadcastReceiver extends BroadcastReceiver
{

    private OTPReceiveListener otpReceiver = null;

    public void initOTPListener(OTPReceiveListener receiver)
    {
        this.otpReceiver = receiver;
    }

    @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:
                    
                    String message = (String) extras.get(SmsRetriever.EXTRA_SMS_MESSAGE);
                    

                    if (otpReceiver != null)
                    {
                        otpReceiver.onOTPReceived(message);
                    }
                    break;
                case CommonStatusCodes.TIMEOUT:
                    
                    if(otpReceiver != null)
                    {
                        otpReceiver.onOTPTimeOut();
                    }
                    break;
            }
        }
    }

    public interface OTPReceiveListener
    {

        void onOTPReceived(String otp);

        void onOTPTimeOut();
    }
}


Ahora teniendo esto, necesitamos implementarlo en una actividad o fragmento, para que pueda ser procesada en alguna de nuestras interfaces, primero comenzaremos por implementar el listener de nuestra clase anterior a nuestro activity y definimos una variable del tipo SMSBroadCasrReceiver

 

public final class MyActivity implements SmsBroadcastReceiver.OTPReceiveListener
{

    SmsBroadcastReceiver smsBroadcastReceiver = new SmsBroadcastReceiver();


Creamos una función para inicializar la recepción mediante un listener en un task

 

public void startSMSListener()
{
    SmsRetrieverClient client = SmsRetriever.getClient(getApplicationContext());
    Task<Void> task = client.startSmsRetriever();
    task.addOnSuccessListener(new OnSuccessListener<Void>(){
        @Override
        public void onSuccess(Void aVoid)
        {
            Log.d("AppEjemplo", "Esperando el mensaje");        }
    });

    task.addOnFailureListener(new OnFailureListener() {
        @Override
        public void onFailure(@NonNull Exception e)
       {
            Log.d("AppEjemplo", "No se pudo inicializar");
        }
    });

}




Posteriormente inicializamos los objetos para la recepción del SMS, usando nuestra función antes definida.

 

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {

    final View vista = inflater.inflate(R.layout.my_layout, container, false);

    startSMSListener();
    smsBroadcastReceiver.initOTPListener(this);
    IntentFilter intentFilter = new IntentFilter();
    intentFilter.addAction(SmsRetriever.SMS_RETRIEVED_ACTION);
    getApplicationContext().registerReceiver(smsBroadcastReceiver, intentFilter);

    return vista;
}

 

Finalmente redefinimos dos funciones que nos ayudaran con el procesamiento final y con el timeout.

 

@Override
public void onOTPReceived(String otp)
{
    if(smsBroadcastReceiver != null)
    {
        LocalBroadcastManager.getInstance(getApplicationContext()).unregisterReceiver(smsBroadcastReceiver);
    }

    
    Log.d("AppEjemplo","Mensaje recibido: " + otp);

}

@Override
public void onOTPTimeOut()
{
    Log.d("AppEjemplo","Timed Out");
}