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

问题描述

我在一些应用程序中看到过(不记得名字),在文本框下,显示一个小弹出窗口

来自消息的自动填充代码

我想为我的应用添加类似的功能。如 documentation 中所建议,添加自动填充提示并设置自动填充重要性以实现此行为。我都试过,但都没有奏效。 我试过以下

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

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

enter image description here

解决方法

有两种处理方法

  1. 短信读取权限(不推荐)

您可以创建一个弹出窗口并在用户触摸它时授予权限。

  1. 短信检索 API(推荐)

您可以设置短信检索 API (look at this link) 并在用户触摸时创建一个弹出窗口然后填充文本视图

,

您应该有一个 BroadcastReceiver 来接收短信并检测您的模板并从中提取您的代码。

这是我接收短信的实现。短信可能会分成很多条,注意它是如何处理的。还要检查 android:priority 属性。

public class MySmsReceiver extends BroadcastReceiver {

    private static final String SMS_RECEIVED = "android.provider.Telephony.SMS_RECEIVED";

    @Override
    public void onReceive(Context context,Intent intent) {
        if (intent.getAction().equals(SMS_RECEIVED)) {
            Bundle bundle = intent.getExtras();
            if (bundle != null) {
                // get sms objects
                Object[] pdus = (Object[]) bundle.get("pdus");
                if (pdus.length == 0) {
                    return;
                }
                // large message might be broken into many
                SmsMessage[] messages = new SmsMessage[pdus.length];
                StringBuilder sb = new StringBuilder();
                for (int i = 0; i < pdus.length; i++) {
                    messages[i] = SmsMessage.createFromPdu((byte[]) pdus[i]);
                    sb.append(messages[i].getMessageBody());
                }
                String sender = messages[0].getOriginatingAddress();
                String message = sb.toString();
                
                //Implement this method as you wish
                extractCodeAndSendToListeners(message); 


                // prevent any other broadcast receivers from receiving broadcast
                // abortBroadcast();
            }
        }
    }
}

AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.sms">

    <uses-permission android:name="android.permission.RECEIVE_SMS" />

    <application android:icon="@drawable/icon" android:label="@string/app_name">
        <activity
            android:name=".SmsActivity"
            android:label="@string/app_name">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

        <receiver android:name="com.example.sms.MySmsReceiver" android:enabled="true">
            <intent-filter android:priority="2147483647">
                <action android:name="android.provider.Telephony.SMS_RECEIVED" />
            </intent-filter>
        </receiver>

    </application>
</manifest>

一些注意事项:如果您在 xml 中声明您的接收器,那么无论您的应用程序是否已启动,系统都可以使用您的接收器。由于有关收到的短信的 Android 1.6 通知作为有序广播传递,您可以使用 android:priority 属性告诉系统首先将短信发送到您的应用程序(您也可以调用 abortBroadcast() 以便其他应用程序不会收到短信,例如本机短信应用程序)。不要忘记广播接收器有大约 10 秒的时间来执行它的操作,否则它可以在完成其工作之前提前终止。

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...