天道酬勤,学无止境

How to disable the new Autofill feature from Android Oreo for espresso tests

Running tests on android devices with sdk 26 causes them to fail because of the new Autofill feature that hides the fields when espresso are trying to click them.

Im running my tests on firebase test lab so I cannot disable them manually on my tests devices.

Some images:

1. Password is visible before clicking username field.

2. After clicking username field password field is hidden by this Autofill dialog:

3. After login it shows another Fill dialog:

Espresso cant click now password field since the autofill dialog is hiding my field and fail.

Using AutofillManager#disableAutofillServices() only disabled the #2. dialog but #3. is still there.

How to disable Autofill on test devices?

评论

adb shell pm disable com.google.android.gms/com.google.android.gms.autofill.service.AutofillService

This should disable the autofill service. It is same as turning off autofill service in the system settings manually. It at least worked on the emulator. But this needs root access.

Another way to disable the autofill service is to change the autofill_service settings.

adb shell settings put secure autofill_service null

Based on documentation, you can disable Autofill services using AutofillManager#disableAutofillServices() API:

If the app calling this API has enabled autofill services they will be disabled.

Usage:


    val autofillManager: AutofillManager = context.getSystemService(AutofillManager::class.java)
    autofillManager.disableAutofillServices()

You can do this in @Before step of your test.

An alternative code organisation based on @Alan K's solution.

Create the class DisableAutofillAction:

public class DisableAutofillAction implements ViewAction {

    @Override
    public Matcher<View> getConstraints() {
        return Matchers.any(View.class);
    }

    @Override
    public String getDescription() {
        return "Dismissing autofill picker";
    }

    @Override
    public void perform(UiController uiController, View view) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {

            AutofillManager autofillManager = view.getContext().getSystemService(AutofillManager.class);

            if (autofillManager != null) {
                autofillManager.cancel();
            }
        }
    }
}

And, in your code when you need to disable AutoFill for editTextPassword...

editTextPassword.perform(..., ViewActions.closeSoftKeyboard(), DisableAutofillAction())

The following snippet can be used to ignore the new android suggestions:

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

I've had luck disabling autofill during Espresso tests with custom ViewActions applied whenever text is entered.

            .onView(...)
            .perform(
                    new ViewAction() {
                        @Override
                        public Matcher<View> getConstraints() {
                            return Matchers.any(View.class);
                        }

                        @Override
                        public String getDescription() {
                            return "Marking view not important for autofill";
                        }

                        @Override
                        public void perform(UiController uiController, View view) {
                            // Required to disable autofill suggestions during tests on API 26+
                            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                                view.setImportantForAutofill(View.IMPORTANT_FOR_AUTOFILL_NO);
                            }
                        }
                    })
            .perform(click())
            .perform(clearText())
            .perform(typeText(textToType))
            .perform(
                    new ViewAction() {
                        @Override
                        public Matcher<View> getConstraints() {
                            return Matchers.any(View.class);
                        }

                        @Override
                        public String getDescription() {
                            return "Dismissing autofill picker";
                        }

                        @Override
                        public void perform(UiController uiController, View view) {
                            // Required to dismiss the autofill picker during tests on API 26+
                            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                                AutofillManager autofillManager =
                                        view.getContext()
                                                .getSystemService(AutofillManager.class);
                                if (autofillManager != null) autofillManager.cancel();
                            }
                        }
                    });

Disable autofill when testing. Define a TestRunner class in gradle

defaultConfig {
    testInstrumentationRunner "com.cover.android.TestRunner"
}

then

public class TestRunner extends AndroidJUnitRunner {

@Override
public void onCreate(Bundle arguments) {
    super.onCreate(arguments);
    CustomEditText.TESTING = TRUE;
    }

then use a custom version of EditText

public class CustomEditText extends AppCompatEditText {
public static boolean TESTING = false;
public CustomEditText(Context context) {
    super(context);
}

@Override
public int getAutofillType() {
    return TESTING? AUTOFILL_TYPE_NONE : super.getAutofillType();
}

According To Documentation : when the view is focused on and is part of a dataset. The application can be notified when the affordance is shown by registering an AutofillManager.AutofillCallback through registerCallback(AutofillCallback). When the user selects a dataset from the affordance, all views present in the dataset are autofilled, through calls to autofill(AutofillValue) or autofill(SparseArray).

The context is then finished when one of the following occurs:

