Last active
July 5, 2019 11:21
-
-
Save jishindev/a28d3f76e80564bccf5f54ea09cd829b to your computer and use it in GitHub Desktop.
Extensions to resolve file paths from uri on Android
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
fun isExternalStorageDocument(uri: Uri) = "com.android.externalstorage.documents" == uri.authority | |
fun isDownloadsDocument(uri: Uri) = "com.android.providers.downloads.documents" == uri.authority | |
fun isMediaDocument(uri: Uri) = "com.android.providers.media.documents" == uri.authority | |
/** | |
* 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 | |
*/ | |
fun Uri.getPath(context: Context): String? { | |
val uri = this | |
// DocumentProvider | |
if (DocumentsContract.isDocumentUri(context, this)) { | |
// ExternalStorageProvider | |
if (isExternalStorageDocument(uri)) { | |
val docId = DocumentsContract.getDocumentId(uri) | |
val split = docId.split(":").toTypedArray() | |
val type = split[0] | |
if ("primary".equals(type, ignoreCase = true)) { | |
return Environment.getExternalStorageDirectory().absolutePath + "/" + split[1] | |
} | |
// TODO handle non-primary volumes | |
} 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 contentUri?.getDataColumn(null, null) | |
} else if (isMediaDocument(uri)) { | |
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 | |
"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 contentUri?.getDataColumn(selection, selectionArgs) | |
}// MediaProvider | |
// DownloadsProvider | |
} else if ("content".equals(uri.scheme, ignoreCase = true)) { | |
return uri.getDataColumn(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 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 Uri.getDataColumn( | |
selection: String?, | |
selectionArgs: Array<String>?, | |
contentResolver: ContentResolver = appCtx.contentResolver | |
): String? { | |
var cursor: Cursor? = null | |
val column = "_data" | |
val projection = arrayOf(column) | |
try { | |
cursor = contentResolver.query(this, projection, selection, selectionArgs, null) | |
if (cursor?.moveToFirst() == true) { | |
val columnIndex = cursor.getColumnIndexOrThrow(column) | |
return cursor.getString(columnIndex) | |
} | |
} finally { | |
cursor?.close() | |
} | |
return null | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment