Android Marshmallow: проверить разрешения с помощью Espresso?

Новая схема разрешений, введенная Android Marshmallow, требует проверки определенных разрешений во время выполнения, что подразумевает необходимость предоставления разных потоков в зависимости от того, отказывается ли пользователь или разрешает доступ.

Поскольку мы используем Espresso для запуска автоматических тестов пользовательского интерфейса в нашем приложении, как мы можем издеваться или обновлять состояние разрешений для тестирования различных сценариев?

Solutions Collecting From Web of "Android Marshmallow: проверить разрешения с помощью Espresso?"

Попробуйте использовать такой статический метод, когда ваш телефон находится на английском языке:

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

Я нашел его здесь

На основе решения @riwnodennyk мы реализовали лучший. В принятом ответе есть два вопроса:

  • Если устройство не находится на английском языке, оно не будет работать
  • Если вы разрешили разрешение ранее, но ваше приложение имеет кнопку с текстом «Разрешить», она будет нажата в каждом тесте, не имеет значения, является ли это диалогом разрешения одним или нет.

Итак, вот окончательное решение:

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

Найдите здесь весь класс: https://gist.github.com/rocboronat/65b1187a9fca9eabfebb5121d818a3c4

Кстати, поскольку этот ответ был популярным, мы добавили PermissionGranter в Barista , наш инструмент выше Espresso и UiAutomator, чтобы сделать инструментальные тесты зелеными: https://github.com/SchibstedSpain/Barista проверить это, потому что мы будем поддерживать Он выпускается по версии.

Вы можете предоставить разрешения перед запуском теста с чем-то вроде:

 @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"); } } 

Но вы не можете отменить. Если вы попробуете pm reset-permissions или pm revoke... процесс будет убит.

На самом деле есть два способа сделать это, я знаю до сих пор:

  1. Предоставьте разрешение с помощью команды adb до начала тестирования ( документация ):

adb shell pm grant "com.your.package" android.permission.your_permission

  1. Вы можете щелкнуть по диалоговому окну разрешения и установить разрешение с помощью UIAutomator ( документация ). Если ваши тесты написаны с помощью Espresso для Android, вы можете легко скомпоновать шаги Espresso и UIAutomator в одном тесте.

Вы можете легко достичь этого, предоставив разрешение перед началом теста. Например, если вы должны использовать камеру во время пробного прогона, вы можете предоставить разрешение следующим образом

 @Before public void grantPermission() { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { getInstrumentation().getUiAutomation().executeShellCommand( "pm grant " + getTargetContext().getPackageName() + " android.permission.CAMERA"); } } 

С новым выпуском Android Supporting Library 1.0 1.0 есть GrantPermissionRule, который вы можете использовать в своих тестах для предоставления разрешения перед началом любых тестов.

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

Я отключил и восстановил масштаб анимации до и после тестов с использованием эспрессо и adb, как здесь ,

И кажется, что он действителен для M-разрешений, также как и Stony Wang здесь, и Denys ответил .