【问题标题】:How to get image real path by using uri without using MediaStore.Images.Media.DATA如何在不使用 MediaStore.Images.Media.DATA 的情况下使用 uri 获取图像真实路径
【发布时间】:2019-12-23 08:01:49
【问题描述】:

我发现MediaStore.Images.Media.DATA已被弃用,所以我想用另一种方式获取图像真实路径。

这是我获取 uri 和图像标题的新方法,但我不知道如何获取真实路径。

我打印 uri、标题、路径:

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

标题:IMG_20191223143418

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

但我想要这样:/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;*/
}

【问题讨论】:

  • 你不会再在 Q 上获得“真正的路径”。你甚至不会尝试它。好消息是您不需要“真正的路径”。直接使用获取的内容方案。
  • @blackapps 我需要真实的图片真实路径,因为我需要将图片上传到firebase,并且在上传之前我需要将所有图片转换为jpeg类型。
  • jpeg 类型与内容方案或文件方案无关。所以你是什么意思?对于上传,您可以直接使用内容方案。
  • @blackapps 我需要转换图像,因为用户可能会选择 png 类型的图像。而且我真的不知道你的内容方案是什么直接是什么意思,我尝试使用content://com.android.providers.media.documents/document/image%3A1605之类的方式上传到firebase,它不起作用。
  • 不是以'content://....'开头的吗?那是一个内容方案。您可以使用该方案将 .png 转换为 .jpg。很简单。

标签: android android-contentprovider mediastore android-10.0


【解决方案1】:

只要用这个方法getImagePath(); 公共类 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());
}

【讨论】:

  • 我用你的方法,但是有点小问题。在您的if (isExternalStorageDocument(uri)) 中,Environment.getExternalStorageDirectory() 已弃用,我该如何替换它,谢谢。
  • 我发现在外部存储中选择文件时无法获取路径。
  • 在问题@playground 中提到MediaStore.Images.Media.DATA 已弃用,但接受的答案使用数据列.. 令人震惊...
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-03-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-06-05
  • 2013-07-06
  • 1970-01-01
相关资源
最近更新 更多