안드로이드의 파일 경로에서 컨텐츠 URI 가져 오기


271

이미지의 절대 경로를 알고 있습니다 (예 : /sdcard/cats.jpg). 이 파일의 콘텐츠 URI를 얻는 방법이 있습니까?

실제로 내 코드에서는 이미지를 다운로드하여 특정 위치에 저장합니다. ImageView 인스턴스에서 이미지를 설정하려면 현재 경로를 사용하여 파일을 열고 바이트를 가져 와서 비트 맵을 만든 다음 ImageView 인스턴스에서 비트 맵을 설정하십시오. 이것은 매우 느린 프로세스입니다. 대신 컨텐츠를 얻을 수 있다면 메소드를 매우 쉽게 사용할 수 있습니다. imageView.setImageUri(uri)


23
Uri uri = Uri.parse ( "file : ///sdcard/img.png");
Anand Tiwari

13
댓글에 +1, 단지 Uri.parse ( "file : //"+ filePath)는 트릭을 수행해야합니다
German Latorre

Uri.Parse는 "추가 할"감가 상각하고
pollaris

@pollaris Uri.parse가 API 1에 추가되었으며 더 이상 사용되지 않음으로 표시되지 않습니다.
JP de la Torre

Uri.parse ( "something"); 나에게 노력하고 있지 않다, 나는 이유를 찾을 수 없다.
Bay

답변:


480

시도해보십시오 :

ImageView.setImageURI(Uri.fromFile(new File("/sdcard/cats.jpg")));

또는

ImageView.setImageURI(Uri.parse(new File("/sdcard/cats.jpg").toString()));

3
감사! 두 번째 방법은 1.6, 2.1 및 2.2에서 잘 작동하지만 첫 번째 방법은 2.2에서만
mishkin

28
이러한 방법 중 어느 것도 컨텐츠 URI에 대한 파일 경로를 해석하지 않습니다. 나는 그것이 즉각적인 문제를 해결했다는 것을 이해합니다.
Jeffrey Blattman

38
"/ sdcard /"를 하드 코딩하지 마십시오. 사용 Environment.getExternalStorageDirectory () getPath () 대신.
ekatz

8
이것은 위의 두 솔루션이 모두 반환하는 것입니다. 다른 것입니다. content : // 형식 URI가 필요합니다. Jinal의 답변은 완벽하게 작동하는 것 같습니다
Ajith Memana

5
헤이 Uri.fromFile안드로이드 26+에하지 작업, 당신은 파일 제공자를 사용해야합니다
vuhung3990

85

최신 정보

여기서 미디어 (이미지 / 비디오)가 이미 콘텐츠 미디어 공급자에 추가되어 있다고 가정합니다. 그렇지 않으면 콘텐츠 URL을 원하는만큼 정확하게 얻을 수 없습니다. 대신 Uri 파일이 있습니다.

파일 탐색기 활동에 대해 같은 질문이있었습니다. 파일의 컨텐츠는 이미지, 오디오 및 비디오와 같은 미디어 스토어 데이터 만 지원한다는 것을 알아야합니다. sdcard에서 이미지를 선택하여 이미지 내용을 가져 오는 코드를 제공합니다. 이 코드를 사용해보십시오. 어쩌면 당신을 위해 일할 것입니다 ...

