Android 11 — Хранилище с ограниченной областью действия — переместить файл документа в java.io.File

#android #android-11 #storage-access-framework #scoped-storage

#Android #android-11 #хранилище-доступ-фреймворк #хранилище с ограниченной областью действия

Вопрос:

Я углубляюсь в SAF и хранилище с ограниченной областью действия. Я не буду комментировать весь опыт, Рождество не за горами.

При попытке переместить a DocumentFile в java.io.File папку с новыми предоставленными API DocumentContract.moveDocument:

 DocumentFile documentFile=...
File outputFolder=...
DocumentsContract.moveDocument(getContentResolver(), documentFile.getUri(), documentFile.getParent().getUri(), DocumentFile.fromFile(outputFolder).getUri())
 

Я всегда получаю java.lang.IllegalArgumentException: Invalid URI :

     Caused by: java.lang.IllegalArgumentException: Invalid URI: file:///storage/emulated/0/Android/media/com.myapp/backup
    at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:172)
    at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:142)
    at android.content.ContentProviderProxy.call(ContentProviderNative.java:732)
    at android.content.ContentResolver.call(ContentResolver.java:2405)
    at android.provider.DocumentsContract.moveDocument(DocumentsContract.java:1514)
    at com.myapp.tasks.MoveFolderTask.move(MoveFolderTask.java:77)
 

Читая в других потоках SO, я понимаю, что это происходит из-за преобразования из java.io.File в с DocumentFile помощью

 DocumentFile.fromFile(outputFolder).getUri()`
 

Но я понятия не имею, как обойти это. outputFolder разрешение предоставляется по умолчанию для конкретной папки приложения, возвращаемой Context.getExternalMediaDirs . Проблема в Uri генерации?

Любое предложение приветствуется. спасибо, Никола

Комментарии:

1. AFAIK, moveDocument() заключается в перемещении документов внутри SAF. Похоже, вы пытаетесь «переместить» документ в файл. Для этого вам нужно будет скопировать содержимое в файл, а затем удалить документ.

2. Спасибо @CommonsWare — я пытаюсь переместить целую папку, поэтому я использую предположительно предоставленный move API. Есть какие-нибудь предложения, кроме перебора всех файлов и папок и копирования заново? Это такой перебор для чего-то, что было одноразовым, даже не обсуждая, насколько это очевидная проблема при нехватке места для хранения

3. «Есть какие-либо предложения, кроме перебора всех файлов и папок и копирования?» — нет. «Это такой перебор для чего-то, что было однострочным» — вы, кажется, думаете, что документы, из которых вы копируете, являются локальными. Это мало что гарантирует. Существует множество поставщиков документов, от Google Drive до поставщиков SMB / CIFS, где документы передаются по сети. Ключевым принципом SAF является абстрагирование от этих различий. То, что вы считаете «переместить», на самом деле является «экспортом» или «резервным копированием» с соответствующим удалением исходных данных.

4. Я понимаю это, но мы говорим о локальном, и если больше нет такого способа сделать это эффективно, кажется, что я двигаюсь назад, я не прав? Конечный клиент работает ужасно и медленно, плюс гораздо чаще подвержен ошибкам. Извините за полемический тон, не на вас, конечно!

5. «но мы говорим о локальном» — вы говорите о локальном. «если больше нет такого способа сделать это эффективно, это похоже на движение назад» — если вы имеете в виду, что должно быть больше возможностей для взаимодействия между Uri значениями SAF и локальной файловой системой, где поставщики документов, возможно, могут предоставить более эффективные решения, я согласен. Увы, Google этого не сделал.