-
-
Save MeNiks/947b471b762f3b26178ef165a7f5558a to your computer and use it in GitHub Desktop.
import android.annotation.SuppressLint | |
import android.content.ContentUris | |
import android.content.Context | |
import android.content.CursorLoader | |
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.text.TextUtils | |
object RealPathUtil { | |
fun getRealPath(context: Context, fileUri: Uri): String? { | |
// SDK >= 11 && SDK < 19 | |
return if (Build.VERSION.SDK_INT < 19) { | |
getRealPathFromURIAPI11to18(context, fileUri) | |
} else { | |
getRealPathFromURIAPI19(context, fileUri) | |
}// SDK > 19 (Android 4.4) and up | |
} | |
@SuppressLint("NewApi") | |
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 columnIndex = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA) | |
cursor.moveToFirst() | |
result = cursor.getString(columnIndex) | |
cursor.close() | |
} | |
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 Niks | |
*/ | |
@SuppressLint("NewApi") | |
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)) { | |
return Environment.getExternalStorageDirectory().toString() + "/" + split[1] | |
} | |
} else if (isDownloadsDocument(uri)) { | |
var cursor: Cursor? = null | |
try { | |
cursor = context.contentResolver.query(uri, arrayOf(MediaStore.MediaColumns.DISPLAY_NAME), null, null, null) | |
cursor!!.moveToNext() | |
val fileName = cursor.getString(0) | |
val path = Environment.getExternalStorageDirectory().toString() + "/Download/" + fileName | |
if (!TextUtils.isEmpty(path)) { | |
return path | |
} | |
} finally { | |
cursor?.close() | |
} | |
val id = DocumentsContract.getDocumentId(uri) | |
if (id.startsWith("raw:")) { | |
return id.replaceFirst("raw:".toRegex(), "") | |
} | |
val contentUri = ContentUris.withAppendedId(Uri.parse("content://downloads"), java.lang.Long.valueOf(id)) | |
return getDataColumn(context, contentUri, null, 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 | |
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) | |
}// 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. | |
* @author Niks | |
*/ | |
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 | |
} | |
/** | |
* @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 | |
} | |
} |
// Extension on intent | |
fun Intent?.getFilePath(context: Context): String { | |
return this?.data?.let { data -> RealPathUtil.getRealPath(context, data) ?: "" } ?: "" | |
} | |
fun Uri?.getFilePath(context: Context): String { | |
return this?.let { uri -> RealPathUtil.getRealPath(context, uri) ?: "" } ?: "" | |
} | |
fun ClipData.Item?.getFilePath(context: Context): String { | |
return this?.uri?.getFilePath(context) ?: "" | |
} | |
// Usage | |
val selectedPath = intent.getFilePath(context) |
Good job! Thanks!!!
this doesnt work when opening a file from google chrome downloads on api > 19 with a uri of something like this content://com.android.chrome.FileProvider/downloads/<some_file_name>
Works for me too. Thanks!
What's context? How do I get it?
thanx works for me in android 8 i love you :3
What's context? How do I get it?
you pass the application context
This is not working if we are selecting a file from the download folder and if that file is downloaded from google drive. I am getting the path from the below code if the file does not exist.
cursor = context.contentResolver.query(uri, arrayOf(MediaStore.MediaColumns.DISPLAY_NAME), null, null, null)
cursor!!.moveToNext()
val fileName = cursor.getString(0)
val path = Environment.getExternalStorageDirectory().toString() + "/Download/" + fileName
if (!TextUtils.isEmpty(path)) {
return path
}
I created a library to facilitate the handling of Intent (Uri) received. It can be found here.
thanks for the code,
if i want to retrieve an audio file and use it on a media player how can i pass the audio to mediaPlayer.create?
Below is the code i have where i create and initiate the player
`
private fun controlSound(id: Uri){
fab_play.setOnClickListener{
if (mp == null){
mp = MediaPlayer.create(this, id)
Log.d("MediaPlayer", "ID: ${mp!!.audioSessionId}")
initialiseSeekBar()
}
mp?.start()
Log.d("MediaPlayer", "Duration: ${mp!!.duration/1000} seconds")
}`
It works (I have tested this till 8.1), Thanks