마스터Q&A 안드로이드는 안드로이드 개발자들의 질문과 답변을 위한 지식 커뮤니티 사이트입니다. 안드로이드펍에서 운영하고 있습니다. [사용법, 운영진]

프로바이더를 이용해서 실제 파일 경로얻어오는거 ..

0 추천

안녕하세요.

카메라로 사진을 찍거나, 동영상을 선택해서 해당 파일의 위치를 얻어낼때

이제부턴 File:// 경로가 아니라 Content://경로로 얻어오잖아요.

 

그래서 아래와 같은 대중적인 코드를 사용했었는데, 확인해보니 null 값이 리턴되고 있어요.

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

 

혹시 변경된 이슈사항이나 다른 것이 있는지 여쭤보고싶습니다. (__)

 

 

겸군님 (1,900 포인트) 님이 2019년 3월 4일 질문

2개의 답변

–1 추천
 
채택된 답변
mcsong (44,040 포인트) 님이 2019년 3월 5일 답변
겸군님님이 2019년 3월 5일 채택됨
답변 감사합니다.

올려주신 코드나 제 코드는 일반적인 이미지/데이터는 괜찮은데, 찾아보니 Google 포토? 클라우드 동영상/이미지인 경우에는
content:// path값을 변환할 때 null이 발생하더라구요.. mediakey라는 값이 path값에 포함이 되더군요. 해당 이슈를 찾아보니 결국 getColumnIndex를 사용하지 말고 파일 생성, 복사등을 통해 해야하더라구요.
그래도 일반적인 방법으로는 알려주신 코드로 사용하니 잘 됩니다~

감사합니다 (__)
+1 추천
위 코드는 content:// 가 MediaStore의 Uri를 가정하고 처리하고 있어 문제가 생기는 경우 입니다. 다른 앱과의 연동에서 content:// 가 MediaStore의 Uri가 아닌 경우가 매우 많습니다. 앱 별로 uri를 if 문으로 처리하는 것은 결국 계속 문제가 생기게 되어있습니다. 해당 파일만을 읽고 쓰는 것으로 충분한 경우라면 File의 위치를 가져와서 처리하는게 아니라 ContentResolver.openAssetFileDescriptor 를 사용해서 FileDescriptor를 얻어 와서 사용해야 호환성 문제가 생기지 않습니다.
회색 (21,340 포인트) 님이 2019년 3월 5일 답변
안녕하세요.

사실 제가 이 문제 원인을 완전히 이해 못한상태에서 글을올려서.. 제대로 밝히지 못했는데, 지금까지 조사해보니.. 말씀해주신것처럼 다른 앱과의 연동 (클라우드뿐아니라 웹 이미지 공유 등,,)에서 이런 특정 Uri값을 많이 리턴하더라구요.

그래서 받은 Uri값을 if문에서 쪼개서 위 소스코드 되면 위 소스 돌리고, 아니면 또 새로운 방법으로 하고.. 뭐 이런 작업을 해야하는게 불편할 것 같습니다.

말씀해주신것 바탕으로 좀 찾아봤는데요.

https://stackoverflow.com/questions/20559392/getting-videosnon-local-from-the-google-photos-app/20992310#20992310

여기에  있는 답변처럼 해봤는데, 말씀해주신 것과 맞는 방법일까요?
해당 답변에서 filePath를 리턴하게 해서 접근하게 했더니 동작은 제대로 하는데, 맞는 방법인건지.
다만 시간이 매우 오래 걸리는 단점이 있네요 ㅠㅜ 카카오톡으로도 똑같은 동영상해보니 오래걸리는거 보아 비슷한 방법일거같긴한데..


답변 감사드립니다(__)
네 제가 설명한 것과 거의 같은 방식입니다. openFileDescriptor 설명에 보면 가능하다면 openAssetFiledescriptor를 사용하라고 되어있기 떄문에 위 스택오버플로우 코드에서 openFileDescriptor -> openAssetFileDescriptor 그리고 ParcelFileDescriptor -> AssetFileDescriptor로 처리하는게 좀더 범용적인 코드라고 할수 있습니다만 지금 처리하시려고 하는 경우에서는 어떻게 처리하던 별 문제는 생기지 않을것 같습니다.

스택오버플로 코드는 현재 앱에서 접근 가능한 경로로 파일을 복사하는 코드인데요. 해당 파일을 가져와서 어떻게 사용하느냐에 따라 코드는 달라져야 할것 입니다. 굳이 새롭게 복사해서 사용하지 않아도 되는 경우라면 File Path를 가지고 여나 File Descriptor를 가지고 여나 성능의 차이는 없는게 맞습니다. 파일을 복사해서 사용해야 한다면 openFileDescriptor는 메인 쓰레드에서 실제 카피는 백그라운드 쓰레드에서 하는 등의 작업은 해주셔야 할것 이구요.
...