使用Intent.createChooser选择文件时文件不存在

时间:2018-10-27 22:02:48

标签: android kotlin

要解决这个问题,我遇到了一个问题,我正在使用Intent.createChooser选择一个文件,并且我使用了各种不同的方法来获取文件的绝对路径,并且它们都会导致在content://downloads/public_downloads/1006中。

在仿真器中使用此路径可以很好地工作并产生预期的结果,但是当我在设备(Galaxy S9)上构建应用程序后,我收到一个错误消息,指出该文件不存在。

我已请求Manifest.permission.READ_EXTERNAL_STORAGEManifest.permission.WRITE_EXTERNAL_STORAGE的权限,并验证该权限已在应用程序中启用。

经过几个小时的搜索后,我没有足够的想法去尝试,如果有人能以正确的方式指导我,我会很高兴。

我当前用于获取绝对路径的方法是

private fun getAbsoluteFilePath(uri: Uri): String {
    val id = DocumentsContract.getDocumentId(uri)
    val contentUri = ContentUris.withAppendedId(Uri.parse("content://downloads/my_downloads"), id.toLong())

    val projection = arrayOf(MediaStore.Images.Media.DATA)
    val cursor = contentResolver.query(contentUri, projection, null, null, null)
    val columnIndex = cursor!!.getColumnIndexOrThrow(MediaStore.Images.Media.DATA)

    cursor.moveToFirst()

    return cursor.getString(columnIndex)
}   

但我也尝试过

object PathUtil {
    /*
     * Gets the file path of the given Uri.
     */
    @SuppressLint("NewApi")
    @Throws(URISyntaxException::class)
    fun getPath(context: Context, uri: Uri): String? {
        var uri = uri
        val needToCheckUri = Build.VERSION.SDK_INT >= 19
        var selection: String? = null
        var selectionArgs: Array<String>? = null

        // Uri is different in versions after KITKAT (Android 4.4), we need to
        // deal with different Uris.
        if (needToCheckUri && DocumentsContract.isDocumentUri(context.applicationContext, uri)) {
            if (isExternalStorageDocument(uri)) {
                val docId = DocumentsContract.getDocumentId(uri)
                val split = docId.split(":".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()

                return Environment.getExternalStorageDirectory().toString() + "/" + split[1]
            }

            if (isDownloadsDocument(uri)) {
                val id = DocumentsContract.getDocumentId(uri)
                uri = ContentUris.withAppendedId(Uri.parse("content://downloads/public_downloads"), java.lang.Long.valueOf(id))
            } else if (isMediaDocument(uri)) {
                val docId = DocumentsContract.getDocumentId(uri)
                val split = docId.split(":".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()
                val type = split[0]

                if ("image" == type) {
                    uri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI
                } else if ("video" == type) {
                    uri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI
                } else if ("audio" == type) {
                    uri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI
                }

                selection = "_id=?"
                selectionArgs = arrayOf(split[1])
            }
        }

        if ("content".equals(uri.scheme, ignoreCase = true)) {
            val projection = arrayOf(MediaStore.Images.Media.DATA)
            var cursor: Cursor? = null

            cursor = context.contentResolver.query(uri, projection, selection, selectionArgs, null)
            val columnIndex = cursor!!.getColumnIndexOrThrow(MediaStore.Images.Media.DATA)

            if (cursor!!.moveToFirst()) {
                return cursor!!.getString(columnIndex)
            }
        } else if ("file".equals(uri.scheme, ignoreCase = true)) {
            return uri.path
        }

        return null
    }


    /**
     * @param uri The Uri to check.
     * @return Whether the Uri authority is ExternalStorageProvider.
     */
    fun isExternalStorageDocument(uri: Uri): Boolean {
        return "com.android.externalstorage.documents" == uri.authority
    }

    /**
     * @param uri The Uri to check.
     * @return Whether the Uri authority is DownloadsProvider.
     */
    fun isDownloadsDocument(uri: Uri): Boolean {
        return "com.android.providers.downloads.documents" == uri.authority
    }

    /**
     * @param uri The Uri to check.
     * @return Whether the Uri authority is MediaProvider.
     */
    fun isMediaDocument(uri: Uri): Boolean {
        return "com.android.providers.media.documents" == uri.authority
    }
}

产生相同的结果,我的代码或多或少是这样的:

fun doSomething() {
    val intent = Intent().apply {
        action = Intent.ACTION_GET_CONTENT
        type = "*/*"
        addCategory(Intent.CATEGORY_OPENABLE)
    }

    val chooser = Intent.createChooser(intent, "Select")

    startActivityForResult(chooser, 1)
}

override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
    ZipFile(getAbsoluteFilePath(data.data))
}

哦,请不要重复进行此操作-我发现了很多类似的问题,但是还没有解决方案对我有用,不确定我所缺少的是什么,但我敢打赌这是愚蠢的

0 个答案:

没有答案