从捕获的DownloadManager意图中检索文件路径

从Android 4.2开始,如果用户在浏览器中下载某个文件,则使用DownloadManager。 如果用户单击“下载完成”通知,则始终启动Intent。 在Android 4.2之前,用于在内容中包含下载文件路径的意图,例如:

intent.getData() 

将返回一个String,例如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语句会抛出exception)。 此外,通过从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访问下载(因为我的应用程序没有启动它们 – 浏览器确实如此)。

通过内容解析器获取它是正确的。 并非每个内容url都是文件。 例如,Gallery应用程序将根据源提供转换为网络调用或本地文件的uri。

即使您已经到达真正的文件路径,由于文件权限,您可能无法读取它,尽管您可能很幸运它在外部存储上。 您是否尝试过将android.permission.ACCESS_ALL_DOWNLOADS添加到您的应用中,就像exception建议一样? 这是行不通的,因为许可是在签名级别:(

这是有效的。 首先,你不能(也不应该)像botteaap正确指出的那样获取文件路径。 (告诉他让我走上正确的道路。)相反,您会自动获得临时权限以访问文件内容,使用:

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

您可以像Java中的任何其他一样读取此InputStream 。 似乎无法获取文件名。 如果需要文件,请先将输入流写入(临时)文件。

撤消临时访问时抛出SecurityException 。 这件事发生在我之前尝试读取错误的一些文件上,特别是当我在Acticity的onNewIntent

我只想补充@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(); }