MediaScanner и ScopedStorage в SDK-29
Приложение , над которым я работаю, использует File
в качестве мишени для фотосъемки. это выполняется извне, когда пользователь выбирает приложение камеры с помощьюIntent(ACTION_IMAGE_CAPTURE)
. после обновления build и target-sdk до 29 возник ряд проблем, начиная с ограничения на свободный доступ к файлам на внешнем хранилище. первое изменение заключалось в использовании одного из каталогов частного кеша приложения, например:
File.createTempFile("tempImage", ".jpg", context.cacheDir)
или каталог частного внешнего хранилища приложений:
File.createTempFile("tempImage", ".jpg", context.getExternalFilesDir(Environment.DIRECTORY_PICTURES))
в сочетании с доступом FileProvider в file_paths.xml
, например:
<paths>
<external-path name="images" path="Pictures/" /><!-- prior to SDK-29, use public external storage -->
<external-files-path name="externalImages" path="Pictures/" />
<files-path name="internalImages" path="internalImages/"/>
<cache-path name="cache" path="/" />
</paths>
теперь они работают нормально после правильной настройки, однако реализация функции "Сохранить в галерею", например: уведомление других приложений о новых изображениях больше не работает на устройствах под управлением Android-10
// use FileProvider to make this new photo publicly accessible
val shareableUri = FileProvider.getUriForFile(context, FILE_PROVIDER_AUTHORITY, newImage)
context.sendBroadcast(
Intent(ACTION_MEDIA_SCANNER_SCAN_FILE).apply { data = uris.externalUri }
)
этот подход должен работать, но не работает, независимо от того, где сохранено исходное изображение (private-app-dir, cache-dir, external-private)
MediaScannerConnection.scanFile(context, arrayOf(newImage.absolutePath), arrayOf("image/jpeg")) { path: String, uri: Uri? ->
if (uri == null) {
throw IllegalStateException("media scan failed...")
} else {
// successful
}
}
Есть ли новые ограничения в Android SDK-29, которые требуют изменения в MediaScanning, в частности, связанных со способом сканирования (потенциально) частного файла изображения? Я заметил, чтоMediaScanner
методы в основном ожидают String
path вместо URI, поэтому это наводит меня на мысль, что новые ограничения не будут применяться к нему, поскольку это системный компонент.
1 ответ
Приложениям, ориентированным на Android 10 (уровень API 29) и выше, по умолчанию предоставляется ограниченный доступ к внешнему запоминающему устройству или ограниченному хранилищу.
поэтому вам нужно сделать его совместимым с scopedStorage, но вы можете использовать этот временный подход, упомянутый в руководстве для разработчиков Google Android.
Прежде чем ваше приложение будет полностью совместимо с ограниченным хранилищем, вы можете временно отказаться от него на основе целевого уровня SDK вашего приложения или атрибута манифеста requestLegacyExternalStorage:
<manifest ... >
<!-- This attribute is "false" by default on apps targeting
Android 10 or higher. -->
<application android:requestLegacyExternalStorage="true" ... >
...
</application>
</manifest>
посетите эту ссылку для получения дополнительной информации: https://developer.android.com/training/data-storage/files/external-scoped