SAF listFiles() возвращает пустое значение для подпапок даже при использовании buildDocumentUriUsingTreeAndroid

Форум для тех, кто программирует под Android
Ответить
Anonymous
 SAF listFiles() возвращает пустое значение для подпапок даже при использовании buildDocumentUriUsingTree

Сообщение Anonymous »

Контекст
Я создаю локальный видеоплеер, используя Capacitor 6 и специальный плагин Java для управления доступом к файловой системе на Android 11+ (API 30+). Я использую Storage Access Framework (SAF) через DocumentFile для рекурсивного сканирования выбранного пользователем каталога.
Проблема
Когда я пытаюсь составить список содержимого подпапки, используя ее URI content://, я часто получаю 0 результатов или ошибку, даже если подпапка определенно содержит файлы.
Я пытался использовать DocumentsContract.buildDocumentUriUsingTree для создания URI, «связанного» с корневым деревом, для которого пользователь предоставил разрешение. Однако моя реализация по-прежнему приводит к пустому массиву при вызове listFiles() для вложенных папок.
Моя реализация
Java (плагин пользовательского конденсатора):

Код: Выделить всё

private DocumentFile getTreeBoundDocument(Uri treeUri, Uri childUri) {
String docId;
try {
// childUri comes from parent.listFiles() -> file.getUri()
docId = DocumentsContract.getDocumentId(childUri);
} catch (IllegalArgumentException e) {
return null;
}

// Explicitly rebuild the URI using the original treeUri and child's docId
Uri treeBoundUri = DocumentsContract.buildDocumentUriUsingTree(treeUri, docId);
return DocumentFile.fromTreeUri(getContext(), treeBoundUri);
}

@PluginMethod
public void listContents(PluginCall call) {
String uriString = call.getString("uri");
String treeUriString = call.getString("treeUri"); // The root folder picked by the user

try {
Uri currentUri = Uri.parse(uriString);
DocumentFile dir = null;

if (treeUriString != null) {
Uri treeUri = Uri.parse(treeUriString);

if (uriString.equals(treeUriString)) {
dir = DocumentFile.fromTreeUri(getContext(), treeUri);
} else {
dir = getTreeBoundDocument(treeUri, currentUri);
}
} else {
dir = DocumentFile.fromTreeUri(getContext(), currentUri);
}

if (dir == null || !dir.exists() || !dir.isDirectory()) {
call.reject("Not a directory or cannot access.");
return;
}

DocumentFile[] children = dir.listFiles();
// PROBLEM: children is always empty [] for subfolders, but works for the root.

// ... build response and resolve ...
} catch (Exception e) {
call.reject(e.getMessage());
}
}
TypeScript (рекурсивная логика):

Код: Выделить всё

const scan = async (path: string): Promise => {
// treeUri is the original root URI string stored globally
const res = await StoragePermission.listContents({ uri: path, treeUri: rootTreeUri });
const items = [];

for (const file of res.files) {
if (file.type === 'directory') {
const children = await scan(file.uri);
items.push({ name: file.name, type: 'directory', children });
} else {
items.push({ name: file.name, type: 'video' });
}
}
return items;
};
Что я проверил
  • Постоянные разрешения: я вызываю takePersistableUriPermission для корневого URI.
  • формат[/b]: идентификатор документа, извлеченный из дочернего URI, выглядит правильно (например, основной:Documents/Folder/Subfolder).
  • Версия для Android: протестировано на Android 14.
Вопрос: Как правильно рекурсивно перечислять файлы в подпапке, когда вы иметь разрешение дерева только корневого каталога в SAF? Почему listFiles() возвращает пустое значение для подпапки, URI которой был получен непосредственно из родительского listFiles()?


Подробнее здесь: https://stackoverflow.com/questions/798 ... menturiusi
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «Android»