안드로이드는 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 2015

uri.getPath()당신에게 진정한 길을 주지 않았습니까?
Darpan

#Try This Still, 실제 경로를 얻는 데 문제가 있으면 내 대답을 시도해 볼 수 있습니다. 위의 답변은 도움이되지 않았습니다. 설명 :-이 메소드는 URI를 가져 와서 Android 기기의 API 레벨을 확인한 후 API 레벨에 따라 실제 경로를 생성합니다. 실제 경로를 생성하는 코드는 API 레벨에 따라 다릅니다. 여기 내 대답은
선일

답변:


56

실제 경로를 얻는 것이 정말로 필요합니까?
예를 들어, ImageView.setImageURI()그리고 ContentResolver.openInputStream()당신은 그것의 실제 경로를 알 필요없이 파일의 내용을 액세스 할 수 있습니다.


내가 찾던 것과 정확히 일치하지만 찾을 수 없습니다. 감사.
davs

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

16
오류 만들기 확실히 커서 API (19)에 확인 ..에서 데이터에 액세스하기 전에 제대로 초기화
Mayur R. Amipara

1
@ReneJuuse : 훌륭한 리소스입니다. 그 덕분에 마침내이 문제를 해결할 수있었습니다. Android가 시작된 이래로 많은 변화가 있다는 것을 깨닫지 못했습니다. API 21을 실행 중이었고 링크 한 사이트에 표시된 API 19 구현을 사용했을 때 마침내 작동했습니다.
Milos Ivanovic

2
CursorWindow에서 행 0, col -1을 읽을 수 없습니다. 커서가 데이터에 액세스하기 전에 올바르게 초기화되었는지 확인하십시오.
Maveň ツ

18

@Rene Juuse-위의 의견 ...이 링크에 감사드립니다!

. 실제 경로를 가져 오는 코드는 SDK마다 약간 다르므로 아래에는 서로 다른 SDK를 처리하는 세 가지 방법이 있습니다.

getRealPathFromURI_API19 () : API 19 (또는 그 이상이지만 테스트되지 않음)에 대한 실제 경로를 반환합니다. getRealPathFromURI_API11to18 () : API 11에서 API 18까지의 실제 경로를 반환합니다.

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 (이 라이브러리는 카메라에서 사진을 찍거나 갤러리에서 선택하는 것입니다. 갤러리에서 선택하면 앨범이있는 서랍이 있고 로컬 파일 만 표시됩니다)


@Clocker on Samsung S4도
Ricardo

Im은 Android에서 모든 유형의 소스 이미지를 관리하기가 정말 어렵습니다. 업로드하거나 갤러리에서 선택하는 경우 가장 좋은 솔루션은 Facebook에서 갤러리로 만드는 것입니다. 가상 또는 임시가 아닌 장치의 실제 이미지 만있는 사용자 지정 갤러리입니다. 이 라이브러리를 사용하여 내 앱의 모든 문제를 해결합니다. github.com/nohana/Laevatein 정말 좋은 라이브러리입니다. 사용자 정의하는 것은 간단하지 않지만 코드를 열고 변경할 수 있습니다. 도움이 되었기를 바랍니다.
luizfelipetx

4.4.1로 내 삼성 S2에서 고장 남
Oliver Dixon

pdf 또는 doc와 같은 파일을 가져와야합니다. 경로를 가져올 수 없습니다. 저를 도와주세요?
Anish Kumar

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 play에서 내 앱을 실행할 때 동일한 문제에 직면했지만 위의 코드를 사용하면 잘 작동한다고 대답했습니다. 감사합니다. 당신은 내 시간 절약
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는 카메라 또는 galeery에서 이미지를 가져 오기위한 완전한 코드입니다.

// 내 변수 선언

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

// Onclick

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);
존 조

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.