Android Marshmallow: Test permissions with Espresso?

With the new release of the Android Testing Support Library 1.0, there's a GrantPermissionRule that you can use in your tests to grant a permission before starting any tests.

@Rule public GrantPermissionRule permissionRule = GrantPermissionRule.grant(android.Manifest.permission.ACCESS_FINE_LOCATION);

Kotlin solution

@get:Rule var permissionRule = GrantPermissionRule.grant(android.Manifest.permission.ACCESS_FINE_LOCATION)

@get:Rule must be used in order to avoid java.lang.Exception: The @Rule 'permissionRule' must be public. More info here.


The accepted answer doesn't actually test the permissions dialog; it just bypasses it. So, if the permissions dialog fails for some reason, your test will give a false green. I encourage actually clicking the "give permissions" button to test the whole app behaviour.

Have a look at this solution:

public static void allowPermissionsIfNeeded(String permissionNeeded) {
    try { 
      if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && !hasNeededPermission(permissionNeeded)) {
        sleep(PERMISSIONS_DIALOG_DELAY);
        UiDevice device = UiDevice.getInstance(getInstrumentation());
        UiObject allowPermissions = device.findObject(new UiSelector()
          .clickable(true) 
          .checkable(false) 
          .index(GRANT_BUTTON_INDEX));
        if (allowPermissions.exists()) {
          allowPermissions.click();
        } 
      } 
    } catch (UiObjectNotFoundException e) {
      System.out.println("There is no permissions dialog to interact with");
    } 
  } 

Find the whole class here: https://gist.github.com/rocboronat/65b1187a9fca9eabfebb5121d818a3c4

By the way, as this answer has been a popular one, we added PermissionGranter to Barista, our tool above Espresso and UiAutomator to make instrumental tests green: https://github.com/SchibstedSpain/Barista check it out, because we will maintain it release by release.


Give a try with such static method when your phone is on English locale:

private static void allowPermissionsIfNeeded() {
    if (Build.VERSION.SDK_INT >= 23) {
        UiDevice device = UiDevice.getInstance(getInstrumentation());
        UiObject allowPermissions = device.findObject(new UiSelector().text("Allow"));
        if (allowPermissions.exists()) {
            try {
                allowPermissions.click();
            } catch (UiObjectNotFoundException e) {
                Timber.e(e, "There is no permissions dialog to interact with ");
            }
        }
    }
}

I found it here


You can grant permissions before the test is run with something like:

@Before
public void grantPhonePermission() {
    // In M+, trying to call a number will trigger a runtime dialog. Make sure
    // the permission is granted before running this test.
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
        getInstrumentation().getUiAutomation().executeShellCommand(
                "pm grant " + getTargetContext().getPackageName()
                        + " android.permission.CALL_PHONE");
    }
}

But you can't revoke. If you try pm reset-permissions or pm revoke... the process is killed.