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

你。 提交于 2019-12-04 00:16:35

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.

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();
                            }
                        }
                    });

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

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 .

DoronK

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

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

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();
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!