2

We have a custom android device that is running Nougat and is wrapped in a vendor specific launcher. I am trying to implement a File Manager for the said device with the use of API 23. This is because I've read that the only way to do it starting from Android M is with SAF.

The device I am developing on has 3 USB ports to which when a USB drive is connected the app would detect and transfer custom files from the USB to the device's Internal Storage (the device has no SD Card). Since direct access to mountable storage is a no-go on Android N I was thinking of doing this with SAF.

I have implemented broadcast receivers for USB Detach and Attach through the USB Manager and USB Host and can successfully detect when a USB is plugged in or not in a vain attempt to communicate with the device and try to extract the files. But I've also read that the Android USB Framework is only for sending small bytes for communicating with a USB connected device such as an Arduino board and what not.

I am now trying to implement a USB Document Provider to browse the USB. Since I cannot directly access the files according to this post.

I am following this source code to implement my USB Document Provider.

I'm currently implementing the queryRoots and queryChildDocuments part of the class. Most of the fields for the Cursor I understand what to put but the part for the COLUMN_DOCUMENT_ID stumbles me (for both methods).

Since the device is a removable USB I don't know what to put as a value for the column

Here is my queryRoots method implementation:

@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;
}

Please correct me if I'm wrong but since the files I want to export are not your typical mime type files, I have set the COLUMN_MIME_TYPES to

*/*

And my queryChildDocuments method:

   @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;
    }

Apart from that, there is nothing else special to my implementation.

I then made an intent to open the documents provider through a navigation menu with this code:

if (id == R.id.nav_file_explorer) {
            Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
            startActivityForResult(intent, 1);
}

The custom document provider is shown on the list but the USB drive is not listed. Apart from that when I click on the document provider to open from my specified root it returns nothing. What am I doing wrong?

4

1 回答 1

3

在 Android M 及更高版本中,无需 SAF 即可访问可移动存储数据。你只需要做低级的编码。如本项目所示。我们在我们的项目中可能会选择实施类似于这个链接项目的东西,因为到目前为止 SAF 被证明是不可靠的。

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

于 2018-01-24T00:15:05.150 回答