Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Real Path Utility class for Android, works for all API
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)) {
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;
}
/**
* @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());
}
}
@kazimdsaidul

This comment has been minimized.

Copy link

kazimdsaidul commented Jan 31, 2018

Thanks for sharing. You save my time.

@vinayAryabhat

This comment has been minimized.

Copy link

vinayAryabhat commented Feb 6, 2018

Thanks for sharing :) works perfectly

@sameer43210

This comment has been minimized.

Copy link

sameer43210 commented Feb 27, 2018

hi,
Thanks for sharing .
Code is not working in android nougot 7.0 ,any suggestions

@imrankst1221

This comment has been minimized.

Copy link

imrankst1221 commented Mar 8, 2018

What will happen if the storage is a memory card? non-primary get's null if using this method in Android L. Do you have any solutions for it?

@nathansdev

This comment has been minimized.

Copy link

nathansdev commented Mar 14, 2018

isGooglePhotosUri method should compare with "com.google.android.apps.photos.contentprovider" not with "com.google.android.apps.photos.content"

@potatola

This comment has been minimized.

Copy link

potatola commented Apr 1, 2018

Works like a charm. Thanks for sharing :)

@basicodemine

This comment has been minimized.

Copy link

basicodemine commented Apr 7, 2018

Thanks you so much :)

@grebulon

This comment has been minimized.

Copy link

grebulon commented Apr 16, 2018

What about contacts uri, such as: content://com.android.contacts/contacts/as_vcard/3231i200 ?
In this case there is no real path. You need to do something like:
AssetFileDescriptor afd = ctx.getContentResolver().openAssetFileDescriptor(uri, "r");
InputStream is = afd.createInputStream();
and perhaps write it to a temp file.

@julianlopezv

This comment has been minimized.

Copy link

julianlopezv commented Apr 18, 2018

Gracias, era justo lo que necesitaba. Funciona perfecto!.

@lovelyelfpop

This comment has been minimized.

Copy link

lovelyelfpop commented May 16, 2018

/**
 * Get external sd card path using reflection
 * @param mContext
 * @param is_removable is external storage removable
 * @return
 */
private static String getExternalStoragePath(Context mContext, boolean is_removable) {

    StorageManager mStorageManager = (StorageManager) mContext.getSystemService(Context.STORAGE_SERVICE);
    Class<?> storageVolumeClazz = null;
    try {
        storageVolumeClazz = Class.forName("android.os.storage.StorageVolume");
        Method getVolumeList = mStorageManager.getClass().getMethod("getVolumeList");
        Method getPath = storageVolumeClazz.getMethod("getPath");
        Method isRemovable = storageVolumeClazz.getMethod("isRemovable");
        Object result = getVolumeList.invoke(mStorageManager);
        final int length = Array.getLength(result);
        for (int i = 0; i < length; i++) {
            Object storageVolumeElement = Array.get(result, i);
            String path = (String) getPath.invoke(storageVolumeElement);
            boolean removable = (Boolean) isRemovable.invoke(storageVolumeElement);
            if (is_removable == removable) {
                return path;
            }
        }
    } catch (ClassNotFoundException e) {
        e.printStackTrace();
    } catch (InvocationTargetException e) {
        e.printStackTrace();
    } catch (NoSuchMethodException e) {
        e.printStackTrace();
    } catch (IllegalAccessException e) {
        e.printStackTrace();
    }
    return null;
}
@vuhung3990

This comment has been minimized.

Copy link

vuhung3990 commented May 24, 2018

it not work on android O if use file provider

@Sinarahimi

This comment has been minimized.

Copy link

Sinarahimi commented Jul 4, 2018

Could you add the imports so we know which one should I import? For example, I have to import for CursorLoader
Thank you

@micer

This comment has been minimized.

Copy link

micer commented Aug 6, 2018

I've created a gist that is converted to Kotlin and handles NumberFormatException that can occur on API 28:

https://gist.github.com/micer/ae5de2984dbbdb386dd262782cfdb39c

@arranlomas

This comment has been minimized.

Copy link

arranlomas commented Sep 22, 2018

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>

@Mudassir25

This comment has been minimized.

