Проблема с разрешением приложения Android, работающая под VirtualBox

Я пытаюсь запустить подключенные тесты для своего приложения, используя Android ISO, установленный на VirtualBox. Я получил ISO-образ Android 7.1 с сайта 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. Покрутите разрешение «Хранилище» в «Настройки» => «Приложения» => «Мое приложение».

person Stephen M -on strike-    schedule 29.10.2018    source источник


Ответы (1)


Проследил проблему до несоответствия в обработке разрешений 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);

Однако это неявно не дает разрешение на чтение. Таким образом, когда приложение запустилось в первый раз на виртуальной машине, ему было явно разрешено ЗАПИСЬ и неявно ЧТЕНИЕ. Однако после того, как 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 никогда не встречались, поэтому поведение отличается.

Спасибо, Гугл! /с

person Stephen M -on strike-    schedule 29.10.2018