Home » Android » android – Get real path from URI of file in sdcard marshmallow

android – Get real path from URI of file in sdcard marshmallow

Posted by: admin June 15, 2020 Leave a comment


I want to pick file that exist in sdcard not in internal storage and upload it server but I am not able to get its path for getting its size. I have start an intent for pick a file using below code:

 intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
 String[] mimetypes = {"application/*"};
 intent.putExtra(Intent.EXTRA_MIME_TYPES, mimetypes);
      Intent.createChooser(intent, "Select a File to Upload"), FILE_SELECT_CODE);

For getting path to file I am using this answer and its working unless user select any file from sdcard(removable). When I debug the code and found that type is not primary so it will not go inside this condition :

     return Environment.getExternalStorageDirectory() + "/" + split[1];

So my question is what will be it’s else? i.e. what if type is not primary? how we can get path to file in that case? I have search many questions and tutorial there is no else in any of them. I have also tried else part of this answer but its not working because System.getenv() return null for “SECONDARY_STORAGE” and sdcard for “EXTERNAL_STORAGE“. I get file not found exception when I try:

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

Uri and doc Id for file look like:

Uri: content://com.android.externalstorage.documents/document/0EF9-3110%3Adevice-2016-12-02-130553.png

docId: 0EF9-3110:device-2016-12-02-130553.png

Any help ??

How to&Answers:

After spending time on Android Device Manager I have found solution, here it is:

If doc type id is not primary then I create path using :

filePath = "/storage/" + type + "/" + split[1];

EDIT: in case of DocumentUri select contentUri on basis of file type

Here is complete function:

public static String getRealPathFromURI_API19(Context context, Uri uri) {
    String filePath = "";

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

            if (Build.VERSION.SDK_INT > 20) {
                    //getExternalMediaDirs() added in API 21
                    File extenal[] = context.getExternalMediaDirs();
                   for (File f : extenal) {
                    filePath = f.getAbsolutePath();
                    if (filePath.contains(type)) {
                        int endIndex = filePath.indexOf("Android");
                        filePath = filePath.substring(0, endIndex) + split[1];
                    filePath = "/storage/" + type + "/" + split[1];
            return filePath;

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

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

        try {
            cursor = context.getContentResolver().query(uri, projection, null, null, null);
            if (cursor != null && cursor.moveToFirst()) {
                final int index = cursor.getColumnIndexOrThrow(column);
                String result = cursor.getString(index);
                return result;
        } finally {
            if (cursor != null)
    } else if (DocumentsContract.isDocumentUri(context, uri)) {
        // MediaProvider
        String wholeID = DocumentsContract.getDocumentId(uri);

        // Split at colon, use second item in the array
        String[] ids = wholeID.split(":");
        String id;
        String type;
        if (ids.length > 1) {
            id = ids[1];
            type = ids[0];
        } else {
            id = ids[0];
            type = ids[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[]{id};
        final String column = "_data";
        final String[] projection = {column};
        Cursor cursor = context.getContentResolver().query(contentUri, 
            projection, selection, selectionArgs, null);

        if (cursor != null) {
            int columnIndex = cursor.getColumnIndex(column);

            if (cursor.moveToFirst()) {
                filePath = cursor.getString(columnIndex);
        return filePath;
    } else {
        String[] proj = {MediaStore.Audio.Media.DATA};
        Cursor cursor = context.getContentResolver().query(uri, proj, null, null, null);
        if (cursor != null) {
            int column_index = cursor.getColumnIndexOrThrow(MediaStore.Audio.Media.DATA);
            if (cursor.moveToFirst())
                filePath = cursor.getString(column_index);

        return filePath;
    return null;


Change your upload code. Somewhere you will have

FileInputStream fis = new FileInputStream(path);

Change to

InputStream is = getContentResolver().openInputStream(uri);

So use the uri directly. No need for a file path.


​It is quite easy to implement FileProvider on your application. First you need to add a FileProvider tag in AndroidManifest.xml under tag like below:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"

And then create a provider_paths.xml file in xml folder under res folder. Folder may be needed to create if it doesn’t exist.


<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <external-path name="external_files" path="."/>

Done! FileProvider is now declared and be ready to use.

The final step is to change the line of code below in MainActivity.java

Uri photoURI = Uri.fromFile(createImageFile());

 Uri photoURI = FileProvider.getUriForFile(MainActivity.this,
            BuildConfig.APPLICATION_ID + ".provider",

And …. done ! Your application should now work perfectly fine on any Android version including Android Nougat. Yah !