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? { 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 } }