自Android 4.2起,如果用户在浏览器中下载某个文件,则使用DownloadManager。如果用户单击“下载完成”通知,则始终启动Intent。在Android 4.2之前,意图用于在内容中包含下载文件的路径,例如:
intent.getData()
将返回file:///storage/emulated/0/Download/some_file.ext
之类的字符串。但是,自Android 4.2以来,下载管理器使用content
方案进行广播和意图,例如content://downloads/all_downloads/2334
。
如何检索下载文件的本地文件路径?
我尝试了以下内容:
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
语句会抛出异常)。此外,通过从Uri解析下载文件ID的hack似乎很奇怪。
更新:我也尝试过:
input = getActivity().getContentResolver().openInputStream(contentUri);
但这会返回错误,说明
权限拒绝:阅读com.android.providers.downloads.DownloadProvider uri content:// downloads / all_downloads / 2334 from pid = 30950,uid = 10064需要android.permission.ACCESS_ALL_DOWNLOADS或grantUriPermission()
显然,我无法通过 ContentProvider
访问下载(因为我的应用没有启动它们 - 浏览器确实如此)。
答案 0 :(得分:5)
这是有效的。首先,你不能(也不应该)获得正确指出botteaap的文件路径。 (告诉他让我走上正确的道路。)相反,你会自动获得临时许可来访问文件内容,使用:
InputStream input = getContentResolver().openInputStream(intent.getData());
您可以像Java中的任何其他内容一样阅读此InputStream
。似乎无法获取文件名。如果需要文件,请先将输入流写入(临时)文件。
当您的临时访问被撤销时,SecurityException
将被抛出。这件事发生在我之前尝试阅读错误的一些文件上,特别是在我的Acticity onNewIntent
中获取意图的时候。
答案 1 :(得分:2)
通过内容解析器获取它是正确的。并非每个内容网址都是文件。例如,Gallery应用程序将根据来源为您提供转换为网络调用或本地文件的uri。
即使您已经到达真正的文件路径,由于文件权限,您可能无法读取它,尽管您可能很幸运它在外部存储上。 您是否尝试过将 That won't work, since the permission is at signature level :( android.permission.ACCESS_ALL_DOWNLOADS
添加到您的应用中,就像异常建议一样?
答案 2 :(得分: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();
}