android通过Uri.getPath()获取真实路径


107

我正在尝试从画廊获得图像。

Intent intent = new Intent();
intent.setType("image/*");
intent.setAction(Intent.ACTION_GET_CONTENT);
startActivityForResult(Intent.createChooser(intent, "Select picture"), resultCode );

从此活动返回后,我得到了一个包含Uri的数据。看起来像:

content://media/external/images/1

如何将这条路径转换为真实路径(就像' /sdcard/image.png')?

谢谢


1
这显然是很晚的评论,但是我只想指出,startActivityForResultCode方法将请求代码作为参数,而不是结果代码。
Tianxiang Xiong

没有uri.getPath()给你真实的道路?
达尔潘

#Try This尽管如此,如果您遇到问题以获取真实路径,可以尝试我的答案。上述答案并没有帮助我。说明:-此方法获取URI,然后检查您的Android设备的API级别,然后根据API级别将生成Real路径。生成真实路径的代码根据API级别而有所不同。 这是我的答案
Sunil

Answers:


56

您真的有必要获得一条物理路径吗?
例如,ImageView.setImageURI()并且ContentResolver.openInputStream()允许你访问一个文件的内容,不知道它的真实路径。


正是我一直在寻找的东西,但是找不到。谢谢。
戴夫斯2010年

6
抱歉,如果我想将此图像转换为文件,而又没有真正的路径怎么办?
Chlebta 2014年

6
物理路径允许访问文件名和扩展名。如果是文件上传。
Clocker

195

这是我的工作:

Uri selectedImageURI = data.getData();
imageFile = new File(getRealPathFromURI(selectedImageURI));

和:

private String getRealPathFromURI(Uri contentURI) {
    String result;
    Cursor cursor = getContentResolver().query(contentURI, null, null, null, null);
    if (cursor == null) { // Source is Dropbox or other similar local file path
        result = contentURI.getPath();
    } else { 
        cursor.moveToFirst(); 
        int idx = cursor.getColumnIndex(MediaStore.Images.ImageColumns.DATA); 
        result = cursor.getString(idx);
        cursor.close();
    }
    return result;
}

注意:managedQuery()不赞成使用方法,所以我没有使用它。

最后编辑:改进。我们应该关闭光标!


1
stackoverflow.com/a/7265235/375093这是另一种选择,但建议比上述方法更好。也检查一下
Sundeep

6
@ m3n0R,您好,在Moto G中,根本没有MediaStore.Images.ImageColumns.DATA列。没有此列如何获取图像?
Seema 2014年

16
错误 确保从游标访问数据之前,游标已正确初始化。.检查API 19
Mayur R. Amipara 2015年

1
@ReneJuuse:极好的资源。由于这一点,我终于设法解决了这个问题-自从Android诞生以来,我没有意识到有太多更改。我正在运行API 21,当我使用您链接的站点上显示的API 19实现时,它终于可以工作了。
米洛斯·伊万诺维奇

2
无法从CursorWindow读取行0,col -1。在访问游标之前,请确保游标已正确初始化。
行家ツ

18

@Rene Juuse-上面的评论...感谢此链接!

。从一个SDK到另一个SDK,获得真实路径的代码有些不同,因此下面我们介绍三种处理不同SDK的方法。

getRealPathFromURI_API19():返回API 19的真实路径(或未测试)getRealPathFromURI_API11to18():返回API 11到API 18的真实路径getRealPathFromURI_below11():返回11以下的API的真实路径

public class RealPathUtil {

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


@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);
      }
      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
      = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
           cursor.moveToFirst();
           return cursor.getString(column_index);
}

字体:http//hmkcode.com/android-display-selected-image-and-its-real-path/


2016年3月更新

要解决所有与图像路径有关的问题,我尝试创建一个自定义图片库,例如facebook和其他应用程序。这是因为您只能使用本地文件(实际文件,不能使用虚拟文件或临时文件),所以我可以解决此库的所有问题。

https://github.com/nohana/Laevatein (该库是从相机拍摄照片或从画廊中选择图片,如果您从画廊中选择,他有一个带相册的抽屉,只显示本地文件)


三星S4上的@Clocker都不是
里卡多

