2

I found that MediaStore.Images.Media.DATA is deprecated, so I want to use another way to get image real path.

Here is my new way to get uri and title of image, but I don't know how to get real path.

I print uri, title, path:

photoUri: content://media/external/images/media/1605

title: IMG_20191223143418

photoUri.getPath: /external/images/media/1605

But I want just like this: /storage/emulated/0/DCIM/1733/IMG_20191223143418.jpg

public static String getRealPathFromUri(Context context, Uri uri) throws IOException {

    String filePath = null;

    if (DocumentsContract.isDocumentUri(context, uri)) {

                String documentId = DocumentsContract.getDocumentId(uri);
                if (isMediaDocument(uri)) { // MediaProvider.
                    String id = documentId.split(":")[1];

                    String selection = MediaStore.Images.Media._ID + "=?";
                    String[] selectionArgs = {id};

                    filePath = getDataColumnImage(context, MediaStore.Images.Media.EXTERNAL_CONTENT_URI, selection, selectionArgs);
                } else if (isDownloadsDocument(uri)) { // DownloadsProvider.
                    Uri contentUri = ContentUris.withAppendedId(Uri.parse("content://downloads/public_downloads"), Long.valueOf(documentId));
                    filePath = getDataColumnImage(context, contentUri, null, null);
                }
        }
        else if ("content".equalsIgnoreCase(uri.getScheme())) {
            filePath = getDataColumnImage(context, uri, null, null);
        }
        else if ("file".equals(uri.getScheme())) {
            filePath = uri.getPath();
        }else
            return filePath = null;
        return filePath;
}


private static boolean isMediaDocument(Uri uri) {
    return "com.android.providers.media.documents".equals(uri.getAuthority());
}

private static boolean isDownloadsDocument(Uri uri) {
    return "com.android.providers.downloads.documents".equals(uri.getAuthority());
}

private static String getDataColumnImage(Context context, Uri uri, String selection, String[] selectionArgs) {

    String path = null;

    String[] projection = new String[]{
                MediaStore.Files.FileColumns._ID,
                MediaStore.Images.Media.DATE_TAKEN,
                MediaStore.Images.Media.WIDTH,
                MediaStore.Images.Media.HEIGHT,
                MediaStore.MediaColumns.TITLE,
                MediaStore.Images.Media.MIME_TYPE,
        };
        Cursor cursor = null;
        try {
            cursor = context.getContentResolver().query(
                    uri,
                    projection,
                    selection,
                    selectionArgs,
                    null
            );
            if (cursor != null && cursor.moveToFirst()) {
                int idColumn = cursor.getColumnIndexOrThrow(MediaStore.MediaColumns._ID);
                int titleColumn = cursor.getColumnIndexOrThrow(MediaStore.MediaColumns.TITLE);

                Uri photoUri = Uri.withAppendedPath(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, cursor.getString(idColumn));
                String title = cursor.getString(titleColumn);

                Log.e("TAG", "photoUri: " + photoUri);
                Log.e("TAG", "title: " + title);
                Log.e("TAG", "photoUri.getPath: " + photoUri.getPath());
            }
        } catch (Exception e) {
            if (cursor != null) {
                cursor.close();
            }
        }
        return path;

        // MediaStore.Images.Media.DATA is deprecated, so I want to use the other way as mentioned above to get real path.
        /*String[] projection = new String[]{MediaStore.Images.Media.DATA};
            Cursor cursor = null;
            try {
                cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs, null);
                if (cursor != null && cursor.moveToFirst()) {
                    int columnIndex = cursor.getColumnIndexOrThrow(projection[0]);
                    path = cursor.getString(columnIndex);
                }
            } catch (Exception e) {
                if (cursor != null) {
                    cursor.close();
                }
            }
            return path;*/
}
playground
  • 115
  • 1
  • 13
  • You will not get a 'real path' anymore on Q. And you will not even try it. The nice thing is that you dont need a `real path'. Use the obtained content scheme directly. – blackapps Dec 23 '19 at 09:36
  • @blackapps I need the real image real path, because I need to upload image to firebase, and before upload, I need to convert all image to jpeg type. – playground Dec 23 '19 at 09:47
  • A jpeg type has nothing to do with content scheme or file scheme. So what do you mean? And for uploading you can use the content scheme directly. – blackapps Dec 23 '19 at 10:09
  • @blackapps I need to convert image, because user maybe choose the image of png type. And I don't really know what is your **content scheme directly** mean, I try to use like `content://com.android.providers.media.documents/document/image%3A1605` to upload to firebase, it can't work. – playground Dec 23 '19 at 10:15
  • Doesn't it start with 'content://....'? That is a content scheme. And you can use that scheme to convert a .png to a .jpg. Very simple. – blackapps Dec 23 '19 at 10:17
  • InputStream is = getContentResolver().openInputStream(Uri.parse(... content .. scheme...)); – blackapps Dec 23 '19 at 10:19
  • Bitmap bitmap = BitmapFactory.decodeStream(is); – blackapps Dec 23 '19 at 10:20
  • @blackapps But I can't use `content://....` to upload to firebase. – playground Dec 23 '19 at 10:28
  • Really? I dont believe that. But it does not matter as you convert that png to jpg. And you can save that jpg as a normal classic file and then upload it. – blackapps Dec 23 '19 at 10:29
  • @blackapps I will try it later, thank you! – playground Dec 23 '19 at 10:32

1 Answers1

3

just use this method getImagePath(); public class RealPathUtil {

@SuppressLint("NewApi")
private static String getRealPathApi19Above(Context context, Uri uri) {
    String filePath = "";
    try {
        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();
        }


      /*  String wholeID = DocumentsContract.getDocumentId(uri);

        // Split at colon, use second item in the array
        String id = wholeID.split(":")[1];

        String[] column = {MediaStore.Images.Media.DATA};

        // where id is equal to
        String sel = MediaStore.Images.Media._ID + "=?";

        Cursor cursor = context.getContentResolver().query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
                column, sel, new String[]{id}, null);

        int columnIndex = cursor.getColumnIndex(column[0]);

        if (cursor.moveToFirst()) {
            filePath = cursor.getString(columnIndex);
        }
        cursor.close();
        */

    } catch (Exception e) {
        filePath = "";
    }
    return filePath;
}


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


@SuppressLint("NewApi")
private static String getRealPathApi11to18(Context context, Uri contentUri) {
    try {
        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);
        }
        return result;
    } catch (Exception e) {
        return "";
    }
}


public static String getImagePath(Context context, Uri uri) {
    if (Build.VERSION.SDK_INT < 19)
        return getRealPathApi11to18(context, uri);
    else
        return getRealPathApi19Above(context, uri);

} 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());
}
ThavaSelvan
  • 123
  • 6
  • I use your way, but it has some little problem. In your `if (isExternalStorageDocument(uri))`, `Environment.getExternalStorageDirectory()` is deprecated, how can I replace it, thank you. – playground Dec 23 '19 at 09:38
  • 1
    And I found that I can't get path when choose file in external storage. – playground Dec 23 '19 at 10:04
  • check this link ...https://stackoverflow.com/questions/13209494/how-to-get-the-full-file-path-from-uri – ThavaSelvan Dec 23 '19 at 10:22
  • 2
    In the question @playground mentioned that `MediaStore.Images.Media.DATA` is deprecated, yet the accepted answer uses the data column.. Shocking... – HB. Feb 17 '20 at 12:40