How to check if resource pointed by Uri is available?

前端 未结 6 2283
说谎
说谎 2021-02-07 00:44

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

6条回答
  •  太阳男子
    2021-02-07 01:48

    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.

提交回复
热议问题