如何为OTP添加自动填充建议

3

我在一些应用程序中看到过类似功能(不记得名字了),在文本框下方弹出一个小型弹出窗口,显示以下内容:

从消息自动填充代码

我想在我的应用程序中添加类似的功能。根据文档的建议,通过添加自动填充提示并将自动填充重要性设置为实现此行为。我尝试了它们两种,但都没有起作用。

        <com.google.android.material.textfield.TextInputLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@id/tv_login"
        android:layout_marginTop="@dimen/x60"
        android:id="@+id/pin"
        app:errorEnabled="true"
        style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
        android:layout_centerHorizontal="true">
        <com.google.android.material.textfield.TextInputEditText
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:hint="PIN"
            android:drawablePadding="@dimen/x16"
            android:inputType="number"
            android:maxLength="6"
            android:id="@+id/et_pin"
            android:importantForAutofill="yes"
            android:autofillHints=".AUTOFILL_HINT_SMS_OTP"
            android:drawableStart="@drawable/ic_pin"/>
    </com.google.android.material.textfield.TextInputLayout>

我希望在我的应用程序中获得这种类型的东西。

这里输入图片描述


1
如果您已收到OTP,那么为什么建议用户添加OTP呢?我的意思是,不要要求用户设置OTP,而是自动设置OTP。 - Rajendra Mahato
应用程序无法自动从用户短信中获取OTP,我想要一些机制来解决这个问题。我没有使用Firebase。短信是使用Twillio从我的服务器发送的。而且Android不允许读取用户短信以验证OTP。 - Attique Ur Rehman
Twilio是否提供一些成功或接收侦听器(回调)? - Rajendra Mahato
5个回答

5

1.在xml中的edittext中添加以下内容:

 android:autofillHints="smsOTPCode"
 android:importantForAutofill="yes"

2.通过导航到设置 > Google > 自动填充 > 短信验证码 > 自动填充服务来启用自动填充服务。

注意: 此解决方案适用于Android 8及以上版本。


2

有两种处理方法:

  1. SMS读取权限(不建议使用)

可以创建一个弹出窗口,当用户触摸它时,给予权限。

  1. SMS检索API(建议使用)

可以设置SMS检索API(查看此链接),并在用户触摸它时创建一个弹出窗口,然后填充文本视图。


上面分享的图片中弹出的窗口是由Android操作系统显示的,我想知道背后的技巧。 - Attique Ur Rehman
如果您指的是当前消息应用程序的图标,您可以从包管理器中获取它们,并按mime_type过滤它们,例如“vnd.android-dir/mms-sms”,并找到当前活动的消息应用程序。请查看此链接https://dev59.com/KG_Xa4cB1Zd3GeqP7f8m - saeedata
看这个链接,兄弟:https://stackoverflow.com/questions/8711940/how-to-open-and-show-phones-message-inbox-programmatically - saeedata
我认为你可以通过合并上述两个链接的代码以及短信接收器API来获得答案。 - saeedata
1
是的,我找到了一种更准确的方法,即合并SMS Retriever API和Twillio来实现所需的行为。这种方法不需要SMS读取权限。https://www.twilio.com/docs/sms/app-verification#verify-android-phone-numbers-with-twilio - Attique Ur Rehman
有没有类似的方法可以从Gmail获取OTP? - undefined

1

-2

经过很多搜索并且对此失去希望之后,我发现设置自动填充为重要选项其实非常简单。

编辑文本代码

<EditText
    android:id="@+id/otp"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:textSize="18sp"
    android:layout_margin="30dp"
    android:textColor="@color/black"
    android:autofillHints="smsOTPCode"
    android:importantForAutofill="yes"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toBottomOf="@id/status" />

而且我也在代码中设置了自动填充提示

lateinit var statusView: TextView
lateinit var otpView: TextView
lateinit var acceptView: RadioButton
lateinit var rejectView: RadioButton
override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)
    statusView = findViewById<TextView>(R.id.status)
    otpView = findViewById<TextView>(R.id.otp)
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        otpView.setAutofillHints(AUTOFILL_HINT_SMS_OTP)
    }
    acceptView = findViewById<RadioButton>(R.id.accept)
    rejectView = findViewById<RadioButton>(R.id.reject)
    startListeningForSms(this,this)
    Log.e(javaClass.simpleName, AppSignatureHelper(this).appSignatures.toString())
}
fun startListeningSms(
    context: Context,
    lifecycleOwner: LifecycleOwner
) {
    val client = SmsRetriever.getClient(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.
    val task: Task<Void> = 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(OnSuccessListener<Void?> {
        // Successfully started retriever, expect broadcast intent
    })

    task.addOnFailureListener(OnFailureListener {
        // Failed to start retriever, inspect Exception for more details
    })
}

我不会分享整个活动代码,只分享与自动填充相关的代码。输入图像描述

可以在这里找到AppSignatureHelper: https://github.com/googlearchive/android-credentials/blob/master/sms-verification/android/app/src/main/java/com/google/samples/smartlock/sms_verify/AppSignatureHelper.java

自动填充库可以添加到依赖项中。

implementation "androidx.autofill:autofill:1.1.0"

这段代码不完整: startListeningForSms函数是什么? AUTOFILL_HINT_SMS_OTP常量是什么? - Dantalian
AUTOFILL_HINT_SMS_OTP 可在 autofill 库中找到。实现 "androidx.autofill:autofill:1.1.0"。 - Islam Assem

-2
Burak Dizlek的解决方案对我无效。
相反 - 我已经测试过了 - 在这里使用Android SMS Retriever https://developers.google.com/identity/sms-retriever/overview 通过SMS Retriever API,您可以在Android应用程序中自动执行基于短信的用户验证,而无需用户手动输入验证代码,也无需任何额外的应用程序权限。
编码。
  1. 使用keytool或Helper获取您的应用哈希值,请参考https://github.com/shishirthedev/sms-verification-api-android/blob/master/app/src/main/java/com/shishirthedev/smsretriverapi/AppSignatureHashHelper.kt

  2. 启动SmsRetrieverClient

    SmsRetrieverClient client = SmsRetriever.getClient(context);
    Task<Void> task = client.startSmsRetriever()
    
  3. 创建等待SmsRetriever.SMS_RETRIEVED_ACTION的广播接收器

    public class MySMSBroadcastReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
     Log.d(TAG, "onReceive");
     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);
            case CommonStatusCodes.TIMEOUT: 
                 // 处理超时
    
  4. 在Activity的onResume中注册此广播接收器

     intentFilter = new IntentFilter(SmsRetriever.SMS_RETRIEVED_ACTION);
     mySMSBroadcastReceiver = new MySMSBroadcastReceiver();
    
     protected void onResume() {  
        super.onResume();
        registerReceiver(mySMSBroadcastReceiver, intentFilter, RECEIVER_EXPORTED);
      }
    
然后,一旦你发送短信(你不需要服务器),你的应用程序将在BR内接收到它,然后你可以处理它。
onOTPReceived: Your code is: 123456                                                                                                
504w8vEgbb8

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接