我真的很难在android中管理所有类型的源图像。如果您上载图片或从图片库中进行选择,最好的解决方案是从Facebook创建图片库。它是一个自定义图片库,其中只有设备中的真实图像,没有虚拟或临时图片。我使用此库修复了应用程序中的所有问题。github.com/nohana/Laevatein 它的库非常好。自定义并不简单,但是您可以打开代码并进行更改。希望对您有所帮助。
luizfelipetx

使用4.4.1破坏了我的Samsung S2
Oliver Dixon

我需要获取pdf或doc等文件,但无法获取路径。你能帮我么?
阿尼丝·库玛

1
太棒了!最后,一些真正有效的方法。一直在寻找这个。谢谢。
Javatar

14

注意这是@ user3516549答案的一项改进,我已经在具有Android 6.0.1的Moto G3上进行了检查,
我遇到了这个问题,因此我尝试了@ user3516549的答案,但在某些情况下它无法正常工作。我发现在Android 6.0(或更高版本)中,当我们启动图库图像选择意图时,将打开一个显示最近图像的屏幕,当用户从此列表中选择图像时,我们将获得uri作为

content://com.android.providers.media.documents/document/image%3A52530

而如果用户从滑动抽屉中而不是从最近的抽屉中选择图库,则我们将uri作为

content://media/external/images/media/52530

所以我已经处理了 getRealPathFromURI_API19()

public static String getRealPathFromURI_API19(Context context, Uri uri) {
        String filePath = "";
        if (uri.getHost().contains("com.android.providers.media")) {
            // Image pick from recent 
            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();
            return filePath;
        } else {
            // image pick from gallery 
           return  getRealPathFromURI_BelowAPI11(context,uri)
        }

    }

编辑:如果您试图以更高版本获取外部sdcard中文件的图像路径,请检查我的问题


嗨,朋友,是的。但这之所以发生,是因为现在Google具有默认格式,可以将手机中的所有照片上传到Google文档。只需将拇指保存在手机中即可。如果您是从Google文档中获得此uri,则需要先下载照片,然后再使用它。总的来说这不好。因此,要在此处修复所有问题,请立即使用此库。(该库仅使用本地文件,使用此解决方案,您的问题将得到解决),或者您可以从库中提取代码并改进自己以解决问题。github.com/nohana/Laevatein希望以上内容对您有所帮助。
luizfelipetx

1+,它对我来说很完美。正如@JaiprakasSoni在回答中所说的那样,当我在Moto G4播放器中运行我的应用程序时遇到了同样的问题,但是当我使用上面的代码时,它对我来说很好用。谢谢。您节省了我的时间
Shailesh

6

编辑: 在这里使用此解决方案:https : //stackoverflow.com/a/20559175/2033223 完美!

首先,感谢您的解决方案@luizfelipetx

我稍微改变了您的解决方案。这对我有用:

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

    Pattern p = Pattern.compile("(\\d+)$");
    Matcher m = p.matcher(uri.toString());
    if (!m.find()) {
        Log.e(ImageConverter.class.getSimpleName(), "ID for requested image not found: " + uri.toString());
        return filePath;
    }
    String imgId = m.group();

    String[] column = { MediaStore.Images.Media.DATA };
    String sel = MediaStore.Images.Media._ID + "=?";

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

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

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

    return filePath;
}

注意:因此,我们获取的文档和图像取决于图像是来自“最近”,“图库”还是其他任何来源。因此,在查找之前,我首先要提取图像ID。


1

Hii这是我从相机或画廊拍摄图像的完整代码

//我的变量声明

protected static final int CAMERA_REQUEST = 0;
    protected static final int GALLERY_REQUEST = 1;
    Bitmap bitmap;
    Uri uri;
    Intent picIntent = null;

//点击

if (v.getId()==R.id.image_id){
            startDilog();
        }

//方法体

