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

Я пишу специальное приложение для камеры, предназначенное для Android 11. Когда я нажимаю запись, я хотел бы создать где-нибудь новый каталог (с именем, основанным на отметке времени и т. д.), который содержит полученное видео, а также целую кучу другие пользовательские файлы YAML/JSON/CSV, которые также записываются в процессе записи (логически относятся к результату записи).

Я хотел бы, чтобы все сгенерированные файлы сохранились после удаления/переустановки приложения, поскольку я не хочу рисковать тем, что пользователи потеряют все, что они когда-либо записали, если они удалят приложение. Как мне это сделать с новыми изменениями в области хранения и т. д. в Android 11?

Глядя на обзор здесь, я вижу, что:

  • Файлы приложения, Настройки приложения и База данных явно не подходят, так как среди прочего эти файлы не сохраняются после удаления.
  • Документы и другие файлы используют Storage Access Framework, но это не подходит, поскольку каждый раз, когда вы хотите что-то написать, требуется средство выбора системных файлов. Это нарушило бы процесс записи/работы пользователя, и ни одно приложение камеры не работает так.
  • Наборы данных/BlobStoreManager (здесь) также не подходит для моего варианта использования.
  • MediaStore API выглядит так, как будто он должен быть единственным, но он не может делать то, что я хочу, с точки зрения создания целого каталога выходных данных, включая пользовательские текстовые файлы YAML/JSON/CSV, которые все принадлежат друг другу. Моя цель состоит в том, чтобы пользователь в любое время мог просто зайти в проводник, перейти к соответствующей папке и просто скопировать папку(и) с записями на свой компьютер или что-то еще, чтобы сохранить/просмотреть данные. Даже MediaStore.Files, похоже, не гарантирует, что вы действительно сможете это сделать, если ваше приложение использует хранилище с ограниченной областью действия.

Единственный оставшийся вариант — использовать MANAGE_EXTERNAL_STORAGE и помещать данные в любое место в домашнем каталоге, но это похоже на чрезмерное разрешение, которое нужно запрашивать только для того, чтобы иметь возможность сохранять некоторые текстовые файлы вместе с мои произведенные видео. Кроме того, это разрешение специфично для Android 11. Если я хочу поддерживать более старые версии Android, что мне нужно сделать?

Какой мой лучший выбор здесь? Есть вариант, который я пропустил?


person pallgeuer    schedule 10.01.2021    source источник
comment
MANAGE_EXTERNAL_STORAGE тоже крайне нежелательно из-за этого: developer.android.com/training/data-storage/   -  person pallgeuer    schedule 10.01.2021


Ответы (2)


но это не подходит, потому что требует выбора системного файла каждый раз, когда вы хотите что-то написать

No.

Используйте ACTION_OPEN_DOCUMENT_TREE, чтобы позволить пользователю выбрать дерево документов. Там вы можете создать свое собственное поддерево и поместить в него свои документы. Вам не нужен сборщик системных файлов ни для чего, кроме исходного ACTION_OPEN_DOCUMENT_TREE запроса. И полученные документы переживут удаление.

person CommonsWare    schedule 10.01.2021
comment
Я правильно понимаю, что приложению нужно позволить пользователю выбрать дерево документов только один раз? Или пользователю нужно выбирать дерево документов один раз при запуске приложения? Один раз за обновление приложения? Один раз за переустановку приложения? - person pallgeuer; 11.01.2021
comment
Только один раз. И один == один. - person blackapps; 11.01.2021
comment
@pallgeuer: вам нужно будет повторно запросить дерево, если ваше приложение будет удалено и переустановлено. Существуют крайние случаи, когда вам нужно будет повторно запросить дерево, например, если пользователь удалит исходное дерево. В противном случае, если вы используете takePersistableUriPermission(), у вас будет постоянный доступ к дереву. - person CommonsWare; 11.01.2021
comment
@CommonsWare, есть ли образец рабочего кода для записи файла во внешнее хранилище, а затем чтения файла из этого места для всех API, включая Android 11? и дополнительный вопрос для чтения этого документа Если я должен спрашивать пользователя каждый раз? или один раз? как метод? - person Noor Hossain; 15.02.2021

Вы можете создать свой собственный каталог в общедоступном каталоге, таком как DCIM, Pictures, Music или Movies, с помощью классических методов File.

person blackapps    schedule 10.01.2021
comment
Да, но если я не ошибаюсь, как я уже сказал, для этого требуется разрешение MANAGE_EXTERNAL_STORAGE, что не является вариантом: support.google.com/googleplay/android-developer/answer/9956427 - person pallgeuer; 11.01.2021
comment
Нет. Этого не требуется. А почему ты еще не пробовал? - person blackapps; 11.01.2021
comment
Да, я это сделал, и, как четко задокументировано в документации Android, классическая попытка записи файла не удалась (операция EPERM не разрешена). Это оставляет только возможность добавить WRITE_EXTERNAL_STORAGE или MANAGE_EXTERNAL_STORAGE, чтобы надеяться, что это сработает, и если вы прочитаете документацию, вы увидите: если ваше приложение предназначено для Android 11 (уровень API 30) или выше, разрешение WRITE_EXTERNAL_STORAGE не имеет никаких влияет на доступ вашего приложения к хранилищу. Может быть, вы не знали, что в Android 11 все изменилось? - person pallgeuer; 11.01.2021
comment
Покажи свой код. Вы не можете создавать файлы в этих каталогах под Android 11. Но вы можете создать там свою собственную папку, а затем создавать файлы в своей папке. Мы не знаем, что вы сделали. Вам нужны обычные разрешения, как и до Android 10. - person blackapps; 11.01.2021
comment
Я использовал Environment.getExternalStoragePublicDirectory(...) для получения каталога DCIM (это устарело — как заменить?), а затем File::mkdir для создания папки в DCIM. Это сработало. Создание FileWriter для файла по этому пути завершается с ошибкой java.io.FileNotFoundException: /storage/emulated/0/DCIM/blah/stuff.yaml: open failed: EPERM (Operation not permitted), где я проверил в файловом менеджере, что папка blah действительно существует из предыдущего mkdir. Просто чтобы быть уверенным, я также попытался после успешного применения разрешения WRITE_EXTERNAL_STORAGE к моему приложению (я нажал «Разрешить»). - person pallgeuer; 11.01.2021
comment
Таким образом, если у вас есть какой-либо код, который успешно выполняет то, что, как вы утверждаете, возможно (проверено на Android 11), опубликуйте его на благо сообщества! - person pallgeuer; 11.01.2021
comment
Точно такой же код, который я пробовал, отлично работает, если приложение имеет разрешение MANAGE_EXTERNAL_STORAGE, так что это определенно не опечатка в коде. Но получить такое разрешение для такого приложения, как мое, невозможно с новой политикой Google. - person pallgeuer; 11.01.2021
comment
Попробуйте /storage/emulated/0/DCIM/blah/stuff.jpg, так как не все типы файлов разрешены в DCIM. - person blackapps; 11.01.2021
comment
Используя собственную папку в каталоге Documents, вы можете писать файлы *.yaml. Вы должны пробовать и тестировать больше! - person blackapps; 11.01.2021
comment
Тестирование не является синонимом угадывания хрупкого недокументированного поведения и не должно им быть. В любом случае, я могу подтвердить, что jpg в подпапке DCIM работал и yaml в подпапке Documents работал. Тем не менее, было бы опрометчиво полагаться на такое недокументированное поведение в серьезном приложении, которое нужно поддерживать годами. - person pallgeuer; 12.01.2021