Skip to content

Instantly share code, notes, and snippets.

@kiratheone
Forked from micer/RealPathUtil.kt
Created August 16, 2018 02:17
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kiratheone/00f88b05e2a0fdca61a8ad70c78642a8 to your computer and use it in GitHub Desktop.
Save kiratheone/00f88b05e2a0fdca61a8ad70c78642a8 to your computer and use it in GitHub Desktop.
Utility class to get real path from URI object - all API versions
import android.content.ContentUris
import android.content.Context
import android.database.Cursor
import android.net.Uri
import android.os.Build
import android.os.Environment
import android.provider.DocumentsContract
import android.provider.MediaStore
import android.support.v4.content.CursorLoader
import android.text.TextUtils
import com.github.ajalt.timberkt.e
object RealPathUtil {
fun getRealPath(context: Context, fileUri: Uri): String? {
val realPath: String?
if (Build.VERSION.SDK_INT < 11) {
// SDK < 11
realPath = RealPathUtil.getRealPathFromUriBelowAPI11(context, fileUri)
} else if (Build.VERSION.SDK_INT < 19) {
// SDK >= 11 && SDK < 19
realPath = RealPathUtil.getRealPathFromUriAPI11to18(context, fileUri)
} else {
// SDK > 19 (Android 4.4) and up
realPath = RealPathUtil.getRealPathFromUriAPI19(context, fileUri)
}
return realPath
}
private fun getRealPathFromUriAPI11to18(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
}
private fun getRealPathFromUriBelowAPI11(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
*/
private fun getRealPathFromUriAPI19(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)) {
val path = StringBuilder()
path.append(Environment.getExternalStorageDirectory())
path.append("/")
path.append(split[1])
return path.toString()
}
// TODO handle non-primary volumes
} else if (isDownloadsDocument(uri)) {
val id = DocumentsContract.getDocumentId(uri)
if (!TextUtils.isEmpty(id)) {
if (id.startsWith("raw:")) {
return id.replaceFirst("raw:", "");
}
return try {
val contentUri = ContentUris.withAppendedId(
Uri.parse("content://downloads/public_downloads"), java.lang.Long.valueOf(id))
getDataColumn(context, contentUri, null, null)
} catch (e: NumberFormatException) {
e(e)
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)
}// MediaProvider
// DownloadsProvider
} 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
}// File
// MediaStore (and general)
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.
*/
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 {
if (cursor != null)
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