Get Path From URI In Kotlin Android

When we pick an image, video, audio, or any other file from the gallery or documents directory we receive URI in intent in the onActivityResult(...) method. So we always further required to get a full file path from that URI. If we directly try to get the path through URI.getData() method, it doesn’t serve the purpose as it provides FileManager address but not the full file path present in the external storage. The following utility class will help you to Get Path From URI In Kotlin Android.

Utility Class to Get Path From URI In Kotlin

Just create a new file with name URIPathHelper.kt. Then copy and paste the following Utility class in your file. It covers all scenarios and works perfectly for all Android versions. Its explanation will be discussed later.

package com.mvp.handyopinion

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

class URIPathHelper {

    fun getPath(context: Context, uri: Uri): String? {
        val isKitKatorAbove = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT

        // DocumentProvider
        if (isKitKatorAbove && DocumentsContract.isDocumentUri(context, uri)) {
            // ExternalStorageProvider
            if (isExternalStorageDocument(uri)) {
                val docId = DocumentsContract.getDocumentId(uri)
                val split = docId.split(":".toRegex()).toTypedArray()
                val type = split[0]
                if ("primary".equals(type, ignoreCase = true)) {
                    return Environment.getExternalStorageDirectory().toString() + "/" + split[1]
                }

            } 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 getDataColumn(context, contentUri, null, null)
            } else if (isMediaDocument(uri)) {
                val docId = DocumentsContract.getDocumentId(uri)
                val split = docId.split(":".toRegex()).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)
            }
        } else if ("content".equals(uri.scheme, ignoreCase = true)) {
            return getDataColumn(context, uri, null, null)
        } else if ("file".equals(uri.scheme, ignoreCase = true)) {
            return uri.path
        }
        return null
    }

    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.getContentResolver().query(uri, projection, selection, selectionArgs,null)
            if (cursor != null && cursor.moveToFirst()) {
                val column_index: Int = cursor.getColumnIndexOrThrow(column)
                return cursor.getString(column_index)
            }
        } finally {
            if (cursor != null) cursor.close()
        }
        return null
    }

    fun isExternalStorageDocument(uri: Uri): Boolean {
        return "com.android.externalstorage.documents" == uri.authority
    }

    fun isDownloadsDocument(uri: Uri): Boolean {
        return "com.android.providers.downloads.documents" == uri.authority
    }

    fun isMediaDocument(uri: Uri): Boolean {
        return "com.android.providers.media.documents" == uri.authority
    }
}

How to Use URIPathHelper class to get path from URI

val uriPathHelper = URIPathHelper()
val filePath = uriPathHelper.getPath(this, YOUR_URI_OBJECT)

Explanation

In the above class, the getPath(…) method is our main method, which uses other methods and finds the path from the given URI. Firstly, it checks the current Android Version, because there is a separate mechanism for getting path from URI in the versions below Kitkat (4.4) and above it. In the versions above the Kitkat, we have to implement a separate logic for different file types, either they are picked from documents directory, Gallery, or downloads folder.

In the User’s Android version is less than Kitkat then getDataColumn(...) method will serve the purpose as gets the file path using ContentResolver.

That’s it. Enjoy 🙂

Next: Pick Image From Gallery in Kotlin – Android

Please share this post:
Native Mobile Application Developer (Android + IOS) having experience in Java, Swift, Kotlin, Objective C, Unity, C#, C/C++, NODE JS & PHP.

One thought on “Get Path From URI In Kotlin Android

Ask a Question

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Related Posts

Begin typing your search term above and press enter to search. Press ESC to cancel.

%d bloggers like this: