android 如何访问给定内容URI的目录中的文件?

bpzcxfmw  于 2022-12-02  发布在  Android
关注(0)|答案(3)|浏览(450)

我的问题与this question非常相似。我使用ACTION_OPEN_DOCUMENT_TREE获得了一个目录的内容URI。

content://com.android.externalstorage.documents/tree/primary%3ASHAREit%2Fpictures

作为选择目录的结果。现在,我的问题是我如何访问目录内的所有文件(最好是子目录)。

svmlkihl

svmlkihl1#

使用DocumentFile.fromTreeUri()为您的树创建a DocumentFile。然后,使用listFiles()获取该树中的文档和子树的列表。对于isDirectory()返回true的文档和子树,您可以进一步遍历树。对于其余的文档和子树,使用getUri()获取Uri。如果需要的话,您可以在ContentResolver上使用openInputStream()来获取内容。

nwo49xxi

nwo49xxi2#

我是Android开发的新手,在很长一段时间里一直在理解CommonsWare的答案(以及其他资源)。
1.您需要DocumentFile AndroidX library,因此将其添加到您的build.gradle

implementation "androidx.documentfile:documentfile:1.0.1"

1.获得包含tree的内容URI后,可以使用DocumentFile.fromTreeUri

val filenamesToDocumentFile = mutableMapOf<String, DocumentFile>()
        val documentsTree = DocumentFile.fromTreeUri(context, treeUri) ?: return
        val childDocuments = documentsTree.listFiles()
        for (childDocument in childDocuments) {
            childDocuments[0].name?.let {
            filenamesToDocumentFile[it] = childDocument
            }
        }

现在我开始弄清楚如何使用这个DocumentFile...(提示:(一个月三个月一次)

xpszyzbs

xpszyzbs3#

下面是与@CommonsWare answer相关的代码片段。
使用Intent.ACTION_OPEN_DOCUMENT_TREE启动文件选取器

startActivityForResult(
    Intent.createChooser(Intent(Intent.ACTION_OPEN_DOCUMENT_TREE), "Choose directory"),
    IMPORT_FILE_REQUEST
)

从文件选取器接收所选目录的Uri

override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
    when (requestCode) {
        IMPORT_FILE_REQUEST -> {
            if (resultCode != Activity.RESULT_OK) return
            val uri = data?.data ?: return
            // get children uri from the tree uri
            val childrenUri =
                DocumentsContract.buildChildDocumentsUriUsingTree(
                    uri,
                    DocumentsContract.getTreeDocumentId(uri)
                )
            // get document file from children uri
            val tree = DocumentFile.fromTreeUri(this, childrenUri)
            // get the list of the documents
            tree?.listFiles()?.forEach { doc ->
                // get the input stream of a single document
                val iss = contentResolver.openInputStream(doc.uri)
                // prepare the output stream
                val oss = FileOutputStream(File(filesDir, doc.name))
                // copy the file
                CopyFile { result ->
                    println("file copied? $result")
                }.execute(iss, oss)
            }
        }
    }
}

使用AsyncTask复制文件(随意使用线程、协程..)

class CopyFile(val callback: (Boolean) -> Unit) :
    AsyncTask<Closeable, Int, Boolean>() {
    override fun doInBackground(vararg closeables: Closeable): Boolean {
        if (closeables.size != 2) throw IllegalArgumentException("two arguments required: input stream and output stream")
        try {
            (closeables[0] as InputStream).use { iss ->
                (closeables[1] as OutputStream).use { oss ->
                    iss.copyTo(oss)
                    return true
                }
            }
        } catch (e: Exception) {
            e.printStackTrace()
        }
        return false
    }

    override fun onPostExecute(result: Boolean) {
        callback.invoke(result)
    }
}

相关问题