Copy link

Mudassir25 commented Oct 3, 2018

This doesn't work on API 28 for URI content://com.android.providers.downloads.documents/document/19.
getDataColumn() giving IllegalArgumentException unknown URI.
Device Pixel.

@MeNiks

This comment has been minimized.

Copy link

MeNiks commented Oct 9, 2018

@Mudassir25 I have handled downloads.document uri issue checkout may be this will help you https://gist.github.com/MeNiks/947b471b762f3b26178ef165a7f5558a

@skfaisal93

This comment has been minimized.

Copy link

skfaisal93 commented Oct 18, 2018

@Sinarahimi @Mudassir25
Some people are asking for imports and some are facing 'NumberFormatException'. Handled both in java
https://gist.github.com/skfaisal93/26129b73a0c49fdc0b4bfae4b58e82d9

@asif84468

This comment has been minimized.

Copy link

asif84468 commented Oct 27, 2018

still Doesn't work : java.lang.IllegalArgumentException: Unknown URI: content://downloads/public_downloads/3853
Occurs in rooted oreo.

Is there any solution for this yet ?

@zainriaz

This comment has been minimized.

Copy link

zainriaz commented Nov 6, 2018

thanks man! works like a charm. also working with android nougot 7.0.

@sergey-dovzhenko

This comment has been minimized.

Copy link

sergey-dovzhenko commented Nov 15, 2018

java.lang.IllegalArgumentException: column '_data' does not exist
help me please

@a92c

This comment has been minimized.

Copy link

a92c commented Dec 7, 2018

Caused by: java.lang.IllegalArgumentException: Unknown URI: content://downloads/public_downloads/
Android oreo e Pie
Google Pixel 2

@aahmetbas

This comment has been minimized.

Copy link

aahmetbas commented Dec 8, 2018

Huawei HUAWEI Y6 2018 (HWATU-QG), Android 8.0
Sony Xperia L1 (G3311), Android 7.0
Oppo A37f (A37f), Android 5.1

Caused by: java.lang.IllegalArgumentException:
at android.database.AbstractCursor.getColumnIndexOrThrow (AbstractCursor.java:333)
at android.database.CursorWrapper.getColumnIndexOrThrow (CursorWrapper.java:87)
at .utils.RealPath.getDataColumn (RealPath.java:168)

in your code getDataColumn (RealPath.java:153)

@hai2san

This comment has been minimized.

Copy link

hai2san commented Dec 18, 2018

Thanks lot. Its saved my time... :-)

@c4rking

This comment has been minimized.

Copy link

c4rking commented Dec 19, 2018

API 28
// DownloadsProvider
else if (isDownloadsDocument(uri)) {
String fileName = getFileName(context, uri);
return Environment.getExternalStorageDirectory().toString() + "/Download/" + fileName;
}
++
public static String getName(String filename) {
if (filename == null) {
return null;
}
int index = filename.lastIndexOf('/');
return filename.substring(index + 1);
}

@MartinezSDiego

This comment has been minimized.

Copy link

MartinezSDiego commented Jan 14, 2019

Thank you¡¡ It is genial

@IlyaLavrov97

This comment has been minimized.

Copy link

IlyaLavrov97 commented Jan 21, 2019

I faced with app's private download folders issue. Sometimes file path cannot be defined when it's location not a public download folder.

It's solution for Xamarin.Android -- https://gist.github.com/IlyaLavrov97/a76063a49515764b60d5fba3ebbb2662

@Ravslee

This comment has been minimized.

Copy link

Ravslee commented Jan 28, 2019

Perfect !!!

@Satyawan007

This comment has been minimized.

Copy link

Satyawan007 commented Feb 17, 2019

If file selecting from Google drive how to access real path and displays in installed applications through intent.

@IlyaLavrov97

This comment has been minimized.

Copy link

IlyaLavrov97 commented Feb 27, 2019

@Satyawan007 My gist for Xamarin.Android has been updated. For actual path access, we need to transfer the file to cacheDir and return AbsolutePath.
If you still need a solution -- https://gist.github.com/IlyaLavrov97/a76063a49515764b60d5fba3ebbb2662

