queryRoots首先调用queryDocument,而不是queryChildDocuments

问题描述 投票:1回答:1

我正在为Dropbox编写SAF包装器的包装器,因为每个人(包括Google)都懒得实现这个“非常丰富”(即:糟糕的)API。我已经扎根于选择器,但我认为应首先调用queryChildren。但是,queryChildren is never called and it goes straight toqueryDocument`。

override fun queryRoots(projection: Array<out String>?): Cursor {
    // TODO: Likely need to be more strict about projection (ie: map to supported)
    val result = MatrixCursor(projection ?: DEFAULT_ROOT_PROJECTION)

    val row = result.newRow()
    row.add(DocumentsContract.Root.COLUMN_ROOT_ID, "com.anthonymandra.cloudprovider.dropbox")
    row.add(DocumentsContract.Root.COLUMN_ICON, R.drawable.ic_dropbox_gray)
    row.add(DocumentsContract.Root.COLUMN_TITLE, "Dropbox")
    row.add(DocumentsContract.Root.COLUMN_FLAGS, DocumentsContract.Root.FLAG_SUPPORTS_CREATE)   // TODO:
    row.add(DocumentsContract.Root.COLUMN_DOCUMENT_ID, ROOT_DOCUMENT_ID)
    return result
}

override fun queryChildDocuments(
    parentDocumentId: String?,
    projection: Array<out String>?,
    sortOrder: String?
): Cursor {
    // TODO: Likely need to be more strict about projection (ie: map to supported)
    val result = MatrixCursor(projection ?: DEFAULT_DOCUMENT_PROJECTION)
    val dropboxPath = if (parentDocumentId == ROOT_DOCUMENT_ID) "" else parentDocumentId

    try {
        val client = DropboxClientFactory.client

        var childFolders = client.files().listFolder(dropboxPath)
        while (true) {
            for (metadata in childFolders.entries) {
                addDocumentRow(result, metadata)
            }

            if (!childFolders.hasMore) {
                break
            }

            childFolders = client.files().listFolderContinue(childFolders.cursor)
        }
    } catch(e: IllegalStateException) { // Test if we can attempt auth thru the provider
        context?.let {
            Auth.startOAuth2Authentication(it, appKey)   // TODO: appKey
        }
    }
    return result
}

override fun queryDocument(documentId: String?, projection: Array<out String>?): Cursor {
    // TODO: Likely need to be more strict about projection (ie: map to supported)
    val result = MatrixCursor(projection ?: DEFAULT_DOCUMENT_PROJECTION)

    try {
        val client = DropboxClientFactory.client
        val metadata = client.files().getMetadata(documentId)
        addDocumentRow(result, metadata)
    } catch(e: IllegalStateException) { // Test if we can attempt auth thru the provider
        context?.let {
            Auth.startOAuth2Authentication(it, appKey)   // TODO: appKey
        }
    }
    return result
}

错误:

java.lang.IllegalArgumentException: String 'path' does not match pattern
    at com.dropbox.core.v2.files.GetMetadataArg.<init>(GetMetadataArg.java:58)
    at com.dropbox.core.v2.files.GetMetadataArg.<init>(GetMetadataArg.java:80)
    at com.dropbox.core.v2.files.DbxUserFilesRequests.getMetadata(DbxUserFilesRequests.java:1285)
    at com.anthonymandra.cloudprovider.dropbox.DropboxProvider.queryDocument(DropboxProvider.kt:98)
    at android.provider.DocumentsProvider.query(DocumentsProvider.java:797)
    at android.content.ContentProvider$Transport.query(ContentProvider.java:240)
    at android.content.ContentProviderNative.onTransact(ContentProviderNative.java:102)
    at android.os.Binder.execTransact(Binder.java:731)

pathROOT_DOCUMENT_ID,我期待首先去queryChildDocuments

我在这里错过了什么?

android storage-access-framework documents-provider
1个回答
1
投票

实施DocumentsProvider的文档是有限的。特别是,没有记录保证呼叫顺序。因此,实际上应该实现DocumentsProvider,以尽可能少地假设这些调用的顺序。

例如,我不会假设首先调用queryRoots()。它可能是第一个,如果第一次使用DocumentsProvider这个过程碰巧是存储访问框架UI。但是,鉴于客户可以(小心)持久保存文档或文档树Uri,如果第一件事恰好是使用持久性Uri的客户端,您可能最终会在您的流程中首先调用其他内容。

并且,在您的具体情况下,我不会认为queryChildDocuments()发生在queryDocument()之前或之后。

© www.soinside.com 2019 - 2024. All rights reserved.