在Android N上浏览可移动USB OTG,Storage Access Framework真的是唯一的方法吗?

时间:2018-01-16 09:56:56

标签: android usb storage-access-framework removable-storage

我们有一个运行Nougat的自定义Android设备,并且包含在供应商特定的启动器中。我正在尝试使用API​​ 23为所述设备实现文件管理器。这是因为我已经读过,从Android M开始的唯一方法是使用SAF。

我正在开发的设备有3个USB端口,当连接USB驱动器时,应用程序会检测并将自定义文件从USB传输到设备的内部存储设备(设备没有SD卡)。由于在Android N上直接访问可安装存储是不可取的,我想用SAF来做这件事。

我已经通过USB管理器和USB主机实现了USB分离和连接的广播接收器,并且可以成功检测USB插入的时间,但徒劳地尝试与设备通信并尝试提取文件。但我也读到Android USB框架仅用于发送小字节,用​​于与USB连接设备(如Arduino板)进行通信,而不是。

我现在正在尝试实施USB文档提供程序来浏览USB。由于我无法根据此post直接访问文件。

我正在关注此source code以实现我的USB文档提供程序。

我目前正在实现类的queryRoots和queryChildDocuments部分。 Cursor的大多数字段我都知道要放什么,但是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 个答案:

答案 0 :(得分:0)

在Android M及更高版本中无需SAF即可访问可移动存储数据。你只需要进行低级编码。正如此project所示。 我们项目中可能会选择实施与此链接项目类似的内容,因为此时SAF证明是不可靠的。

该项目还包括SAF的实施,但以低级USB读取库为基础。