@binodsarkar

This comment has been minimized.

Copy link

binodsarkar commented Mar 9, 2019

This is not working when I am choosing csv file. Can you please check it

@HariharanEswaran

This comment has been minimized.

Copy link

HariharanEswaran commented May 10, 2019

Thanks.Source is not working above android N please help me !

@sanketmthakare

This comment has been minimized.

Copy link

sanketmthakare commented Jul 15, 2019

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>

any body got the solution for this problem. I am getting null value.

@sanketmthakare

This comment has been minimized.

Copy link

sanketmthakare commented Jul 19, 2019

Thanks.Source is not working above android N please help me !
any one got the solution for this problem. please reply

@aj-shinde

This comment has been minimized.

Copy link

aj-shinde commented Jul 30, 2019

just add the below code in catch block when catching the illigalArgumentException

File file = new File(context.getCacheDir(), "tmp");
String filePath = file.getAbsolutePath();

        try {
	        ParcelFileDescriptor pfd = context.getContentResolver().openFileDescriptor(filePathUri, "r");
	        if (pfd == null)
		        return null;

	        FileDescriptor fd = pfd.getFileDescriptor();
	        input = new FileInputStream(fd);
	        output = new FileOutputStream(filePath);
	        int read;
	        byte[] bytes = new byte[4096];
	        while ((read = input.read(bytes)) != -1) {
		        output.write(bytes, 0, read);
	        }

	        input.close();
	        output.close();
	        return new File(filePath).getAbsolutePath();
        } catch (IOException ignored) {
	        ignored.printStackTrace();
        }

here we are just reading the file and writing to temp file and getting its absolutepath.
here is the full file

public class FilePath
{
/**
* Method for return file path of Gallery image
*
* @param context
* @param uri
* @return path of the selected image file from gallery
*/

private static Uri filePathUri = null;
public static String getPath(final Context context, final Uri uri)
{
    //check here to KITKAT or new version
    final boolean isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT;
    filePathUri = uri;

    // 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];
            }
        }

        //DownloadsProvider
        else if (isDownloadsDocument(uri)) {

            final String id = DocumentsContract.getDocumentId(uri);
            
            final Uri contentUri = ContentUris.withAppendedId(
                    Uri.parse("content://downloads/public_downloads"), Long.valueOf(id));

            //return getDataColumn(context, uri, null, null);
            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
    };
    FileInputStream input = null;
    FileOutputStream output = null;

    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);
        }
    } catch (IllegalArgumentException e){
        e.printStackTrace();

        File file = new File(context.getCacheDir(), "tmp");
        String filePath = file.getAbsolutePath();

        try {
	        ParcelFileDescriptor pfd = context.getContentResolver().openFileDescriptor(filePathUri, "r");
	        if (pfd == null)
		        return null;

	        FileDescriptor fd = pfd.getFileDescriptor();
	        input = new FileInputStream(fd);
	        output = new FileOutputStream(filePath);
	        int read;
	        byte[] bytes = new byte[4096];
	        while ((read = input.read(bytes)) != -1) {
		        output.write(bytes, 0, read);
	        }

	        input.close();
	        output.close();
	        return new File(filePath).getAbsolutePath();
        } catch (IOException ignored) {
	        ignored.printStackTrace();
        }
    } 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());
}

}

Hope this will work.

@sanketmthakare

This comment has been minimized.

Copy link

sanketmthakare commented Aug 1, 2019

@aj-shinde
Thanks a lot bro. its working awesome. you saved me.

@HBiSoft

This comment has been minimized.

Copy link

HBiSoft commented Aug 30, 2019

If you are having the following issue's.

  • Can't select a file from SDCard
  • Can't select a file from the downloads directory
  • Or if you want to be able to select Google Drive, Dropbox and One Drive files.

Have a look at this library I've created, it's easy to implement and handles everything for you-

https://github.com/HBiSoft/PickiT

@Abhishekgarg727

This comment has been minimized.

Copy link

Abhishekgarg727 commented Oct 4, 2019

