Просматривая съемную USB OTG на Android N, действительно ли Storage Access Framework - единственный способ?
У нас есть пользовательское устройство Android, работающее под управлением Nougat и обернутое в специфичную для поставщика программу запуска. Я пытаюсь реализовать диспетчер файлов для указанного устройства с использованием API 23. Это потому, что я прочитал, что единственный способ сделать это, начиная с Android M, - это SAF.
Устройство, на котором я разрабатываю, имеет 3 порта USB, к которым при подключении USB-накопителя приложение будет обнаруживать и передавать пользовательские файлы с USB-накопителя во внутреннюю память устройства (на устройстве нет SD-карты). Поскольку прямой доступ к монтируемому хранилищу на Android не используется, N I думал об этом с помощью SAF.
Я реализовал широковещательные приемники для USB отсоединения и подключения через USB-менеджер и USB-хост и могу успешно определять, подключен ли USB или нет, в тщетной попытке связаться с устройством и попытаться извлечь файлы. Но я также читал, что Android USB Framework предназначен только для отправки небольших байтов для связи с USB-подключенным устройством, таким как плата Arduino, а что нет.
Я сейчас пытаюсь реализовать провайдера документов USB для просмотра USB. Так как я не могу напрямую получить доступ к файлам согласно этому посту.
Я следую этому исходному коду для реализации моего USB-провайдера документов.
В настоящее время я реализую часть класса queryRoots и queryChildDocuments. Большинство полей для курсора я понимаю, что поставить, но часть для COLUMN_DOCUMENT_ID ставит меня в тупик (для обоих методов).
Поскольку устройство является съемным USB, я не знаю, что указать в качестве значения для столбца
Вот моя реализация метода queryRoots:
@Override
public Cursor queryRoots(String[] projection) throws FileNotFoundException {
final MatrixCursor result = new MatrixCursor(resolveRootProjection(projection));
final MatrixCursor.RowBuilder row = result.newRow();
row.add(Root.COLUMN_ROOT_ID, BuildConfig.DOCUMENTS_AUTHORITY);
row.add(Root.COLUMN_ICON, R.drawable.ic_menu_manage);
row.add(Root.COLUMN_TITLE, "Root Title");
row.add(Root.COLUMN_FLAGS, Root.FLAG_SUPPORTS_SEARCH | Root.FLAG_SUPPORTS_RECENTS);
row.add(Root.COLUMN_SUMMARY, "USB Reader");
row.add(Root.COLUMN_DOCUMENT_ID, "/");
row.add(Root.COLUMN_MIME_TYPES, "*/*");
Uri rootsUri = DocumentsContract.buildRootsUri(BuildConfig.DOCUMENTS_AUTHORITY);
getContext().getContentResolver().notifyChange(rootsUri, null);
return result;
}
Пожалуйста, исправьте меня, если я ошибаюсь, но так как файлы, которые я хочу экспортировать, не являются вашими типичными файлами mime-типов, я установил для COLUMN_MIME_TYPES значение
*/*
И мой метод queryChildDocuments:
@Override
public Cursor queryChildDocuments(String parentDocumentId, String[] projection,
String sortOrder) throws FileNotFoundException {
final MatrixCursor result = new
MatrixCursor(resolveDocumentProjection(projection));
String parentDocumenPath = getContext().getFilesDir().getPath() + "/" + parentDocumentId;
File dir = new File(parentDocumenPath);
for (File file : dir.listFiles()) {
String documentId = parentDocumentId + "/" + file.getName();
includeFile(result, documentId);
}
return result;
}
Кроме этого, в моей реализации нет ничего особенного.
Затем я решил открыть провайдер документов через меню навигации с этим кодом:
if (id == R.id.nav_file_explorer) {
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
startActivityForResult(intent, 1);
}
Пользовательский поставщик документов отображается в списке, но USB-накопитель отсутствует в списке. Кроме того, когда я нажимаю на провайдера документов, чтобы открыть его из указанного мной корня, он ничего не возвращает. Что я делаю неправильно?
1 ответ
Доступ к данным съемного хранилища можно сделать без SAF в Android M и выше. Вам просто нужно сделать низкоуровневое кодирование. Как показано в этом проекте. Мы в нашем проекте могли бы предпочесть реализацию чего-то похожего на этот связанный проект, поскольку SAF оказывается ненадежным на данный момент.
Проект также включает реализацию SAF, но с низкоуровневой библиотекой чтения USB в качестве основы.