使用 Sms Retriever 时无法获取 OTP

Cannot get OTP when use Sms Retriever

我正在尝试使用 Google 的短信检索器 API 进行自动短信验证。我已按照说明 here 进行操作,但我的应用程序没有收到任何短信。我已经尝试了很多方法,但它仍然无法正常工作,我真的不明白为什么。

这是我所做的。首先我创建 class MySMSBroadcastReceiver:

public class MySMSBroadcastReceiver extends BroadcastReceiver {

    public OTPReceiveListener otpReceiveListener;
    public void initOtpReceiveListener(OTPReceiveListener otpReceiveListener) {
        this.otpReceiveListener = otpReceiveListener;
    }

    @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);
                    otpReceiveListener.onOTPReceived(message);
                    break;
                case CommonStatusCodes.TIMEOUT:
                    otpReceiveListener.onOTPTimeOut();
                    break;
            }
        }
    }

    public interface OTPReceiveListener {

        void onOTPReceived(String otp);
        void onOTPTimeOut();
    }

}

对于classOTPActivity,我删除了不相关的代码:

public class OTPActivity extends BaseActivity implements IDelegateResponse<OTPResponse>, GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, MySMSBroadcastReceiver.OTPReceiveListener {

    @BindView(R.id.edtSmsOtp)
    EditText edtSmsOtp;

    private final String TAG = "OTPActivity";
    private MySMSBroadcastReceiver mySMSBroadcastReceiver;

    @Override
    public int getLayoutID() {
        return R.layout.activity_otp;
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setUpOTPSms();
    }

    private void setUpOTPSms() {
        AppSignatureHelper appSignatureHelper = new AppSignatureHelper(OTPActivity.this);
        Utils.showLog(TAG, "getAppSignatures:" + appSignatureHelper.getAppSignatures());

        mySMSBroadcastReceiver = new MySMSBroadcastReceiver();
        mySMSBroadcastReceiver.initOtpReceiveListener(this);

        IntentFilter intentFilter = new IntentFilter();
        intentFilter.addAction(SmsRetriever.SMS_RETRIEVED_ACTION);
        intentFilter.setPriority(2147483647);
        registerReceiver(mySMSBroadcastReceiver, intentFilter);

        startSMSListener();
   }

    private void startSMSListener() {
        SmsRetrieverClient client = SmsRetriever.getClient(OTPActivity.this);
        Task<Void> task = client.startSmsRetriever();
        task.addOnSuccessListener(aVoid -> {
            //Toast.makeText(OTPActivity.this, "SMS Retriever starts", Toast.LENGTH_LONG).show();
            Utils.showLog(TAG, "SMS Retriever starts");
        });
        task.addOnFailureListener(e -> Toast.makeText(OTPActivity.this, "Error", Toast.LENGTH_LONG).show());
    }

    @Override
    public void onConnected(@Nullable Bundle bundle) {

    }

    @Override
    public void onConnectionSuspended(int i) {

    }

    @Override
    public void onConnectionFailed(@NonNull ConnectionResult connectionResult) {

    }

    @Override
    public void onOTPReceived(String otp) {
        if (mySMSBroadcastReceiver != null) {
            unregisterReceiver(mySMSBroadcastReceiver);
        }

        Utils.showLog("OTP Received", "OTP: " + otp);
    }

    @Override
    public void onOTPTimeOut() {
        Utils.showLog("OTP Received", "onOTPTimeOut");
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (mySMSBroadcastReceiver != null) {
            unregisterReceiver(mySMSBroadcastReceiver);
        }
    }
}

Google 最近更改了短信策略。现在您必须以这种方式发送短信,OTP:

  1. 消息 (otp) 应以前缀 <#>

  2. 开头
  3. 消息 (otp) 不能超过 140 字节

  4. 消息 (otp) 应以 11 个字符结尾 标识您的应用程序的哈希字符串。

这个 post 将是 helpfully

确保 emulator/device 上的播放服务版本 > 10.2.0

您无需在清单 中添加任何权限,OPT 即可工作。 遵循给定的代码(在 Kotlin 中,易于实现并且正在运行)。

class MainActivity : AppCompatActivity() {

private val smsBroadcastReceiver by lazy { SMSBroadcastReceiver() }

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)

    val client = SmsRetriever.getClient(this)
    val retriever = client.startSmsRetriever()
    retriever.addOnSuccessListener {

        Toast.makeText(this@MainActivity,"Listener started", Toast.LENGTH_SHORT).show()

        val otpListener = object : SMSBroadcastReceiver.OTPListener {
            override fun onOTPReceived(otp: String) {
                customCodeInput.setText(otp)
                Toast.makeText(this@MainActivity, otp , Toast.LENGTH_LONG).show()
            }

            override fun onOTPTimeOut() {
                Toast.makeText(this@MainActivity,"TimeOut", Toast.LENGTH_SHORT).show()
            }
        }
        smsBroadcastReceiver.injectOTPListener(otpListener)
        registerReceiver(smsBroadcastReceiver,
                IntentFilter(SmsRetriever.SMS_RETRIEVED_ACTION))
    }
    retriever.addOnFailureListener {
        Toast.makeText(this@MainActivity,"Problem to start listener", Toast.LENGTH_SHORT).show()
    }

}

override fun onDestroy() {
    super.onDestroy()
    unregisterReceiver(smsBroadcastReceiver)
}}

SMSBroadcastReceiver如下:

class SMSBroadcastReceiver: BroadcastReceiver() {

private var otpReceiver: OTPListener? = null

fun injectOTPListener(receiver: OTPListener?) {
    this.otpReceiver = receiver
}

override fun onReceive(context: Context, intent: Intent) {
    if (SmsRetriever.SMS_RETRIEVED_ACTION == intent.action) {
        val extras = intent.extras
        val status = extras.get(SmsRetriever.EXTRA_STATUS) as Status

        when (status.statusCode) {

            CommonStatusCodes.SUCCESS -> {

                val message = extras.get(SmsRetriever.EXTRA_SMS_MESSAGE) as String

                val pattern = Pattern.compile("\d{6}")
                val matcher = pattern.matcher(message)

                if (matcher.find()) {
                    otpReceiver?.onOTPReceived(matcher.group(0))
                    return
                }
            }
            CommonStatusCodes.TIMEOUT -> {
                otpReceiver?.onOTPTimeOut()
            }
        }
    }
}

interface OTPListener {


    fun onOTPReceived(otp: String)

    fun onOTPTimeOut()
}}

PS : 如果您仍然遇到困难,请告诉我。

请同时核对您的清单

1.have 您在清单中添加了以下代码

<receiver android:name=".MySMSBroadcastReceiver" 
          android:exported="true">
  <intent-filter>
    <action android:name="com.google.android.gms.auth.api.phone.SMS_RETRIEVED" />
  </intent-filter>
</receiver>
  1. 添加依赖关系

    实施"com.google.android.gms:play-services-auth-api-phone:15.0.1"

如果您只想检索 android 的 OTP,我会向您推荐这个 package SMS 这在 android 上非常有效,它只有 2 行代码 获取传入的短信;

创建接收器实例

SmsReceiver receiver = new SmsReceiver();

在您的初始化状态中收听传入的短信

receiver.onSmsReceived.listen((SmsMessage msg) => print(msg.body));

这很好用,但不幸的是这个包不支持 ios