public class FilePath
{
/**

  • Method for return file path of Gallery image
  • @param context
  • @param uri
  • @return path of the selected image file from gallery
    */
private static Uri filePathUri = null;
public static String getPath(final Context context, final Uri uri)
{
    //check here to KITKAT or new version
    final boolean isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT;
    filePathUri = uri;

    // 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];
            }
        }

        //DownloadsProvider
        else if (isDownloadsDocument(uri)) {

            final String id = DocumentsContract.getDocumentId(uri);
            
            final Uri contentUri = ContentUris.withAppendedId(
                    Uri.parse("content://downloads/public_downloads"), Long.valueOf(id));

            //return getDataColumn(context, uri, null, null);
            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
    };
    FileInputStream input = null;
    FileOutputStream output = null;

    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);
        }
    } catch (IllegalArgumentException e){
        e.printStackTrace();

        File file = new File(context.getCacheDir(), "tmp");
        String filePath = file.getAbsolutePath();

        try {
	        ParcelFileDescriptor pfd = context.getContentResolver().openFileDescriptor(filePathUri, "r");
	        if (pfd == null)
		        return null;

	        FileDescriptor fd = pfd.getFileDescriptor();
	        input = new FileInputStream(fd);
	        output = new FileOutputStream(filePath);
	        int read;
	        byte[] bytes = new byte[4096];
	        while ((read = input.read(bytes)) != -1) {
		        output.write(bytes, 0, read);
	        }

	        input.close();
	        output.close();
	        return new File(filePath).getAbsolutePath();
        } catch (IOException ignored) {
	        ignored.printStackTrace();
        }
    } 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());
}

}

thank you

@zionnite

This comment has been minimized.

Copy link

zionnite commented Oct 14, 2019

Hey guys!
am having issue, am getting
java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String android.net.Uri.getScheme()' on a null object reference

@HBiSoft

This comment has been minimized.

Copy link

HBiSoft commented Oct 14, 2019

@zionnite have a look at my library

@eriffanani

This comment has been minimized.

Copy link

eriffanani commented Nov 23, 2019

Thanks for sharing. You save my time.

@AmmarYasserAllaiThy

This comment has been minimized.

Copy link

AmmarYasserAllaiThy commented Nov 29, 2019

Really I don't know how to thank you for this valuable gist it helps me a lot and fixes the error after I became disappointed.
I'm very grateful to you.

@abbasalid

This comment has been minimized.

Copy link

abbasalid commented Mar 20, 2020

This code is not working if you select a file from google photos or google drive or downloads in android 10

@HBiSoft

This comment has been minimized.

Copy link

HBiSoft commented Mar 20, 2020

@abbasalid
This is only an issue on Android 10. You can fix this by adding the following in your manifest:

<manifest>
    <application 
        android:requestLegacyExternalStorage="true">
    </application>
</manifest>
@Marc-Ferrer-Castillo

This comment has been minimized.

Copy link

Marc-Ferrer-Castillo commented Mar 21, 2020

Is this still usable? I got the following Error:

2020-03-21 03:46:38.678 31773-31773/? E/omultimediamar: Unknown bits set in runtime_flags: 0x8000 2020-03-21 03:46:44.735 31773-31773/com.example.aplicaciomultimediamarc E/AndroidRuntime: FATAL EXCEPTION: main Process: com.example.aplicaciomultimediamarc, PID: 31773 java.lang.IllegalArgumentException: Invalid column latitude at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:170) at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:140) at android.content.ContentProviderProxy.query(ContentProviderNative.java:423) at android.content.ContentResolver.query(ContentResolver.java:944) at android.content.ContentResolver.query(ContentResolver.java:880) at android.content.ContentResolver.query(ContentResolver.java:836) at com.example.aplicaciomultimediamarc.RealPathUtil.getDataColumn(RealPathUtil.java:164) at com.example.aplicaciomultimediamarc.RealPathUtil.getRealPathFromURI_API19(RealPathUtil.java:134) at com.example.aplicaciomultimediamarc.RealPathUtil.getRealPath(RealPathUtil.java:29) at com.example.aplicaciomultimediamarc.EditarVideo$6.onClick(EditarVideo.java:222) at android.view.View.performClick(View.java:7125) at android.view.View.performClickInternal(View.java:7102) at android.view.View.access$3500(View.java:801) at android.view.View$PerformClick.run(View.java:27336) at android.os.Handler.handleCallback(Handler.java:883) at android.os.Handler.dispatchMessage(Handler.java:100) at android.os.Looper.loop(Looper.java:214) at android.app.ActivityThread.main(ActivityThread.java:7356) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930)

