Skip to content

Instantly share code, notes, and snippets.

@ImaginativeShohag
Last active October 20, 2023 16:40
Show Gist options
  • Save ImaginativeShohag/4e53572141c017369941bbbaac538576 to your computer and use it in GitHub Desktop.
Save ImaginativeShohag/4e53572141c017369941bbbaac538576 to your computer and use it in GitHub Desktop.
Real Path Utility class for Android. Tested till API 33. Java Version of this: https://gist.github.com/ImaginativeShohag/476a5ba87824f6e036f6bce10e229079
import android.content.ContentUris
import android.content.Context
import android.database.Cursor
import android.net.Uri
import android.os.Environment
import android.provider.DocumentsContract
import android.provider.MediaStore
/**
* Real Path Utility class for Android.
*
* Updated by @ImaginativeShohag
*
* Source: https://gist.github.com/ImaginativeShohag/4e53572141c017369941bbbaac538576
*/
object RealPathUtil {
fun getRealPath(context: Context, uri: Uri): String? {
// ----------------------------------------------------------------
// DocumentProvider
// ----------------------------------------------------------------
if (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]
// ----------------------------------------------------------------
// 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() + "/"
}
} else {
// ----------------------------------------------------------------
// This is for checking SD Card
// ----------------------------------------------------------------
"storage" + "/" + docId.replace(":", "/")
}
} else if (isDownloadsDocument(uri)) {
// ----------------------------------------------------------------
// DownloadsProvider
// ----------------------------------------------------------------
val fileName = getFilePath(context, uri)
if (fileName != null) {
return Environment.getExternalStorageDirectory()
.toString() + "/Download/" + fileName
}
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)) {
// ----------------------------------------------------------------
// MediaProvider
// ----------------------------------------------------------------
val docId = DocumentsContract.getDocumentId(uri)
val split = docId.split(":".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()
val type = split[0]
var contentUri: Uri? = null
when (type) {
"image" -> {
contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI
}
"video" -> {
contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI
}
"audio" -> {
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)) {
// ----------------------------------------------------------------
// MediaStore (and general)
// ----------------------------------------------------------------
// Return the remote address
return if (isGooglePhotosUri(uri)) {
uri.lastPathSegment
} else {
getDataColumn(
context,
uri,
null,
null
)
}
} else if ("file".equals(uri.scheme, ignoreCase = true)) {
// ----------------------------------------------------------------
// File
// ----------------------------------------------------------------
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 {
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
}
private fun getFilePath(context: Context, uri: Uri): String? {
var cursor: Cursor? = null
val projection = arrayOf(MediaStore.MediaColumns.DISPLAY_NAME)
try {
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
}
/**
* @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
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment