【问题标题】:Cannot get OTP when use Sms Retriever使用 Sms Retriever 时无法获取 OTP
【发布时间】:2019-07-21 00:41:27
【问题描述】:

我正在尝试使用 Google 的 SMS Retriever API 进行自动 SMS 验证。我已按照here 的指示进行操作,但我的应用没有收到任何 SMS 消息。我尝试了很多方法,但仍然无法正常工作,我真的不明白为什么。

这就是我所做的。首先我创建类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();
    }

}

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

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 的 SMS Retriever API 不需要权限
  • 是的,你是对的人,问题是别的

标签: android sms one-time-password


【解决方案1】:

您无需在清单中添加任何权限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:如果您仍然遇到困难,请告诉我。

【讨论】:

  • 我进行了测试,但它运行不完美,但在我的 Java 代码项目中,它仍然无法运行。
【解决方案2】:

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

  1. 消息 (otp) 应以前缀

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

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

这篇文章将是helpfully

【讨论】:

  • 我也是这样,那是我的消息 SampleApp: Your verification code is 143567 32urg60XXXX 但它不起作用。
【解决方案3】:

确保您的模拟器/设备上的播放服务版本 > 10.2.0

【讨论】:

  • 感谢您的回答,但我的手机中的 google play 服务是 15.0.90。
【解决方案4】:

请交叉检查您的清单

1.你是否在清单中添加了以下代码

<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”

【讨论】:

    【解决方案5】:

    如果您只想为 android 检索 OTP,我会向您推荐这个 package SMS 这在 android 上运行得很好,而且它只有 2 行代码 获取传入的短信;

    创建一个receiver实例

    SmsReceiver receiver = new SmsReceiver();
    

    在你的 initstate 中监听传入的短信

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

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

    【讨论】:

      猜你喜欢
      • 2019-08-08
      • 1970-01-01
      • 2019-07-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-08-20
      • 2019-07-18
      相关资源
      最近更新 更多