2013-01-16 4 views
10

사용자가 브라우저에서 일부 파일을 다운로드하는 경우 Android 4.2 이후 DownloadManager가 사용됩니다. 사용자가 '다운로드 완료'알림을 클릭하면 인 텐트가 시작되어 항상 시작되었습니다.잡힌 DownloadManager 인 텐트에서 파일 경로 가져 오기

intent.getData() 

file:///storage/emulated/0/Download/some_file.ext 같은 문자열을 반환 : 안드로이드 4.2하도록 내용에서 다운로드 한 파일의 경로를 가지고하는 데 사용되는 의도 전에. 그러나 Android 4.2 이후 다운로드 관리자는 content://downloads/all_downloads/2334과 같이 content 체계로 브로드 캐스트하고 있습니다.

다운로드 한 파일의 로컬 파일 경로를 검색하려면 어떻게합니까?

public static String getRealPathFromURI(Uri contentUri, Activity activity) { 
    DownloadManager downloadManager = (DownloadManager) activity.getSystemService(Activity.DOWNLOAD_SERVICE); 
    String[] contentParts = contentUri.getEncodedPath().split("/"); 
    Cursor q = downloadManager.query(new DownloadManager.Query().setFilterById(Integer.parseInt(contentParts[contentParts.length - 1]))); 
    if (q == null) { 
     // Download no longer exists 
     return null; 
    } 
    q.moveToFirst(); 
    return q.getString(q.getColumnIndex(DownloadManager.COLUMN_LOCAL_FILENAME)); 
} 

그러나 커서가 모든 행 (그래서 q.getCount() == 0 및 그 마지막 return 문은 예외를 throw)를 반환하지 :

나는 다음과 같은 시도했습니다. 또한 Uri에서 다운로드 한 파일 ID를 파싱하여 해킹하는 것이 이상하게 보입니다.

UPDATE : 나는 또한 시도 :

input = getActivity().getContentResolver().openInputStream(contentUri); 

을하지만,이

권한 거부라는 오류 반환 읽기 com.android.providers.downloads.DownloadProvider URI 내용 :// downloads/all_downloads/2334 from pid = 30950, uid = 10064는 android.permission.ACCESS_ALL_DOWNLOADS 또는 grantUriPermission()이 필요합니다.

분명히 다운로드에 액세스 할 수 없습니다 (내 앱이 브라우저를 시작하지 않았기 때문에) ContentProvider을 통해 다운로드에 액세스 할 수 없습니다.

+0

이 BTW 첫 번째 접근 방식은, 나를 위해 무사 작동 DownloadManager.COLUMN_STATUS == STATUS_SUCCESSFUL과 유효한 URI를 반환 열 COLUMN_LOCAL_URI. – southerton

답변

1

콘텐츠 리졸버를 통해 얻는 것이 옳습니다. 모든 콘텐츠 URL이 파일이되는 것은 아닙니다. 예를 들어 갤러리 응용 프로그램은 소스에 따라 네트워크 호출이나 로컬 파일로 변환하는 uri를 제공합니다.

실제 파일 경로가 표시 되더라도 파일 권한으로 인해 파일을 읽을 수는 없지만 외부 저장소에있는 것이 좋을 수도 있습니다. 예외가 제시 한 것처럼 android.permission.ACCESS_ALL_DOWNLOADS을 앱에 추가 해 봤니?That won't work, since the permission is at signature level :(

+0

예, ContentResolver를 거쳐야하지만 위의 설명 된 문제가 발생할 것으로 예상됩니다. 그리고 네,''내 AndroidManifest.xml 파일에 있습니다. 그러나 나는 당신이이 허락을 묻기로되어 있다고 확신하지는 않습니다 ... –

+0

방금 ​​만들었습니다. 간단한 테스트 응용 프로그램 및 나를 위해 잘 작동합니다. 예외는 다운로드 프로그램에서 파일을 클릭하면 부여 된 읽기 권한을 어떻게 든 "잃어버린"것을 의미합니다. – botteaap

5

다음은 효과가 있습니다. 첫째, 올바르게 지적 된대로 파일 경로를 가져올 수 없습니다.

InputStream input = getContentResolver().openInputStream(intent.getData()); 

당신은 자바의 다른 같은이 InputStream을 읽을 수 있습니다. (옳은 길을 저를 설정하는 그에게 학점) 대신 사용하여, 파일 내용에 액세스하기 위해 자동으로 임시 허가를 얻을. 파일 이름을 가져올 방법이없는 것 같습니다. 파일이 필요하면 먼저 입력 스트림을 (임시) 파일에 작성하십시오.

SecurityException은 임시 액세스가 취소 된 경우 처리됩니다. 이것은 내가 전에 잘못 읽었던 어떤 파일에서 나에게 일어난 일이며, 특히 나의 활동도 (Activicity)의 onNewIntent에서 인 텐트를 집어 들었을 때.

+1

전체 URL이 아닌 커서를 사용하여 이름과 크기를 가져올 수 있습니다. 이름을 얻는 것이 좋습니다. 임시 파일을 동일한 이름과 파일 확장자로 저장할 수 있습니다. – jcesarmobile

+0

'onNewIntent'에서'SecurityException'을 피할 수있는 방법을 찾아 냈습니까? 나는 똑같은 문제가있어 그것에 대해 무엇을해야 할지를 알 수 없다. –

+0

@Jarett 내 활동 시작 모드를 변경하고 더 이상이 문제가 발생하지 않는다는 점을 제외하고는 구체적으로 아니오. 아마도 singleInstance와 관련이 있습니다 (지금 singleTop 사용). 문제가 발생한 곳의 onNewIntent에서 액티비티가 전달됩니다. 죄송합니다. 더 많은 정보가 없습니다. –

2

나는 이것을 알아 내기 위해 몇 시간이 걸렸으므로 @erickok의 답변에 추가하고 싶습니다. @jcesarmobile에 명시된 바와 같이, 전체 경로가 아닌 파일의 이름과 크기 만 확보 할 수 있습니다.

당신은 다음과 같이 이름과 크기를 얻을, 다음 임시 파일로 저장할 수 있습니다

String filename = null; 
Long filesize = null; 
Cursor cursor = null; 
try { 
    cursor = this.getContentResolver().query(intent.getData(), new String[] { 
     OpenableColumns.DISPLAY_NAME, OpenableColumns.SIZE}, null, null, null); 
    if (cursor != null && cursor.moveToFirst()) { 
     filename = cursor.getString(0); 
     filesize = cursor.getLong(1); 
    } 
} finally { 
    if (cursor != null) 
     cursor.close(); 
} 
+0

아아 파일 이름이 아니며 DownloadManager.Request setTitle 메소드에 할당 된 제목입니다. – southerton

관련 문제