  1. commit() is called or all savable views are gone.
  2. cancel() is called.

It is safe to call into its methods from any thread.

Instances of this class must be obtained using Context.getSystemService(Class) with the argument AutofillManager.class.

Use : disableAutofillServices() method to disible the service .

Within your device, go to this route Settings > System > Languages & input > Advanced > AutoFill Service and cancel it

受限制的 HTML

  • 允许的HTML标签:<a href hreflang> <em> <strong> <cite> <blockquote cite> <code> <ul type> <ol start type> <li> <dl> <dt> <dd> <h2 id> <h3 id> <h4 id> <h5 id> <h6 id>
  • 自动断行和分段。
  • 网页和电子邮件地址自动转换为链接。

相关推荐
  • 禁用应用程序的Android O自动填充服务(Disabling Android O auto-fill service for an application)
    问题 Android O具有支持字段自动填充的功能。 有什么方法可以针对特定应用程序禁用它。 那就是我要强制我的应用程序不要使用自动填充服务。 是否可以 ? 要阻止整个活动的自动填充,请在活动的onCreate()中使用此功能: getWindow() .getDecorView() .setImportantForAutofill(View.IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS); 有没有比这更好的方法了? 回答1 是否可以 ? 不是我知道的。 当然,没有任何文件记录。 有没有比这更好的方法了? 不是我知道的。 回答2 当前,没有直接的方法可以禁用整个应用程序的自动填充功能,因为自动填充功能是特定于视图的。 您仍然可以尝试这种方式,并在任何地方调用BaseActivity。 public class BaseActivity extends AppCompatActivity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); disableAutofill(); } @TargetApi(Build.VERSION_CODES.O) private void
  • Android Oreo: what should I do to publish my app as an Autofill service provider?
    I'm an independent developer of a password manager app. What should I do, or what should I implement (interface/API/Service), to make my app an Autofill service provider (in a device with Android Oreo API >= 26)? I have read all kinds of related documentation, but I can't understand how to do this. Am I missing something? At the moment I see that only well-known password managers support this feature: Any hints are welcome.
  • Android UI tests with Espresso + MockK crash with SIGSEGV on emulators, fine on physical devices
    I have just started using MockK to mock all the Repositories / Services logic in an MVP-based app for UI tests. I have some UI tests running a login activity where the Espresso inputs logins and passwords and using MockK I can fake various situation where the login fails or not. All services & repositories are standard Kotlin object, so I am using mockkobject and every/coEvery to override and handle login requests & tasks. On my physical devices, there are no issues with the tests at all, but as soon as I tried to run them on a emulator running Android P+ with recommended image, they
  • Android Crash on Android 8.0 Oreo: SecurityException: Permission Denial: null asks to run as user 450 but is calling from user 0
    I upgrade my phone to Android Oreo. When I'm running my app on this device. My app crashes. While it's running well on Android 7 and lower devices. This is the log: E/AndroidRuntime: FATAL EXCEPTION: main Process: com.test.test, PID: 28271 java.lang.SecurityException: Permission Denial: null asks to run as user 450 but is calling from user 0; this requires android.permission.INTERACT_ACROSS_USERS_FULL or android.permission.INTERACT_ACROSS_USERS at android.os.Parcel.readException(Parcel.java:1942) at android.os.Parcel.readException(Parcel.java:1888) at android.view.autofill.IAutoFillManager
  • 如何检测Android应用程序是否正在使用Espresso运行UI测试(How to detect whether android app is running UI test with Espresso)
    问题 我正在编写一些针对Android的Espresso测试。 我正在运行以下问题: 为了使某个测试用例正常运行,我需要禁用该应用程序中的某些功能。 因此,在我的应用中,我需要检测我是否正在运行Espresso测试,以便可以将其禁用。 但是,我不想使用BuildConfig.DEBUG ,因为我不想在调试版本中禁用这些功能。 另外,我想避免创建新的buildConfig,以免创建太多的构建变体(我们已经定义了很多样式)。 我在寻找一种定义buildConfigField进行测试的方法,但在Google上找不到任何引用。 回答1 结合CommonsWare的评论。 这是我的解决方案: 我定义了一个AtomicBoolean变量和一个函数来检查它是否正在运行测试: private AtomicBoolean isRunningTest; public synchronized boolean isRunningTest () { if (null == isRunningTest) { boolean istest; try { Class.forName ("myApp.package.name.test.class.name"); istest = true; } catch (ClassNotFoundException e) { istest = false; }
  • How to detect whether android app is running UI test with Espresso
    I am writing some Espresso tests for Android. I am running in the the following problem: In order for a certain test case to run properly, I need to disable some features in the app. Therefore, in my app, I need to detect whether I am running Espresso test so that I can disable it. However, I don't want to use BuildConfig.DEBUG to because I don't want those features to be disabled in a debug build. Also, I would like to avoid creating a new buildConfig to avoid too many build variants to be created (we already have a lot of flavors defined). I was looking for a way to define buildConfigField
  • Oreo BroadcastReceiver收到的SMS无效(Oreo BroadcastReceiver SMS Received not working)
    问题 我正在使用的应用程序允许用户允许该应用程序读取确认SMS的内容,以自行输入验证码。 对于使用早于Oreo(API 26)的OS的所有设备,BroadcastReceiver的实现均可正常运行,并允许正确接收SMS。 通过这种实现,我的意思是将接收器对象放置在AndroidManifest中。 <receiver android:name=".SmsReceiver"> <intent-filter> <action android:name="android.provider.Telephony.SMS_RECEIVED"/> </intent-filter> </receiver> 但是,从奥利奥(Oreo)开始,必须在适当的上下文中显式注册BroadcastReceivers。 我已经实现了如下: if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { smsReceiver = new SmsReceiver(); IntentFilter intentFilter = new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION); intentFilter.addAction(Telephony.Sms.Intents.DATA_SMS_RECEIVED
  • 在Chrome中禁用表单自动填充功能,而无需禁用自动完成功能(Disable form autofill in Chrome without disabling autocomplete [duplicate])
    问题 这个问题已经在这里有了答案: 禁用Chrome自动填充(68个答案) 3年前关闭。 我们如何在某些<input>上禁用Chrome的自动填充功能,以防止它们在页面加载时自动填充? 同时,我需要保持启用自动完成功能,因此用户仍然可以通过单击输入或输入内容来查看建议列表。 能做到吗? 编辑:如果您觉得有必要,可以随意使用普通的Javascript或jQuery,或者您觉得这会使您的解决方案更简单。 回答1 这是您想要的魔术: autocomplete="new-password" Chrome会故意忽略autocomplete="off"和autocomplete="false" 。 但是,他们将new-password作为特殊子句放入,以阻止自动填写新密码形式。 我在密码输入中输入了以上一行,现在我可以在表单中编辑其他字段,并且密码不会自动填写。 回答2 有点晚了,但这是我的傻瓜解决方案,对于诸如用户必须输入新密码的注册/注册页面之类的页面很有用。 <form method="post"> <input type="text" name="fname" id="firstname" x-autocompletetype="given-name" autocomplete="on"> <input type="text" name="lname" id="lastname" x
  • 在运行Espresso测试时如何禁用代码中的动画(How to disable animations in code when running Espresso tests)
    问题 在运行Espresso测试时,是否有人设法通过代码禁用动画? 我一直在尝试遵循此网页中的说明(从此处链接到): https://code.google.com/p/android-test-kit/wiki/DisablingAnimations 不幸的是,它似乎不起作用,因为我一直看到此权限错误: 04-27 15:48:28.694 303-342/system_process W/PackageManager﹕ Not granting permission android.permission.SET_ANIMATION_SCALE to package com.cookbrite.dev (protectionLevel=50 flags=0x18be46) 我真的希望避免重新配置设备/仿真器。 我们经常在本地运行单独的测试,如果我不得不继续切换设置,这将使我很烦。 我注意到其他一些开发人员抱怨这行不通,所以我可能并不孤单: https://groups.google.com/forum/#!msg/android-test-kit-discuss/TCil7kMQRTM/QK1qCjzM6KQJ 回答1 我正在为每种动画类型执行以下三个命令,它们正在为我工​​作: adb shell settings put global window_animation
  • 自动化测试-Appium-Desired Capabilities参数详解
    分类 定义与说明General Capabilities(通用功能)Update settings Android OnlyUIAutomator 1UIAutomator2 OnlyEspresso Only iOS OnlyiOS Only, using XCUITestSafaridriver OnlyGeckodriver OnlyMacDriver OnlyMac2Driver OnlyYou.i Engine OnlyWinAppDriver OnlyFlutter driver only 定义与说明 Desired capabilities是编码在JSON对象中的键和值在请求新的自动化会话时由Appium客户端发送到服务器用来告诉Appium 驱动程序做哪些特定的测试可在WebDriver测试中编写脚本可在Appium服务器GUI中设置可在设置中添加项目名和值,Appium中自带JSON转换类似Jmeter、Postman、Fiddler、Web等里面的参数请求,这种请求在这里是面向iOS和Android移动端的,有兴趣的小伙伴都去了解一下 { "platformName": "iOS", "platformVersion": "11.0", "deviceName": "iPhone 7", "automationName": "XCUITest", "app":
  • 在用户名和密码上禁用Safari自动填充(Disabling Safari autofill on usernames and passwords)
    问题 您可能已经知道,无论是否设置autocomplete="off" ,Safari都有一个讨厌的自动填充错误,该错误会在其中填充电子邮件,用户名和密码字段。 这是一个基本形式: <form action="/" method="post"> <p> <label>E-mail</label> <input type="text" name="email" value="" /> </p> <p> <label>Password</label> <input type="password" name="password" value="" /> </p> </form> ... Safari会自动在页面加载时自动填充这些字段,做得好! 如果将autocomplete="off"放入字段和/或form元素,则Safari仍会自动填充这些字段: <form action="/" method="post" autocomplete="off"> <p> <label>E-mail</label> <input type="text" name="email" value="" autocomplete="off" /> </p> <p> <label>Password</label> <input type="password" name="password" value=""
  • Android Espresso,测试前唤醒设备。 如何使用自定义清单进行测试?(Android Espresso, Wake up device before test. How to use a custom manifest for test?)
    问题 我一直在用android的新espresso框架编写测试,发现它运行良好。 一件令人烦恼的事情(不是特浓咖啡)是我必须确保屏幕醒着并解锁才能运行测试。 我(通过各种来源)找到了一种解决方法,但是我不确定将其集成的最佳方法。 这就是我所做的,在“家庭”活动中,我有以下代码: Home.class: public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); /************ Put this in a conditional for a test version ***********/ KeyguardManager km = (KeyguardManager) getSystemService(Context.KEYGUARD_SERVICE); KeyguardManager.KeyguardLock keyguardLock = km.newKeyguardLock("TAG"); keyguardLock.disableKeyguard(); getWindow().addFlags(WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON); } 另外,您需要添加以下权限: <uses-permission
  • 拒绝权限:这需要android.permission.INTERACT_ACROSS_USERS_FULL(Permission Denial: this requires android.permission.INTERACT_ACROSS_USERS_FULL)
    问题 我在Android中使用sqlite db遇到问题。 但是,当我在Internet上进行快速研究时,我怀疑问题与sqlite无关,而与系统用户有关。 我的应用程序未被识别为访问数据库功能的授权用户。 我试图在堆栈溢出中应用可能的建议解决方案,但没有一个起作用。 每次尝试使用数据库功能时,我都会遇到此LogCat。 12-14 02:35:17.721 2953-3355/? E/DatabaseUtils﹕ Writing exception to parcel java.lang.SecurityException: Permission Denial: get/set setting for user asks to run as user -2 but is calling from user 0; this requires android.permission.INTERACT_ACROSS_USERS_FULL at com.android.server.am.ActivityManagerService.handleIncomingUser(ActivityManagerService.java:13082) at android.app.ActivityManager.handleIncomingUser(ActivityManager.java:2038)
  • iOS 11禁用密码自动填充附件视图选项?(iOS 11 disable password autofill accessory view option?)
    问题 到目前为止,我想退出iOS 11提供的新选项,即在应用程序中建议输入密码。 当我在iOS 11上运行该应用程序时,我在键盘上方获得了自动填充选项,而我的用户名和密码文本字段甚至都没有显示。 因此,我的问题是,如何才能一起禁用新的密码自动填充功能,以使键盘上的键完全不显示,并且总体行为与iOS 11之前的版本相同? 回答1 iOS 11和12和13-Swift 4.2和5 (已更新): if #available(iOS 12, *) { // iOS 12 & 13: Not the best solution, but it works. passwordTextField.textContentType = .oneTimeCode } else { // iOS 11: Disables the autofill accessory view. // For more information see the explanation below. emailTextField.textContentType = .init(rawValue: "") passwordTextField.textContentType = .init(rawValue: "") } iOS 11说明: 确保像这样设置所有UITextField对象。 例如
  • Disable browsers Form inputs prefill/autofill feature when hitting “back” button
    I want to "prevent browsers from prefilling form inputs when hitting the "back" button". Indeed, I want the initial values to be filled in (added via jsp), not the browser's (cached) values. Solution 1: I found out that this can be done by disabling the browser caching for the current page. This seems a rather extreme solution considering that I "only" want to disable this prefill feature for a "form" (hence disable caching for the form only, not the whole page). Solution 2: Then, the obvious next solution is to use javascript: that is, store the initial value in a data-* attribute, then, on
  • 当点击“后退”按钮时,禁用浏览器的表单输入预填充/自动填充功能(Disable browsers Form inputs prefill/autofill feature when hitting “back” button)
    问题 我想“在单击“后退”按钮时防止浏览器预填表单输入”。 确实,我希望填写初始值(通过jsp添加),而不是浏览器的(缓存)值。 解决方案1:我发现可以通过禁用当前页面的浏览器缓存来实现。 考虑到我“仅”要对“表单”禁用此预填充功能,这似乎是一个极端的解决方案(因此,仅对表单而不是整个页面禁用缓存)。 解决方案2:然后,明显的下一个解决方案是使用javascript:即,将初始值存储在data- *属性中,然后在页面加载时,将输入值替换为初始值(如果它们不同)。 两种解决方案似乎都不太理想(这些都是可解决的方法),我转向希望听到更好解决方案的人们。 资源: SO的形式如何记住以前的输入值? 禁用Firefox的自动填充在提交之前,按正确的值回填预填的输入 HTML表单值和“返回”按钮 回答1 我想到的第一件事是使用<input type="reset">按钮。 由于用户很少真正想要重置表单,因此如今很少见到这些,但是这里可能正是您所需要的。 您也可以使用form.reset();在页面加载的javascript中完成此操作form.reset(); 而不是为用户提供按钮。 https://developer.mozilla.org/zh-CN/docs/Web/API/HTMLFormElement.reset 这类似于您的解决方案2,因此仍然是浏览器行为的一种解决方法
  • 如何在Espresso中单击RecyclerView内的项目(How to click on an item inside a RecyclerView in Espresso)
    问题 我有一个RecyclerView(R.id.recyclerView),其中每一行都有一个图像(R.id.row_image)和一个TextView。 我想单击第一行中的图像。 我尝试使用onData(..),但似乎无法正常工作。 回答1 使用RecyclerViewActions onView(withId(R.id.recyclerView)) .perform(actionOnItemAtPosition(0, click())); 包括在您的gradle脚本中: dependencies { androidTestCompile 'com.android.support.test.espresso:espresso-core:2.0' androidTestCompile 'com.android.support.test.espresso:espresso-contrib:2.0' } 回答2 只是为了增加Gabor的答案(这是自Espresso 2.0以来的正确而完整的答案)。 当您使用espresso-contrib和RecyclerView时,您可能会遇到问题(请参阅android-test-kit票证)。 一种解决方法是将此排除项添加到上述的意式espresso-contrib依赖性Gabor中: androidTestCompile('com
  • 如何管理运行时权限android棉花糖意式浓缩咖啡测试(How to manage Runtime permissions android marshmallow espresso tests)
    问题 我正在使用espresso进行测试,但是有时我会尝试从外部存储中获取图像,并且使用棉花糖,我需要运行时权限,否则将发生Exception崩溃,并且测试将失败。 androidTestCompile 'com.android.support.test:runner:0.4' androidTestCompile 'com.android.support.test:rules:0.4' androidTestCompile 'com.android.support.test.espresso:espresso-core:2.2.1' androidTestCompile 'com.android.support.test.espresso:espresso-intents:2.2.1' androidTestCompile('com.android.support.test.espresso:espresso-contrib:2.2.1') { // this library uses the newest app compat v22 but the espresso contrib still v21. // you have to specifically exclude the older versions of the contrib library or //
  • How to disable animations in code when running Espresso tests
    Has anybody managed to disable animations through code when running Espresso tests? I've been trying to follow the instructions in this webpage (linked to from here): https://code.google.com/p/android-test-kit/wiki/DisablingAnimations Unfortunately it does not appear to be working, as I keep seeing this permissions error: 04-27 15:48:28.694 303-342/system_process W/PackageManager﹕ Not granting permission android.permission.SET_ANIMATION_SCALE to package com.cookbrite.dev (protectionLevel=50 flags=0x18be46) I was really hoping to avoid reconfiguring my device/emulators. We frequently run
  • Android Espresso, Wake up device before test. How to use a custom manifest for test?
    I've been writing tests with androids new espresso framework and find that it works well. One annoying thing (not particular to espresso) is that I have to make sure my screen is awake and unlocked for the tests to run. I found a workaround (through various sources) however I am not sure the best way to integrate it. So this is what I did, in my "Home" activity I have the following code: Home.class: public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); /************ Put this in a conditional for a test version ***********/ KeyguardManager km = (KeyguardManager)