Фон
До Android Q, если мы хотели получить информацию об APK-файле, мы могли использовать WRITE_EXTERNAL_STORAGE и READ_EXTERNAL_STORAGE, чтобы получить доступ к хранилищу, а затем используйте PackageManager.getPackageArchiveInfo в пути к файлу.
Существуют аналогичные случаи, например использование класса ZipFile a> в сжатом файле и, возможно, бесчисленное множество API фреймворков и сторонних библиотек.
Проблема
Недавно Google объявил об огромном количестве ограничений на Android Q.
Одно из них называется Scoped Storage. разрушает разрешение на хранение, когда дело доходит до доступа ко всем файлам, которые есть на устройстве. Он позволяет либо обрабатывать медиафайлы, либо использовать очень ограниченную платформу доступа к хранилищу (SAF), который не позволяет приложениям получать доступ к файлам и использовать их с помощью File API и путей к файлам.
Когда вышла Android Q Beta 2, из-за нее сломалось множество приложений, в том числе и Google. Причина заключалась в том, что он был включен по умолчанию и затрагивал все приложения, независимо от того, нацелены они на Android Q или нет.
Причина в том, что многие приложения, SDK и сама платформа Android довольно часто используют File API. Во многих случаях они также не поддерживают решения, связанные с InputStream или SAF. Примером этого является именно тот пример анализа APK, о котором я писал (PackageManager.getPackageArchiveInfo).
Однако в Q beta 3 все немного изменилось, так что приложение, предназначенное для Q, будет иметь ограниченное хранилище, и есть флаг, чтобы отключить его и по-прежнему использовать обычные разрешения хранилища и File API, как обычно. К сожалению, этот флаг является временным (прочитайте здесь), так что это отсрочивает неизбежное .
Что я пробовал
Я пробовал и нашел следующие вещи:
Использование разрешения на хранение действительно не позволило мне прочитать ни один файл, кроме медиафайла (я хотел найти файлы APK). Как будто файлов нет.
Используя SAF, я смог найти APK-файл и найти его реальный путь с помощью обходного пути (ссылка здесь), я заметил, что File API может сказать мне, что файл действительно существует, но он не может получить его размер, и фреймворк не может использовать его путь с помощью
getPackageArchiveInfo
. Написал об этом здесьЯ попытался сделать символическую ссылку на файл (ссылка здесь), а затем читать по символической ссылке. Это не помогло.
В случае парсинга APK-файлов я пытался искать альтернативные решения. Я нашел 2 репозитория github, которые обрабатывают APK с помощью класса File (здесь a> и здесь), и тот, который вместо этого использует InputStream ( здесь). К сожалению, тот, который использует InputStream, очень старый, в нем отсутствуют различные функции (например, получение имени и значка приложения), и он не будет обновляться в ближайшее время. Кроме того, наличие библиотеки требует обслуживания, чтобы не отставать от будущих версий Android, иначе в будущем могут возникнуть проблемы или даже сбой.
Вопросы
Как правило, есть ли способ по-прежнему использовать File API при использовании SAF? Я не говорю о корневых решениях или простом копировании файла куда-то еще. Я говорю о более твердом решении.
В случае синтаксического анализа APK есть ли способ решить эту проблему, когда фреймворк предоставляет только путь к файлу в качестве параметра? Возможно, какой-нибудь обходной путь или способ использования InputStream?
Uri
указывал на обычный файл в файловой системе, не говоря уже о том, к которому у вас есть доступ. Например,DocumentsProvider
может потребоваться расшифровать файл на лету, как показано в этот образец, на который вы указали 4,5 года назад. Все, что вы можете сделать, это скопировать содержимое в файл, которым вы управляете. - person CommonsWare   schedule 18.05.2019DocumentsProvider
. Любой независимо написанныйDocumentsProvider
нарушит ваш методgetFullPathFromTreeUri()
, так как вы слепо предполагаете, чтоUri
принадлежит конкретномуDocumentsProvider
(тот, который в идеале не будет поддерживать ваш хак и, возможно, перестанет поддерживать его в какой-то будущей версии Android). - person CommonsWare   schedule 18.05.2019Uri
указывал на файл в файловой системе, не говоря уже о файле, к которому вы можете получить прямой доступ любым способом. Пользователь может использовать SAF, чтобы выбрать местоположение на Google Диске, образец Vault, на который я ссылаюсь, сетевой ресурс SMB/CIFS или любой другойDocumentsProvider
, к которому у него есть доступ.Uri
может указывать на расположение на сервере, или в столбцеBLOB
базы данных, или на что-то еще, что захочетDocumentsProvider
автор. - person CommonsWare   schedule 18.05.2019DocumentsProvider
. Будет ли это работать? -- Я не знаю, что это такое. Действительно ли Google собирается сломать так много приложений? -- Google сломал их пять лет назад. Вместо того, чтобы работать над альтернативными решениями ваших проблем (например, над библиотекой разбора APK, которая не зависит от файлов), вы и другие прибегли к хакам. Если бы вы использовали эти хаки как краткосрочную временную лазейку и приложили усилия к устранению необходимости в них, сегодня вы были бы в лучшей форме. - person CommonsWare   schedule 18.05.2019moveDocument
). До этого вам приходилось копировать и удалять. И это только один пример. - person android developer   schedule 18.05.2019