我在Android 13版本手机上无法检索文件上传的真实路径

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

我使用此对象从所选文件的 URI 中获取其真实路径:

object RealPathUtil {
fun getRealPath(context: Context, fileUri: Uri): String? {
    val realPath: String?
    // SDK < API11
    realPath = if (Build.VERSION.SDK_INT < 11) {
        getRealPathFromURI_BelowAPI11(context, fileUri)
    } else if (Build.VERSION.SDK_INT < 19) {
        getRealPathFromURI_API11to18(context, fileUri)
    } else {
        getRealPathFromURI_API19(context, fileUri)
    }
    return realPath
}

@SuppressLint("NewApi")
fun getRealPathFromURI_API11to18(context: Context?, contentUri: Uri?): String? {
    val proj = arrayOf(MediaStore.Images.Media.DATA)
    var result: String? = null
    val cursorLoader = CursorLoader(
        context!!, contentUri!!, proj, null, null, null
    )
    val cursor = cursorLoader.loadInBackground()
    if (cursor != null) {
        val column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA)
        cursor.moveToFirst()
        result = cursor.getString(column_index)
        cursor.close()
    }
    return result
}

fun getRealPathFromURI_BelowAPI11(context: Context, contentUri: Uri?): String {
    val proj = arrayOf(MediaStore.Images.Media.DATA)
    val cursor = context.contentResolver.query(contentUri!!, proj, null, null, null)
    var column_index = 0
    var result = ""
    if (cursor != null) {
        column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA)
        cursor.moveToFirst()
        result = cursor.getString(column_index)
        cursor.close()
        return result
    }
    return result
}

/**
 * Get a file path from a Uri. This will get the the path for Storage Access
 * Framework Documents, as well as the _data field for the MediaStore and
 * other file-based ContentProviders.
 *
 * @param context The context.
 * @param uri     The Uri to query.
 * @author paulburke
 */
@SuppressLint("NewApi")
fun getRealPathFromURI_API19(context: Context, uri: Uri): String? {
    val isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT

    // DocumentProvider
    if (isKitKat && DocumentsContract.isDocumentUri(context, uri)) {
        // ExternalStorageProvider
        if (isExternalStorageDocument(uri)) {
            val docId = DocumentsContract.getDocumentId(uri)
            val split = docId.split(":".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()
            val type = split[0]
            if ("primary".equals(type, ignoreCase = true)) {
                return Environment.getExternalStorageDirectory().toString() + "/" + split[1]
            }
        } else if (isDownloadsDocument(uri)) {
            val id = DocumentsContract.getDocumentId(uri)
            val contentUri = ContentUris.withAppendedId(
                Uri.parse("content://downloads/public_downloads"), java.lang.Long.valueOf(id)
            )
            return getDataColumn(context, contentUri, null, null)
        } else if (isMediaDocument(uri)) {
            val docId = DocumentsContract.getDocumentId(uri)
            val split = docId.split(":".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()
            val type = split[0]
            var contentUri: Uri? = null
            if ("image" == type) {
                contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI
            } else if ("video" == type) {
                contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI
            } else if ("audio" == type) {
                contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI
            }
            val selection = "_id=?"
            val selectionArgs = arrayOf(
                split[1]
            )
            return getDataColumn(context, contentUri, selection, selectionArgs)
        }
    } else if ("content".equals(uri.scheme, ignoreCase = true)) {

        // Return the remote address
        return if (isGooglePhotosUri(uri)) uri.lastPathSegment else getDataColumn(
            context,
            uri,
            null,
            null
        )
    } else if ("file".equals(uri.scheme, ignoreCase = true)) {
        return uri.path
    }
    return null
}

/**
 * Get the value of the data column for this Uri. This is useful for
 * MediaStore Uris, and other file-based ContentProviders.
 *
 * @param context       The context.
 * @param uri           The Uri to query.
 * @param selection     (Optional) Filter used in the query.
 * @param selectionArgs (Optional) Selection arguments used in the query.
 * @return The value of the _data column, which is typically a file path.
 */
fun getDataColumn(
    context: Context, uri: Uri?, selection: String?,
    selectionArgs: Array<String>?
): String? {
    var cursor: Cursor? = null
    val column = "_data"
    val projection = arrayOf(
        column
    )
    try {
        cursor = context.contentResolver.query(
            uri!!, projection, selection, selectionArgs,
            null
        )
        if (cursor != null && cursor.moveToFirst()) {
            val index = cursor.getColumnIndexOrThrow(column)
            return cursor.getString(index)
        }
    } finally {
        cursor?.close()
    }
    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
}

/**
 * @param uri The Uri to check.
 * @return Whether the Uri authority is Google Photos.
 */
fun isGooglePhotosUri(uri: Uri): Boolean {
    return "com.google.android.apps.photos.content" == uri.authority
}}

在此方法中,Android 版本 13 设备返回 null 值。另一方面,在不同 Android 版本的设备中,我可以成功从 URI 检索真实路径。

您可以看到,在传递从文件选择中获取的 uri 后,我得到了 null 值:

有人可以建议我如何解决 Android 版本 13 手机上的文件上传问题吗?

android kotlin file-upload android-file android-version
1个回答
0
投票
fun getRealPath(context: Context, fileUri: Uri): String? {
    val contentResolver = context.contentResolver
    val projection = arrayOf(MediaStore.Images.Media.DATA)

    val cursor = contentResolver.query(fileUri, projection, null, null, null)

    return cursor?.use { c ->
        if (c.moveToFirst()) {
            val columnIndex = c.getColumnIndexOrThrow(MediaStore.Images.Media.DATA)
            c.getString(columnIndex)
        } else {
            null
        }
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.