private void startDilog() {
    AlertDialog.Builder myAlertDilog = new AlertDialog.Builder(yourActivity.this);
    myAlertDilog.setTitle("Upload picture option..");
    myAlertDilog.setMessage("Where to upload picture????");
    myAlertDilog.setPositiveButton("Gallery", new DialogInterface.OnClickListener() {
        @Override
        public void onClick(DialogInterface dialog, int which) {
            picIntent = new Intent(Intent.ACTION_GET_CONTENT,null);
            picIntent.setType("image/*");
            picIntent.putExtra("return_data",true);
            startActivityForResult(picIntent,GALLERY_REQUEST);
        }
    });
    myAlertDilog.setNegativeButton("Camera", new DialogInterface.OnClickListener() {
        @Override
        public void onClick(DialogInterface dialog, int which) {
            picIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
            startActivityForResult(picIntent,CAMERA_REQUEST);
        }
    });
    myAlertDilog.show();
}

//剩下的事情

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if (requestCode==GALLERY_REQUEST){
        if (resultCode==RESULT_OK){
            if (data!=null) {
                uri = data.getData();
                BitmapFactory.Options options = new BitmapFactory.Options();
                options.inJustDecodeBounds = true;
                try {
                    BitmapFactory.decodeStream(getContentResolver().openInputStream(uri), null, options);
                    options.inSampleSize = calculateInSampleSize(options, 100, 100);
                    options.inJustDecodeBounds = false;
                    Bitmap image = BitmapFactory.decodeStream(getContentResolver().openInputStream(uri), null, options);
                    imageofpic.setImageBitmap(image);
                } catch (FileNotFoundException e) {
                    e.printStackTrace();
                }
            }else {
                Toast.makeText(getApplicationContext(), "Cancelled",
                        Toast.LENGTH_SHORT).show();
            }
        }else if (resultCode == RESULT_CANCELED) {
            Toast.makeText(getApplicationContext(), "Cancelled",
                    Toast.LENGTH_SHORT).show();
        }
    }else if (requestCode == CAMERA_REQUEST) {
        if (resultCode == RESULT_OK) {
            if (data.hasExtra("data")) {
                bitmap = (Bitmap) data.getExtras().get("data");
                uri = getImageUri(YourActivity.this,bitmap);
                File finalFile = new File(getRealPathFromUri(uri));
                imageofpic.setImageBitmap(bitmap);
            } else if (data.getExtras() == null) {

                Toast.makeText(getApplicationContext(),
                        "No extras to retrieve!", Toast.LENGTH_SHORT)
                        .show();

                BitmapDrawable thumbnail = new BitmapDrawable(
                        getResources(), data.getData().getPath());
                pet_pic.setImageDrawable(thumbnail);

            }

        } else if (resultCode == RESULT_CANCELED) {
            Toast.makeText(getApplicationContext(), "Cancelled",
                    Toast.LENGTH_SHORT).show();
        }
    }
}

private String getRealPathFromUri(Uri tempUri) {
    Cursor cursor = null;
    try {
        String[] proj = { MediaStore.Images.Media.DATA };
        cursor = this.getContentResolver().query(tempUri,  proj, null, null, null);
        int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
        cursor.moveToFirst();
        return cursor.getString(column_index);
    } finally {
        if (cursor != null) {
            cursor.close();
        }
    }
}
public static int calculateInSampleSize(
        BitmapFactory.Options options, int reqWidth, int reqHeight) {
    // Raw height and width of image
    final int height = options.outHeight;
    final int width = options.outWidth;
    int inSampleSize = 1;

    if (height > reqHeight || width > reqWidth) {

        final int halfHeight = height / 2;
        final int halfWidth = width / 2;

        // Calculate the largest inSampleSize value that is a power of 2 and keeps both
        // height and width larger than the requested height and width.
        while ((halfHeight / inSampleSize) > reqHeight
                && (halfWidth / inSampleSize) > reqWidth) {
            inSampleSize *= 2;
        }
    }
    return inSampleSize;
}

private Uri getImageUri(YourActivity youractivity, Bitmap bitmap) {
    ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
    bitmap.compress(Bitmap.CompressFormat.JPEG, 100, byteArrayOutputStream);
    String path = MediaStore.Images.Media.insertImage(youractivity.getContentResolver(), bitmap, "Title", null);
    return Uri.parse(path);
}

您如何知道这条线中的100? options.inSampleSize = calculateInSampleSize(options, 100, 100);
John Joe

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.