Проблема с разрешением приложений Android, работающих под VirtualBox - PullRequest
0 голосов
/ 29 октября 2018

Я пытаюсь запустить связанные тесты для моего приложения, используя Android ISO, установленный на VirtualBox. Я получил Android 7.1 ISO от http://www.android -x86.org / . Он установлен под VirtualBox и, кажется, работает правильно.

Наше приложение использует PocketSphinx, который создает несколько каталогов и сохраняет в них некоторые файлы. Приложение работает корректно на некоторых планшетах Android 7.0 и под эмулятором, который поставляется с Android Studio. Иногда он работает правильно в VirtualBox, но он попадает в какое-то странное состояние, когда он не может читать или записывать в нужные каталоги.

AndroidManifest содержит это разрешение (наряду с другими):

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

Разрешения отображаются как включенные в Настройках => Приложения => [Наше приложение] => Разрешения.

Вот фактическое сообщение об ошибке:

W/System.err: java.io.FileNotFoundException: /storage/emulated/0/Android/data/com.hcs.android.orconnect/files/sync/cmudict-en-us.dict (No such file or directory)
                  at java.io.FileOutputStream.open(Native Method)
                  at java.io.FileOutputStream.<init>(FileOutputStream.java:221)
                  at java.io.FileOutputStream.<init>(FileOutputStream.java:169)
                  at edu.cmu.pocketsphinx.Assets.copy(Assets.java:224)
                  at edu.cmu.pocketsphinx.Assets.syncAssets(Assets.java:269)

Если я установлю точку останова перед этим вызовом, я вижу, что все они возвращают false:

new File("/storage/emulated/0/Android/data/").canRead()
new File("/storage/emulated/0/Android/data/").canWrite()
new File("/storage/emulated/0/Android/data/com.hcs.android.orconnect").canRead()
new File("/storage/emulated/0/Android/data/com.hcs.android.orconnect").canWrite()

Однако что-то создало папку /storage/emulated/0/Android/data/com.hcs.android.orconnect/files. Если я вручную удалю эту папку из приглашения оболочки adb, она будет воссоздана при следующем запуске моего теста приложения, но у приложения все еще будут те же проблемы.

Я действительно в недоумении, почему у меня проблемы с разрешением. Любые идеи о том, что происходит и как исправить разрешения?

(Примечание: я не хочу использовать эмулятор Android, потому что мы запускаем VirtualBox по другим причинам, и они не будут играть друг с другом.)

(Примечание. Неудивительно, что при запуске приложения из отладчика возникают те же проблемы, что и при запуске подключенного теста.)

Шаги для воспроизведения:

  1. Установите и запустите образ VirtualBox под Android 7.1 ISO.
  2. Пробег adb connect <ip address>
  3. Выполнить ./gradlew connectAndroidTest
  4. Тест пройдёт
  5. Выполнить ./gradlew connectAndroidTest
  6. Тест не пройден и не будет выполняться для всех будущих прогонов.

Работа вокруг:

  1. Установить приложение (если не установлено)
  2. Поверните разрешение «Хранилище» в Настройках => Приложения => [Мое приложение]

1 Ответ

0 голосов
/ 30 октября 2018

Отследил проблему до несоответствия в обработке разрешений Android.

Манифест нашего приложения содержал:

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

В результате /data/system/users/0/runtime-permissions.xml содержит:

<item name="android.permission.READ_EXTERNAL_STORAGE" granted="true" flags="0" />^M     
<item name="android.permission.WRITE_EXTERNAL_STORAGE" granted="true" flags="0" />^M

Чтение предоставляется неявно. Однако при написании подключенного теста я использовал правила предоставления разрешений:

@Rule public GrantPermissionRule permissionRule2 = GrantPermissionRule.grant(android.Manifest.permission.WRITE_EXTERNAL_STORAGE);

Это, однако, не неявно дает разрешение на чтение. Таким образом, когда приложение впервые запускалось на виртуальной машине, оно было предоставлено WRITE явно и неявно READ. Однако после первого запуска теста gradlew приложение будет удалено. Затем при следующем тесте приложение будет переустановлено, но только получит разрешение ЗАПИСАТЬ в соответствии с правилами. Затем проверка не проходит, как описано выше.

Итак, решение состоит в том, чтобы запросить разрешение на чтение и запись в тесте:

@Rule public GrantPermissionRule permissionRule2 = GrantPermissionRule.grant(android.Manifest.permission.READ_EXTERNAL_STORAGE);
@Rule public GrantPermissionRule permissionRule25 = GrantPermissionRule.grant(android.Manifest.permission.WRITE_EXTERNAL_STORAGE);

Не берите в голову, что это не соответствует моему файлу AndroidManifest.xml. Левая и правая рука Google никогда не встречались, поэтому поведение отличается.

Спасибо, Google! / С * 1 021 *

...