public static Uri getImageContentUri(Context context, File imageFile) {
  String filePath = imageFile.getAbsolutePath();
  Cursor cursor = context.getContentResolver().query(
      MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
      new String[] { MediaStore.Images.Media._ID },
      MediaStore.Images.Media.DATA + "=? ",
      new String[] { filePath }, null);
  if (cursor != null && cursor.moveToFirst()) {
    int id = cursor.getInt(cursor.getColumnIndex(MediaStore.MediaColumns._ID));
    cursor.close();
    return Uri.withAppendedPath(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, "" + id);
  } else {
    if (imageFile.exists()) {
      ContentValues values = new ContentValues();
      values.put(MediaStore.Images.Media.DATA, filePath);
      return context.getContentResolver().insert(
          MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
    } else {
      return null;
    }
  }
}

녹화 된 비디오 파일의 content : // URI를 찾는 방법을 찾고 있었고 위의 코드는 Nexus 4 (Android 4.3)에서 완벽하게 작동하는 것 같습니다. 코드를 설명 할 수 있다면 좋을 것입니다.
Ajith Memana

절대 경로가 "/ sdcard / Image Depo / picture.png"인 파일의 콘텐츠 Uri를 얻으려고 시도했습니다. 그것은 작동하지 않았으므로 코드 경로를 디버깅하고 커서가 비어 있고 항목이 ContentProvider에 추가 될 때 Content Uri로 null을 제공한다는 것을 알았습니다. 도와주세요.
스리 크리슈나

1
file : ///storage/emulated/0/Android/data/com.packagename/files/out.mp4 파일 경로가 있지만 contentUri를 얻으려고하면 null이 발생합니다. 또한로 변경 MediaStore.Images.Media을 시도 MediaStore.Video.Media했지만 여전히 운이 없습니다.
Narendra Singh

1
이것은 안드로이드 파이 API를 28 커서를 반환 널 (null)에 작동하지 않습니다
이브라힘 Gharyali

1
Android 10에서 DATA 열에 액세스 할 수 없으므로 Android 10에 대해이 방법을 업데이트 할 수 있습니까?
Khushbu Shah

16

//이 코드는 2.2의 이미지에서 작동하지만 다른 미디어 유형인지 확실하지 않습니다.

   //Your file path - Example here is "/sdcard/cats.jpg"
   final String filePathThis = imagePaths.get(position).toString();

   MediaScannerConnectionClient mediaScannerClient = new
   MediaScannerConnectionClient() {
    private MediaScannerConnection msc = null;
    {
        msc = new MediaScannerConnection(getApplicationContext(), this);
        msc.connect();
    }

    public void onMediaScannerConnected(){
        msc.scanFile(filePathThis, null);
    }


    public void onScanCompleted(String path, Uri uri) {
        //This is where you get your content uri
            Log.d(TAG, uri.toString());
        msc.disconnect();
    }
   };

1
앱에 Uri 콘텐츠가 포함 된 미디어 스트림이 필요하므로 절대 경로가 작동하지 않기 때문에 Google+에 공유하는 데 도움이되었습니다.
Ridcully

1
우수한! 오디오 미디어 유형에서도 작동하는지 확인할 수 있습니다.
Matt M

16

허용되는 솔루션은 아마도 귀하의 목적에 가장 적합한 것이지만 실제로 제목 줄의 질문에 대답하는 것입니다.

내 응용 프로그램에서는 URI에서 경로를 가져 와서 경로에서 URI를 가져와야합니다. 전자 :

/**
 * Gets the corresponding path to a file from the given content:// URI
 * @param selectedVideoUri The content:// URI to find the file path from
 * @param contentResolver The content resolver to use to perform the query.
 * @return the file path as a string
 */
private String getFilePathFromContentUri(Uri selectedVideoUri,
        ContentResolver contentResolver) {
    String filePath;
    String[] filePathColumn = {MediaColumns.DATA};

    Cursor cursor = contentResolver.query(selectedVideoUri, filePathColumn, null, null, null);
    cursor.moveToFirst();

    int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
    filePath = cursor.getString(columnIndex);
    cursor.close();
    return filePath;
}

후자는 비디오에 사용되지만 MediaStore.Video를 MediaStore.Audio 등으로 대체하여 오디오 또는 파일 또는 다른 유형의 저장된 콘텐츠에도 사용할 수 있습니다.

/**
 * Gets the MediaStore video ID of a given file on external storage
 * @param filePath The path (on external storage) of the file to resolve the ID of
 * @param contentResolver The content resolver to use to perform the query.
 * @return the video ID as a long
 */
private long getVideoIdFromFilePath(String filePath,
        ContentResolver contentResolver) {


    long videoId;
    Log.d(TAG,"Loading file " + filePath);

            // This returns us content://media/external/videos/media (or something like that)
            // I pass in "external" because that's the MediaStore's name for the external
            // storage on my device (the other possibility is "internal")
    Uri videosUri = MediaStore.Video.Media.getContentUri("external");

    Log.d(TAG,"videosUri = " + videosUri.toString());

    String[] projection = {MediaStore.Video.VideoColumns._ID};

    // TODO This will break if we have no matching item in the MediaStore.
    Cursor cursor = contentResolver.query(videosUri, projection, MediaStore.Video.VideoColumns.DATA + " LIKE ?", new String[] { filePath }, null);
    cursor.moveToFirst();

    int columnIndex = cursor.getColumnIndex(projection[0]);
    videoId = cursor.getLong(columnIndex);

    Log.d(TAG,"Video ID is " + videoId);
    cursor.close();
    return videoId;
}

기본적으로 DATAMediaStore(또는 쿼리하는 하위 섹션)은 파일 경로를 저장하므로 해당 정보를 사용하여 파일을 찾습니다.


항상 그런 것은 아니며, 반 보증 열이 두 개 반환 OpenableColumns.DISPLAY_NAME & OpenableColumns.SIZE되어 전송 앱이 '규칙'을 따르는 경우에도 마찬가지입니다. 일부 주요 앱은이 두 필드 만 반환하지만 항상 해당 _data필드를 반환하지는 않습니다 . 일반적으로 내용에 대한 직접 경로가 포함 된 데이터 필드가없는 경우 먼저 내용을 읽고 파일이나 메모리에 쓴 다음 자신의 경로가 있어야합니다.
Pierre

7

사용에 따라이 두 가지 방법을 사용할 수 있습니다

Uri uri = Uri.parse("String file location");

또는

Uri uri = Uri.fromFile(new File("string file location"));

나는 두 가지 방법 모두를 시도했다.


5

content://File에서 Content Uri를 작성하는 가장 쉽고 강력한 방법은 FileProvider 를 사용하는 입니다. FileProvider에서 제공하는 Uri는 다른 앱과 파일을 공유하기위한 Uri도 제공 할 수 있습니다. 절대 경로에서 File Uri를 가져 오려면 FileDocumentFile.fromFile (new File (path, name))을 사용하면 Api 22에 추가되고 아래 버전에서는 null을 반환합니다.

File imagePath = new File(Context.getFilesDir(), "images");
File newFile = new File(imagePath, "default_image.jpg");
Uri contentUri = getUriForFile(getContext(), "com.mydomain.fileprovider", newFile);


2

adb shell CLI 명령을 사용하여 코드를 작성하지 않고 파일 ID 얻기

adb shell content query --uri "content://media/external/video/media" | grep FILE_NAME | grep -Eo " _id=([0-9]+)," | grep -Eo "[0-9]+"

Google "adb는 컨텐츠 URI에서 실제 경로를 얻습니다".이 질문은 검색 결과 요약에 0 투표 답변의 컨텐츠가 포함 된 상위 1 개 질문입니다. 먼저 투표를하겠습니다. 고마워 친구!
주말

이것은 멋지다. 그러나 Permission Denial: Do not have permission in call getContentProviderExternal() from pid=15660, uid=10113 requires android.permission.ACCESS_CONTENT_PROVIDERS_EXTERNALLY뿌리를 내리지 않는 한, 당신은 얻을 것 같습니다 : .
not2qubit

그래서 이것은 전화의 루트 액세스가 필요합니까?
Samintha Kaveesh

1

유효성 검사를 사용하여 Android N 이전 버전을 지원하는 것이 좋습니다 (예 :

  if (Build.VERSION.SDK_INT >=  Build.VERSION_CODES.N) {
     imageUri = Uri.parse(filepath);
  } else{
     imageUri = Uri.fromFile(new File(filepath));
  }

  if (Build.VERSION.SDK_INT >=  Build.VERSION_CODES.N) {
     ImageView.setImageURI(Uri.parse(new File("/sdcard/cats.jpg").toString()));         
  } else{
     ImageView.setImageURI(Uri.fromFile(new File("/sdcard/cats.jpg")));
  }

https://es.stackoverflow.com/questions/71443/reporte-crash-android-os-fileuriexposedexception-en-android-n


0

U는 아래 코드 스 니펫을 시도 할 수 있습니다

    public Uri getUri(ContentResolver cr, String path){
    Uri mediaUri = MediaStore.Files.getContentUri(VOLUME_NAME);
    Cursor ca = cr.query(mediaUri, new String[] { MediaStore.MediaColumns._ID }, MediaStore.MediaColumns.DATA + "=?", new String[] {path}, null);
    if (ca != null && ca.moveToFirst()) {
        int id = ca.getInt(ca.getColumnIndex(MediaStore.MediaColumns._ID));
        ca.close();
        return  MediaStore.Files.getContentUri(VOLUME_NAME,id);
    }
    if(ca != null) {
        ca.close();
    }
    return null;
}

1
VOLUME_NAME이란 무엇입니까?
Evgenii Vorobei

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