禁用Android O中应用程序的自动填充服务

46

Android O具有支持字段自动填充的功能。是否有任何方法可以禁用特定应用程序的此功能?也就是说,我想强制我的应用程序不使用自动填充服务。

这可能吗?

要阻止整个活动的自动填充,请在活动的onCreate()中使用以下内容:

getWindow()
  .getDecorView()
  .setImportantForAutofill(View.IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS);

有比这更好的方法吗?

6
自动填充可能会导致一个非常难以捉摸的崩溃,当用户将焦点更改到 TextInputLayout 中先前填充的 textInputEditText 时,我们会遇到这个问题:java.lang.NullPointerException: 尝试在空对象引用上调用虚拟方法 'void android.view.View.getBoundsOnScreen(android.graphics.Rect)' - Justin
发现了一个 bug https://issuetracker.google.com/issues/67675432,请给它点个赞。 - Viktor Yakunin
创建一个活动类,用于其他所有活动继承,并将此代码添加到其中。 - Patrick
@Justin,这个问题已在Android 8.1上得到修复,您能否在8.1上进行测试? - Prags
1
我相信如果应用程序尝试使用超过1MB的数据填充像EditText这样的控件,这可能也会导致TransactionTooLargeException异常。这超出了Bundle的限制。请参阅AutoFillManager的源代码。解决方法是在View的xml中包含“android:importantForAutofill =” noExcludeDescendants“。” - fattire
10个回答

30

目前还没有一种直接的方法可以禁用整个应用程序的自动填充,因为自动填充功能是视图特定的。

您仍然可以尝试这种方式,并在各处调用BaseActivity。

public class BaseActivity extends AppCompatActivity {

    @Override
    public void onCreate(Bundle savedInstanceState) {
       super.onCreate(savedInstanceState);
       disableAutofill();
    }

    @TargetApi(Build.VERSION_CODES.O)
    private void disableAutofill() { 
        getWindow().getDecorView().setImportantForAutofill(View.IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS);
    }
}
你也可以通过这种方式强制请求自动填充。
public void forceAutofill() {
    AutofillManager afm = context.getSystemService(AutofillManager.class);
    if (afm != null) {
        afm.requestAutofill();
    }
}

注意:目前自动填充功能仅适用于API 26 Android Oreo 8.0

希望这能有所帮助!


非常好!我将结合 Android 8.1 的 API 检查来实现此答案;在 8.0 中禁用有缺陷的自动填充,但在 8.1+ 中允许它。否则,我将花费超过一个小时在整个应用程序中放置 TextInputLayout 的提示。 - Someone Somewhere
2
如果 (Build.VERSION.SDK_INT == Build.VERSION_CODES.O) { getWindow().getDecorView().setImportantForAutofill(View.IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS); } - Someone Somewhere
这个答案在模拟器(API 26)上不起作用:java.lang.NullPointerException: Attempt to invoke virtual method 'void android.view.View.getBoundsOnScreen(android.graphics.Rect)' on a null object reference - Someone Somewhere
我在安卓10上使用getDecorView().setImportantForAutofill(View.IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS)没有任何效果。 - Alexey Ozerov

26

我认为被接受的答案是不正确的:

所以我有自己的类,它是 继承自 android.support.v7.widget.AppCompatEditText,我所做的就是用下面的值重写了以下方法:

@Override
public int getAutofillType() {
    return AUTOFILL_TYPE_NONE;
}

没有其他解决方案有效,甚至包括android:importantForAutofill="no"。

getAutofillType()来自View类,因此它也适用于TextInputEditText等其他类!


3
目前这是唯一可行的解决方案,对于TextInputEditText也适用且效果良好! - Viktor Yakunin
1
添加了代码示例以展示存储库 https://github.com/BukT0p/AutofillBug - Viktor Yakunin
1
如果您使用任何第三方库与视觉组件,而这些组件不扩展您的基类,则此方法将无法正常工作。 - Leo supports Monica Cellio
我确认这个解决方案有效,而在EditText上设置android:importantForAutofill="no"android:importantForAutofill="noExcludeDescendants"无效。已在Oreo 8.0(API级别26)和Android Pie(API级别28)模拟器上测试。 - Carmen
1
这是2022年唯一可行的解决方案。 - Abhishek Bansal
显示剩余2条评论

12

我也遇到了这个问题。原因是在TextInputLayout中嵌套的EditText上设置了提示文本。

经过一些研究,我在2017年6月发布的26.0.0 Beta 2版本说明中找到了一个有价值的信息。 Andorid Support Release Notes June 2017

TextInputLayout必须在onProvideAutofillStructure()上设置提示信息。

这使我尝试在TextInputLayout上设置提示,取代了嵌套的EditText上的提示。

这样对我解决了崩溃问题。 例如:

            <android.support.design.widget.TextInputLayout
                android:id="@+id/textInputLayout"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:hint="Some Hint Text"
                android.support.design:hintAnimationEnabled="true"
                android.support.design:hintEnabled="true"
                android.support.design:layout_marginTop="16dp">

                <android.support.design.widget.TextInputEditText
                    android:id="@+id/editText"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"/>

            </android.support.design.widget.TextInputLayout>