@HBiSoft

This comment has been minimized.

Copy link

HBiSoft commented Mar 21, 2020

@Marc-Ferrer-Castillo
What version are you targeting?

@abbasalid

This comment has been minimized.

Copy link

abbasalid commented Mar 21, 2020

@HBiSoft I had already added the requestlegacy line since start of the project it is still giving issues

@HBiSoft

This comment has been minimized.

Copy link

HBiSoft commented Mar 21, 2020

@abbasalid
I have not tried this gist so I can't say, you can try my library which I know is working on Android 10 - https://github.com/HBiSoft/PickiT

@abbasalid

This comment has been minimized.

Copy link

abbasalid commented Mar 21, 2020

@HBiSoft this library will get path of any selected file???

@HBiSoft

This comment has been minimized.

Copy link

HBiSoft commented Mar 21, 2020

@Marc-Ferrer-Castillo

This comment has been minimized.

Copy link

Marc-Ferrer-Castillo commented Mar 21, 2020

@HBiSoft
targetSdkVersion 29

@abbasalid

This comment has been minimized.

Copy link

abbasalid commented Mar 21, 2020

@HBiSoft Thanks man was looking for something like this.There is only one drawback after selecting file from drive or google photos it takes a lot of time?

@HBiSoft

This comment has been minimized.

Copy link

HBiSoft commented Mar 21, 2020

@abbasalid
How big is the file? Drive files needs to be copied

@HBiSoft

This comment has been minimized.

Copy link

HBiSoft commented Mar 21, 2020

@Marc-Ferrer-Castillo
Same as I mentioned above, add android:requestLegacyExternalStorage="true" in your manifest.

@abbasalid

This comment has been minimized.

Copy link

abbasalid commented Mar 21, 2020

@HBiSoft file is like 100kb.

@HBiSoft

This comment has been minimized.

Copy link

HBiSoft commented Mar 21, 2020

@abbasalid
100kb should only take few milliseconds, unless your are using an emulator or your internet connection is extremely slow. The file is being copied, 100kb should barely be noticeable. You can send me a mail if you'd like, my email address is on my github profile.

@Ellisonlee

This comment has been minimized.

Copy link

Ellisonlee commented Mar 27, 2020

Hi, I got

java.lang.NumberFormatException: For input string: "raw:/storage/emulated/0/Download/*****.png

So I just insert a little code into download provider

final String id = DocumentsContract.getDocumentId(uri);
if (id.startsWith("raw:")) {
     return id.replaceFirst("raw:", "");
}
final Uri contentUri = ContentUris.withAppendedId(
                    Uri.parse("content://downloads/public_downloads"), Long.valueOf(id));

Just for anyone got same problem with me

@tahelromero

This comment has been minimized.

Copy link

tahelromero commented Mar 29, 2020

Thanks Ellisonlee

Your fix works Android 6,7 and 9

@mrungue

This comment has been minimized.

Copy link

mrungue commented Apr 14, 2020

if (id.startsWith("raw:")) {
return id.replaceFirst("raw:", "");
}
final Uri contentUri = ContentUris.withAppendedId(
Uri.parse("content://downloads/public_downloads"), Long.valueOf(id));

Many thanks @Ellisonlee!

@sleepermonkey

This comment has been minimized.

Copy link

sleepermonkey commented Apr 24, 2020

@aj-shinde This really help me. Thank you very much.

@kmoec

This comment has been minimized.

Copy link

kmoec commented May 29, 2020

I get File Not Found exception on Kitkat when I select photo from Galaxy Photo App. Basically, I converted the returned path back into URI and fed it to MediaStore.Images.Media.getBitmap method.

@akwa-peter

This comment has been minimized.

Copy link

akwa-peter commented Jun 29, 2020

Thank you so much, you really saved me a lot of time

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.