I have resource (music file) pointed by Uri. How can I check if it is available before I try to play it with MediaPlayer?
Its Uri is stored in database, so when the file
I too had this problem - I really wanted to check if a Uri was available before trying to load it, as unnecessary failures would end up crowding my Crashlytics logs.
Since the arrival of the StorageAccessFramework (SAF), DocumentProviders, etc., dealing with Uris has become more complicated. This is what I eventually used:
fun yourFunction() {
val uriToLoad = ...
val validUris = contentResolver.persistedUriPermissions.map { uri }
if (isLoadable(uriToLoad, validUris) != UriLoadable.NO) {
// Attempt to load the uri
}
}
enum class UriLoadable {
YES, NO, MAYBE
}
fun isLoadable(uri: Uri, granted: List): UriLoadable {
return when(uri.scheme) {
"content" -> {
if (DocumentsContract.isDocumentUri(this, uri))
if (documentUriExists(uri) && granted.contains(uri))
UriLoadable.YES
else
UriLoadable.NO
else // Content URI is not from a document provider
if (contentUriExists(uri))
UriLoadable.YES
else
UriLoadable.NO
}
"file" -> if (File(uri.path).exists()) UriLoadable.YES else UriLoadable.NO
// http, https, etc. No inexpensive way to test existence.
else -> UriLoadable.MAYBE
}
}
// All DocumentProviders should support the COLUMN_DOCUMENT_ID column
fun documentUriExists(uri: Uri): Boolean =
resolveUri(uri, DocumentsContract.Document.COLUMN_DOCUMENT_ID)
// All ContentProviders should support the BaseColumns._ID column
fun contentUriExists(uri: Uri): Boolean =
resolveUri(uri, BaseColumns._ID)
fun resolveUri(uri: Uri, column: String): Boolean {
val cursor = contentResolver.query(uri,
arrayOf(column), // Empty projections are bad for performance
null,
null,
null)
val result = cursor?.moveToFirst() ?: false
cursor?.close()
return result
}
If someone has a more elegant -- or correct -- alternative, please do comment.