11

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

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.

4

3 回答 3

5

这是有效的。首先,您不能(也不应该)得到 botteaap 正确指出的文件路径。(归功于他让我走上了正确的道路。)相反,您会自动获得访问文件内容的临时权限,使用:

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

您可以像阅读InputStreamJava 中的任何其他内容一样阅读此内容。似乎没有办法获取文件名。如果需要文件,首先将输入流写入(临时)文件。

SecurityException您的临时访问权限被撤销时抛出。这发生在我之前尝试错误阅读的一些文件上,特别是当 Intent 在我的 Acticity 中被拾取时onNewIntent

于 2013-01-17T14:42:38.397 回答
2

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

即使您访问了真实的文件路径,由于文件权限,您也可能无法读取它,尽管幸运的是它位于外部存储上。您是否尝试过android.permission.ACCESS_ALL_DOWNLOADS像异常提示的那样添加到您的应用程序中? 那行不通,因为权限处于签名级别:(

于 2013-01-17T11:55:31.323 回答
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();
}
于 2014-09-22T11:28:45.533 回答