Skip to content

Instantly share code, notes, and snippets.

@MeNiks
Last active July 10, 2024 08:57
Show Gist options
  • Save MeNiks/947b471b762f3b26178ef165a7f5558a to your computer and use it in GitHub Desktop.
Save MeNiks/947b471b762f3b26178ef165a7f5558a to your computer and use it in GitHub Desktop.
Kotlin code to get real path / sd card path from intent data while browsing file.
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)
@Ramakrishna1064
Copy link

is it not java code?

@ArslanKathia
Copy link

can you provide this code in java!

@hai2san
Copy link

hai2san commented Jan 3, 2019

is it not java code?

package com.vakilsearch.libra.Common;

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;

public class RealPathUtil {

public static String getRealPath(Context context, Uri fileUri) {
    String realPath;
    // SDK < API11
    if (Build.VERSION.SDK_INT < 11) {
        realPath = RealPathUtil.getRealPathFromURI_BelowAPI11(context, fileUri);
    }
    // SDK >= 11 && SDK < 19
    else if (Build.VERSION.SDK_INT < 19) {
        realPath = RealPathUtil.getRealPathFromURI_API11to18(context, fileUri);
    }
    // SDK > 19 (Android 4.4) and up
    else {
        realPath = RealPathUtil.getRealPathFromURI_API19(context, fileUri);
    }
    return realPath;
}


@SuppressLint("NewApi")
public static String getRealPathFromURI_API11to18(Context context, Uri contentUri) {
    String[] proj = {MediaStore.Images.Media.DATA};
    String result = null;

    CursorLoader cursorLoader = new CursorLoader(context, contentUri, proj, null, null, null);
    Cursor cursor = cursorLoader.loadInBackground();

    if (cursor != null) {
        int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
        cursor.moveToFirst();
        result = cursor.getString(column_index);
        cursor.close();
    }
    return result;
}

public static String getRealPathFromURI_BelowAPI11(Context context, Uri contentUri) {
    String[] proj = {MediaStore.Images.Media.DATA};
    Cursor cursor = context.getContentResolver().query(contentUri, proj, null, null, null);
    int column_index = 0;
    String 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
 */
@SuppressLint("NewApi")
public static String getRealPathFromURI_API19(final Context context, final Uri uri) {

    final boolean isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT;

    // DocumentProvider
    if (isKitKat && DocumentsContract.isDocumentUri(context, uri)) {
        // ExternalStorageProvider
        if (isExternalStorageDocument(uri)) {
            final String docId = DocumentsContract.getDocumentId(uri);
            final String[] split = docId.split(":");
            final String type = split[0];

            if ("primary".equalsIgnoreCase(type)) {
                return Environment.getExternalStorageDirectory() + "/" + split[1];
            }

            // TODO handle non-primary volumes
        }
        // DownloadsProvider
        else if (isDownloadsDocument(uri)) {
            String fileName = getFilePath(context, uri);
            if (fileName != null) {
                return Environment.getExternalStorageDirectory().toString() + "/Download/" + fileName;
            }

            final String id = DocumentsContract.getDocumentId(uri);
            final Uri contentUri = ContentUris.withAppendedId(
                    Uri.parse("content://downloads/public_downloads"), Long.valueOf(id));
            return getDataColumn(context, contentUri, null, null);
        }
        // MediaProvider
        else if (isMediaDocument(uri)) {
            final String docId = DocumentsContract.getDocumentId(uri);
            final String[] split = docId.split(":");
            final String type = split[0];

            Uri contentUri = null;
            if ("image".equals(type)) {
                contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
            } else if ("video".equals(type)) {
                contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
            } else if ("audio".equals(type)) {
                contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
            }

            final String selection = "_id=?";
            final String[] selectionArgs = new String[]{
                    split[1]
            };

            return getDataColumn(context, contentUri, selection, selectionArgs);
        }
    }
    // MediaStore (and general)
    else if ("content".equalsIgnoreCase(uri.getScheme())) {

        // Return the remote address
        if (isGooglePhotosUri(uri))
            return uri.getLastPathSegment();

        return getDataColumn(context, uri, null, null);
    }
    // File
    else if ("file".equalsIgnoreCase(uri.getScheme())) {
        return uri.getPath();
    }

    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.
 */
public static String getDataColumn(Context context, Uri uri, String selection,
                                   String[] selectionArgs) {

    Cursor cursor = null;
    final String column = "_data";
    final String[] projection = {
            column
    };

    try {
        cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs,
                null);
        if (cursor != null && cursor.moveToFirst()) {
            final int index = cursor.getColumnIndexOrThrow(column);
            return cursor.getString(index);
        }
    } finally {
        if (cursor != null)
            cursor.close();
    }
    return null;
}


public static String getFilePath(Context context, Uri uri) {

    Cursor cursor = null;
    final String[] projection = {
            MediaStore.MediaColumns.DISPLAY_NAME
    };

    try {
        cursor = context.getContentResolver().query(uri, projection, null, null,
                null);
        if (cursor != null && cursor.moveToFirst()) {
            final int index = cursor.getColumnIndexOrThrow(MediaStore.MediaColumns.DISPLAY_NAME);
            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.
 */
public static boolean isExternalStorageDocument(Uri uri) {
    return "com.android.externalstorage.documents".equals(uri.getAuthority());
}

/**
 * @param uri The Uri to check.
 * @return Whether the Uri authority is DownloadsProvider.
 */
public static boolean isDownloadsDocument(Uri uri) {
    return "com.android.providers.downloads.documents".equals(uri.getAuthority());
}

/**
 * @param uri The Uri to check.
 * @return Whether the Uri authority is MediaProvider.
 */
public static boolean isMediaDocument(Uri uri) {
    return "com.android.providers.media.documents".equals(uri.getAuthority());
}

/**
 * @param uri The Uri to check.
 * @return Whether the Uri authority is Google Photos.
 */
public static boolean isGooglePhotosUri(Uri uri) {
    return "com.google.android.apps.photos.content".equals(uri.getAuthority());
}

}

@manthri-mohan-sai
Copy link

It works (I have tested this till 8.1), Thanks

@brucemax
Copy link

Good job! Thanks!!!

@sanketmthakare
Copy link

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>

@shahrukhamd
Copy link

Works for me too. Thanks!

@AlexBerz
Copy link

What's context? How do I get it?

@dkpapo
Copy link

dkpapo commented Apr 13, 2020

thanx works for me in android 8 i love you :3

@onimur
Copy link

onimur commented May 26, 2020

What's context? How do I get it?

you pass the application context

@Bajranghudda
Copy link

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
                    }

@onimur
Copy link

onimur commented Jun 25, 2020

I created a library to facilitate the handling of Intent (Uri) received. It can be found here.

@Victortorresf
Copy link

Victortorresf commented Jan 5, 2021

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")
    }`

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment