How can I get Absolute file path at started content:// type Uri on Non-Media Type

287 Views Asked by At

The problem is that, for security reasons, we know that the absolute path of a file cannot be obtained directly from a uri starting with content://. So I solved the problem by using the library and applying it to media type files starting with content://. However, in the case of a file such as pdf that is not a media type, it is not converted properly. Is there any way I can add this to my code?

class UriPathUtils{
fun getRealPathFromURI(context: Context, uri: Uri): String? {
    when {
        // DocumentProvider
        DocumentsContract.isDocumentUri(context, uri) -> {
            when {
                // ExternalStorageProvider
                isExternalStorageDocument(uri) -> {
                    //Toast.makeText(context, "From Internal & External Storage dir", Toast.LENGTH_SHORT).show()
                    val docId = DocumentsContract.getDocumentId(uri)
                    val split = docId.split(":").toTypedArray()
                    val type = split[0]
                    // This is for checking Main Memory
                    return if ("primary".equals(type, ignoreCase = true)) {
                        if (split.size > 1) {
                            Environment.getExternalStorageDirectory().toString() + "/" + split[1]
                        } else {
                            Environment.getExternalStorageDirectory().toString() + "/"
                        }
                        // This is for checking SD Card
                    } else {
                        "storage" + "/" + docId.replace(":", "/")
                    }
                }
                isDownloadsDocument(uri) -> {
                    //Toast.makeText(context, "From Downloads dir", Toast.LENGTH_SHORT).show()
                    val fileName = getFilePath(context, uri)
                    if (fileName != null) {
                        return Environment.getExternalStorageDirectory().toString() + "/Download/" + fileName
                    }
                    var id = DocumentsContract.getDocumentId(uri)
                    if (id.startsWith("raw:")) {
                        id = id.replaceFirst("raw:".toRegex(), "")
                        val file = File(id)
                        if (file.exists()) return id
                    }
                    val contentUri = ContentUris.withAppendedId(Uri.parse("content://downloads/public_downloads"), java.lang.Long.valueOf(id))
                    return getDataColumn(context, contentUri, null, null)
                }
                isMediaDocument(uri) -> {
                    //Toast.makeText(context, "From Documents dir", Toast.LENGTH_SHORT).show()
                    val docId = DocumentsContract.getDocumentId(uri)
                    val split = docId.split(":").toTypedArray()
                    val type = split[0]
                    var contentUri: Uri? = null
                    when (type) {
                        "image" -> {
                            contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI
                            Log.d("image_file_contentUri", contentUri.toString())
                        }
                        "video" -> {
                            contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI
                        }
                        "audio" -> {
                            contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI
                        }
                        else -> {
                            //non-media files i.e documents and other files
                            contentUri = MediaStore.Files.getContentUri("external")
                            Log.d("document_fil_contentUri", contentUri.toString())
                            val selection =
                            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
                                MediaStore.MediaColumns.RELATIVE_PATH + "=?"
                            } else "_id=?"

                            val selectionArgs = arrayOf(Environment.DIRECTORY_DOCUMENTS)

                            Log.d("document_file_selection", selection)
                            Log.d("document_file_selArgs", selectionArgs.toString())

                            return getMediaDocumentPath(context, contentUri,selection,selectionArgs)
                        }
                    }
                    val selection = "_id=?"
                    val selectionArgs = arrayOf(split[1])
                    Log.d("image_file_selection", selection)
                    Log.d("image_file_selArgs", selectionArgs.toString())
                    return getDataColumn(context, contentUri, selection, selectionArgs)
                }
                isGoogleDriveUri(uri) -> {
                    Toast.makeText(context, "From Google Drive", Toast.LENGTH_SHORT).show()
                    return getDriveFilePath(uri, context)
                }
            }
        }
        "content".equals(uri.scheme, ignoreCase = true) -> {
            //Toast.makeText(context, "From Content Uri", Toast.LENGTH_SHORT).show()
            // Return the remote address
            return if (isGooglePhotosUri(uri)) uri.lastPathSegment else getDataColumn(context, uri, null, null)
        }
        "file".equals(uri.scheme, ignoreCase = true) -> {
            //Toast.makeText(context, "From File Uri", Toast.LENGTH_SHORT).show()
            return uri.path
        }
    }
    return null
}

private fun getDataColumn(context: Context, uri: Uri?, selection: String?, selectionArgs: Array<String>?): String? {
    var cursor: Cursor? = null
    val column = "_data"
    val projection = arrayOf(column)
    try {
        if (uri == null) return null
        cursor = context.contentResolver.query(uri, projection, selection, selectionArgs, null)

        Log.d("image_file_cursor", cursor.toString())

        //여기서부터 갈림
        if (cursor != null && cursor.moveToFirst()) {
            val index = cursor.getColumnIndexOrThrow(column)

            Log.d("image_file_index", index.toString())
            Log.d("image_file_return", cursor.getString(index).toString())
            return cursor.getString(index)
        }
    } finally {
        cursor?.close()
    }
    return null
}


private fun getMediaDocumentPath(context: Context, uri: Uri?,selection: String?, selectionArgs: Array<String>?): String? {
    var cursor: Cursor? = null
    val column = "_data"
    val projection = arrayOf(column)
    try {
        if (uri == null) return null
        cursor = context.contentResolver.query(uri, projection, selection, selectionArgs, null)

        Log.d("document_file_cursor", cursor.toString())

        if (cursor != null && cursor.moveToFirst()) {
            val index = cursor.getColumnIndexOrThrow(column)
            Log.d("document_file_index", index.toString())
            Log.d("document_file_return", cursor.getString(index).toString())
            return cursor.getString(index)
        }
    } finally {
        cursor?.close()
    }
    return null
}






private fun getFilePath(context: Context, uri: Uri?): String? {
    var cursor: Cursor? = null
    val projection = arrayOf(MediaStore.MediaColumns.DISPLAY_NAME)
    try {
        if (uri == null) return null
        cursor = context.contentResolver.query(uri, projection, null, null,
            null)
        if (cursor != null && cursor.moveToFirst()) {
            val index = cursor.getColumnIndexOrThrow(MediaStore.MediaColumns.DISPLAY_NAME)
            return cursor.getString(index)
        }
    } finally {
        cursor?.close()
    }
    return null
}

private fun getDriveFilePath(uri: Uri, context: Context): String? {
    val returnCursor = context.contentResolver.query(uri, null, null, null, null)
    val nameIndex = returnCursor!!.getColumnIndex(OpenableColumns.DISPLAY_NAME)
    val sizeIndex = returnCursor.getColumnIndex(OpenableColumns.SIZE)
    returnCursor.moveToFirst()
    val name = returnCursor.getString(nameIndex)
    val size = returnCursor.getLong(sizeIndex).toString()
    val file = File(context.cacheDir, name)
    try {
        val inputStream = context.contentResolver.openInputStream(uri)
        val outputStream = FileOutputStream(file)
        var read = 0
        val maxBufferSize = 1 * 1024 * 1024
        val bytesAvailable = inputStream!!.available()

        //int bufferSize = 1024;
        val bufferSize = Math.min(bytesAvailable, maxBufferSize)
        val buffers = ByteArray(bufferSize)
        while (inputStream.read(buffers).also { read = it } != -1) {
            outputStream.write(buffers, 0, read)
        }
        Log.e("File Size", "Size " + file.length())
        inputStream.close()
        outputStream.close()
        Log.e("File Path", "Path " + file.path)
        Log.e("File Size", "Size " + file.length())
    } catch (e: Exception) {
        Log.e("Exception", e.message!!)
    }
    return file.path
}

/**
 * @param uri The Uri to check.
 * @return Whether the Uri authority is ExternalStorageProvider.
 */
private 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.
 */
private 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.
 */
private 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.
 */
private fun isGooglePhotosUri(uri: Uri): Boolean {
    return "com.google.android.apps.photos.content" == uri.authority
}

/**
 * @param uri The Uri to check.
 * @return Whether the Uri authority is Google Photos.
 */
private fun isGoogleDriveUri(uri: Uri): Boolean {
    return "com.google.android.apps.docs.storage" == uri.authority || "com.google.android.apps.docs.storage.legacy" == uri.authority
}

}

image file upload

enter image description here

enter image description here

pdf file upload

enter image description here

enter image description here

0

There are 0 best solutions below