它只解决了TextInputEditText的错误,我使用你的解决方案更新了我的repo(github.com/BukT0p/AutofillBug)。但是AutoCompleteTextView也有类似的错误。在API 27中,自动填充以同步模式工作,会导致UI冻结和延迟。因此,也许最好禁用那些肯定不需要填充的视图的自动填充功能。 - Viktor Yakunin
即使我们在这个线程中使用其他建议来禁用自动填充,用户仍然可以长按视图并从上下文菜单中选择自动填充。我观察到,在某些情况下,您将被告知无法自动填充视图,但我尚未找到该标志。我已经看到了一些解决方案,涉及返回自动填充选项为NONE的自定义视图,但这对于所有实现都不可行。 - Azethoth
这个解决方案对我有效。用户仍然可以长按输入字段并选择自动填充,但它不会崩溃 - 它只是无动于衷。谢谢。 - Tom Wayne
这种方法是可行的,但是因为我的应用程序有大量活动而变得非常麻烦。请注意,我没有使用以 android.support.design 开头的行,只需移动提示参数即可。 - Someone Somewhere

4
似乎存在一个需要修复的漏洞:https://issuetracker.google.com/issues/67675432
同时,现在的解决方法是禁用整个项目的自动填充功能。您可以在values-v26/styles.xml文件中添加以下样式或者编辑您的BaseEditTextStyle(如果您正在为EditText视图使用特定样式)。
<style name="App_EditTextStyle" parent="@android:style/Widget.EditText">
<item name="android:importantForAutofill">noExcludeDescendants</item>
</style>

values-v26/themes.xml文件中,您可以简单地添加以下项目到应用程序中使用的默认主题中:editTextStyleandroid:editTextStyle,如下所示:

<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
...
<item name="android:editTextStyle">@style/App_EditTextStyle</item>
<item name="editTextStyle">@style/App_EditTextStyle</item>
</style>

这样,您就可以将此更改应用于 所有 EditText,而无需更改布局文件或活动(以后在修复错误时可以轻松删除它)。


3

这有可能吗?

我不知道。当然,没有任何文档可以证明。

是否有比这更好的方法?

我不知道有什么更好的方法。


这个问题在Android 8.1上已经修复了,你能否用8.1版本进行测试? - Prags
2
android:importantForAutofill="no" 可能吗? - Appnweb31
1
@appnweb31web:这是用于视图的属性,而不是用于清单文件中的<application> - CommonsWare

2
在您的EditText属性中添加android:importantForAutofill="no"。这应该是一个临时解决方案,仅适用于api 26+。

1
这与其他答案有何不同? - Viktor Yakunin

2

创建自定义EditText样式,并将android:importantForAutofill设置为no

<style name="EditTextStyleWithoutAutoFill" parent="Widget.AppCompat.EditText">
    <item name="android:importantForAutofill">no</item>
</style>

然后在你的活动主题中为editTextStyle设置这个样式。

<item name="android:editTextStyle">@style/EditTextStyleWithoutAutoFill</item>

importantForAutofill 在这里有文档记录:https://developer.android.com/guide/topics/text/testautofill.html#trigger_autofill_in_your_app - SoftWyer
我会尝试下一步的方法,但是将其与 res/values-v26/styles.xml 合并,以仅影响 Android 8.0,而不是 8.1(我无法相信 Google 发布了如此巨大的错误!) - Someone Somewhere

2
在我的情况下,我们的应用程序目标SDK版本为21,但更新的设备(26+)仍会出现自动填充。如果应用在多人共享的设备上运行,则是一个相当大的问题。使用只有 android:importantForAutofill="no" 是无法解决我的问题的。
我找到的唯一可行的解决方案是:
<EditText
    android:importantForAutofill="no"
    tools:targetApi="o"
    android:autofillHints="AUTOFILL_HINT_SMS_OTP" ...

我添加 android:autofillHints="AUTOFILL_HINT_SMS_OTP" 的原因是,如果你长按 EditText,它仍然会弹出自动填充。基本上,我告诉了字段的自动填充,它正在等待永远不会发送的短信。这有点像一个 hack,我知道...
注意:如果还没有,您可能需要将 xmlns:tools="http://schemas.android.com/tools" 添加到您的模式中。

对我来说可以。它在较低的API上会给你带来问题吗? - Soy César Mora
我无法对Lollipop以下的版本进行发言,因为我没有测试过。但是对于从Lollipop到最新版本,自发布以来我没有遇到任何问题。 - Rob C

1
我有同样的问题,与API 28+和禁用Autofill有关。对我来说,唯一的解决方案是禁用我的视图的长按功能。
                <com.google.android.material.textfield.TextInputEditText
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:longClickable="false"
                    android:text="@={model.emailAdress}"/>

0

2
这个答案与问题无关。但它确实与问题的第一条评论有关。 - CommonsWare

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