【问题标题】:How to add auto fill suggestion for otp如何为 otp 添加自动填充建议
【发布时间】:2021-04-08 17:07:55
【问题描述】:

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

消息中的自动填充代码

我想为我的应用添加类似的功能。正如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>

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

【问题讨论】:

  • 如果您收到了 OTP,那么您为什么建议用户添加 OTP。我的意思不是要求用户设置 otp,而是自动设置 otp。
  • 应用程序无法从用户消息中获取 otp auto,我需要一些机制。我没有使用火力基地。 SMS 是使用 twillio 从我的服务器发送的。 Android 不允许读取用户短信来验证 otp。
  • Twillio 是否提供了一些关于成功或接收监听器(回调?

标签: android message autofill one-time-password


【解决方案1】:

有两种方法可以解决这个问题

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

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

  1. 短信检索API(推荐)

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

【讨论】:

  • 以上共享图片中的弹窗是android OS如何显示的,我想知道它背后的技巧
  • 如果您指的是当前消息应用程序的图标,您可以从包管理器中获取它并通过 mime_type 过滤它们,例如“vnd.android-dir/mms-sms”并找到当前活动的消息应用程序.看看这个链接stackoverflow.com/questions/15567957/…
  • 看看这个链接兄弟,stackoverflow.com/questions/8711940/…
  • 我认为您可以通过合并上面两个链接的代码以及 Sms retiver API 来获得答案
  • 是的,我找到了一种更准确的方法,将 sms retiver api 和 twillio 合并以实现所需的行为。这种方法不需要 SMS 读取权限。 twilio.com/docs/sms/…
【解决方案2】:

您是否在 Android 设置中启用了自动填充功能?

  • 首先选择一个自动填充服务,例如谷歌。
  • 设置 -> 谷歌 -> 自动填充 -> 短信验证码 -> 切换到启用

见:https://www.techrepublic.com/article/how-to-enable-sms-verification-code-autofill-in-android/

【讨论】:

    【解决方案3】:

    您应该有一个 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 秒的时间来执行它的操作,否则它可能会在完成工作之前被提前终止。

    【讨论】:

    • 谷歌现在从不推荐,谷歌在发布应用时询问是否有sms_read权限。 Google 不允许仅通过短信验证帐户的 sms_read 权限
    • 您可以向google描述您使用此权限的原因
    • support.google.com/googleplay/android-developer/answer/10208820 访问此链接,他们无论如何都不允许这样做
    • 不是任何原因:You should only access Call Log or SMS permissions when your app falls within permitted uses and only to enable your app’s critical core functionality. Core functionality is defined as the main purpose of the app. This may comprise of a set of core features, which must all be prominently documented and promoted in the app's description. Without the core feature(s), the app is "broken" or rendered unusable.
    • 我知道 Play 商店中的一些应用程序使用此代码来获取激活码
    【解决方案4】:

    经过大量搜索并失去希望后,我发现它非常简单,只需将其设置为自动填充重要

    编辑文本代码

    <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 常量是什么?
    • AUTOFILL_HINT_SMS_OTP 在 auofill 库实现“androidx.autofill:autofill:1.1.0”中找到
    猜你喜欢
    • 2018-08-10
    • 2021-04-10
    • 2018-03-30
    • 2013-02-10
    • 2021-12-31
    • 1970-01-01
    • 2019-10-09
    • 2017-04-21
    • 2016-10-04
    相关资源
    最近更新 更多