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

8

28

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.

enter image description here

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

enter image description here

3. After login it shows another Fill dialog:

enter image description here

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?

Burack answered 18/10, 2017 at 14:34 Comment(10)
Per a deleted answer, Settings > System > Advanced > Autofill service > Set to "None".Disgrace
@Disgrace I dont have access to settings on devices from clouds like firebase, I need to disable those from code before tests runsBurack
For me (using Android 8.0.0), it was under Settings > System > Languages & input > Advanced > Autofill serviceWarenne
Did you manage to find the answer? Same problemPapacy
Hey, did you find any solution? below answers are not working for me to close suggestion box of autofill on email/password(screenshot #2) and test get failedWord
@Word The accepted answer is working for me, maybe there's something different on your env?Burack
idk, but I do this hack https://mcmap.net/q/492467/-how-to-disable-the-new-autofill-feature-from-android-oreo-for-espresso-testsWord
And that worked for you?Burack
yes, I already have CustomEditText everywhere. So no extra work was neededWord
I dont see that as a good practice, you modified your production code in order to be testable, and that add a risk of possible failure and also knowledge about the existence of the tests, have that in mind in the futureBurack
C
13

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

Courbevoie answered 18/1, 2018 at 4:21 Comment(4)
The last one adb shell settings put secure autofill_service null worked! thanks manBurack
Can you add code to enable it again :) after "... autofill_service null"Papacy
I enabled it changing "null" for "com.google.android.gms/com.google.android.gms.autofill.service.AutofillService", thanks :)Papacy
As of 5/25/2023, this no longer works: sudo adb shell settings put secure autofill_service null Exception occurred while executing 'put': java.lang.SecurityException: Permission denial: writing to settings requires:android.permission.WRITE_SECURE_SETTINGSEarpiece
T
14

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.

Tyner answered 24/10, 2017 at 2:25 Comment(3)
It removed the "Tap to let Google" dialog but it still shows "Save password to AUTOFILL with GOOGLE" dialog.Burack
I do not have O device and I cannot find "Autofill with Google" app inside emulator. I think you can try to disable that application through adb shell command (how?) when performing instrumented test: adb shell pm disable package.name.of.autofill.with.google.Tyner
you can find it in the Settings for an Android O emulator.Burack
C
13

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

Courbevoie answered 18/1, 2018 at 4:21 Comment(4)
The last one adb shell settings put secure autofill_service null worked! thanks manBurack
Can you add code to enable it again :) after "... autofill_service null"Papacy
I enabled it changing "null" for "com.google.android.gms/com.google.android.gms.autofill.service.AutofillService", thanks :)Papacy
As of 5/25/2023, this no longer works: sudo adb shell settings put secure autofill_service null Exception occurred while executing 'put': java.lang.SecurityException: Permission denial: writing to settings requires:android.permission.WRITE_SECURE_SETTINGSEarpiece
S
7

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())
Sumptuous answered 13/2, 2019 at 21:6 Comment(0)
S
4

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

getWindow().getDecorView().setImportantForAutofill(View.IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS);
Starfish answered 8/9, 2019 at 11:19 Comment(0)
A
3

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();
                            }
                        }
                    });
Astatic answered 19/9, 2018 at 7:33 Comment(0)
R
-1

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();
}
Romano answered 24/10, 2017 at 21:49 Comment(1)
It feels bad to change all the EditText in my app just for this purpuse but thanksBurack
S
-1

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 .

Supine answered 30/10, 2017 at 17:47 Comment(1)
Please read the question, I already said that there's one case where this does not workBurack
S
-1

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

Suet answered 7/11, 2020 at 12:52 Comment(1)
This works if you have access to your device but not for a test device farm and something more automated, please read the question text.Burack

© 2022 - 2024 — McMap. All rights reserved.