自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 的黑客似乎很奇怪。
更新:我也尝试过:
input = getActivity().getContentResolver().openInputStream(contentUri);
但这返回一个错误,指出
权限拒绝:从 pid=30950、uid=10064 读取 com.android.providers.downloads.DownloadProvider uri content://downloads/all_downloads/2334 需要 android.permission.ACCESS_ALL_DOWNLOADS,或 grantUriPermission((
显然,我无法通过ContentProvider
访问下载(因为我的应用程序没有启动它们 - 浏览器启动了下载(。
这是有效的方法。首先,你不能(也不应该想要(像botteaap正确指出的那样获取文件路径。(感谢他让我走上了正确的道路。相反,您可以使用以下方法自动获得访问文件内容的临时权限:
InputStream input = getContentResolver().openInputStream(intent.getData());
您可以像阅读 Java 中的任何其他InputStream
一样阅读此。似乎没有办法获取文件名。如果需要文件,请先将输入流写入(临时(文件。
SecurityException
在撤销临时访问权限时抛出。这发生在我之前试图错误阅读的一些文件上,特别是当我的 Acticity onNewIntent
中拾取意图时。
通过内容解析器获取它是正确的事情。并非每个内容 url 都会是一个文件。例如,图库应用将为您提供转换为网络调用或本地文件的 uri,具体取决于源。
即使您到达了真实的文件路径,由于文件权限,您也可能无法读取它,尽管您可能很幸运它在外部存储上。您是否尝试过像异常建议的那样向应用程序添加这是行不通的,因为权限处于签名级别:(android.permission.ACCESS_ALL_DOWNLOADS
?
我只想补充@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();
}