java Android 7 - 无法显示 PDF(pdf_name 格式无效)
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/40996935/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Android 7 - Cannot display PDF (pdf_name is of invalid format)
提问by Christian
I have an App that is working properly for Android 4, 5 and 6. That App lists remote files in a server and lets you download them from the server (PDF files). Once you click on a file, it downloads it on the "Android Downloads folder" and when it's finished it opens it with default PDF reader.
我有一个适用于 Android 4、5 和 6 的应用程序。该应用程序列出了服务器中的远程文件,并允许您从服务器下载它们(PDF 文件)。单击文件后,它会将其下载到“Android 下载文件夹”中,完成后会使用默认 PDF 阅读器打开它。
The problem is that the same code in Android 7 fails giving the next error: "Cannot display PDF (pdf_name is of invalid format)".
问题是 Android 7 中的相同代码失败并给出下一个错误:“无法显示 PDF(pdf_name 的格式无效)”。
It's funny because:
这很有趣,因为:
- if I access Downloads folder and click on the downloaded file, it opens properly.
- When it finishes downloading, it shows a notification, that click on it opens it properly.
- 如果我访问下载文件夹并单击下载的文件,它会正确打开。
- 下载完成后,它会显示一条通知,单击它可以正确打开它。
So the problem happens only when the same App tries to open the file automatically after download it.
所以只有当同一个应用程序在下载文件后尝试自动打开文件时才会出现问题。
How I do the download:
我如何进行下载:
fileName="file.pdf";
request = new DownloadManager.Request(Uri.parse(Constants.GetURL()));
request.setMimeType(mime)
.setTitle(fileName).setVisibleInDownloadsUi(true)
.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE)
.setDescription(mContext.getString(R.string.app_name))
.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED)
.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, fileName);
enqueue = dm.enqueue(request);
Once is downloaded:
一次下载:
Uri path = Uri.parse(c.getString(c.getColumnIndex(DownloadManager.COLUMN_LOCAL_URI)));
//path contains the route where file was downloaded. Something like: file:///storage/emulated/0/Download/file.pdf
Intent pdfOpenintent = IntentHelper.getViewPDFIntent(path);
mContext.startActivity(pdfOpenintent);
How I open it:
我如何打开它:
public static Intent getViewPDFIntent(Uri path){
Intent i = new Intent(Intent.ACTION_VIEW);
i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
pdfOpenintent.setDataAndType(path, "application/pdf");
return i;
}
About FileProvider: I have implemented using FileProvider and the problem is the same. It is not related with permissions, Download Folder is public folder and there is no SecurityException raising or any other exception related with permissions.
关于 FileProvider:我已经使用 FileProvider 实现了,问题是一样的。它与权限无关,下载文件夹是公共文件夹,没有引发 SecurityException 或任何其他与权限相关的异常。
It is not related with any PDF App, because it happens the same sharing with Gmail for sending the document.
它与任何 PDF 应用程序无关,因为它发生与 Gmail 相同的共享以发送文档。
Extrange behaviour: When I debug the App step by step, it works perfectly. When I execute normal, it fails. If I put sleep or delays of 5 secs, does not work. So only works debugging.
Extrange 行为:当我逐步调试应用程序时,它运行良好。当我正常执行时,它失败了。如果我睡眠或延迟 5 秒,则不起作用。所以只能调试。
About Android 7: Reading the official changes of Android 7 (https://developer.android.com/about/versions/nougat/android-7.0-changes.html) it says it should work, but dont recommend any more this way. Otherwise, it does not work.
关于 Android 7:阅读Android 7的官方更改(https://developer.android.com/about/versions/nougat/android-7.0-changes.html)它说它应该可以工作,但不再推荐这种方式。否则,它不起作用。
Any new idea?
有什么新想法吗?
采纳答案by Christian
After some days of research and some people involved, we arrived to the conclusion that Android changed the behaviour of DownloadManager on Android 7 to add the permissions of FileProvider. (In Android 7 Changelog they explain)
经过几天的研究和一些人的参与,我们得出的结论是,Android 改变了 Android 7 上 DownloadManager 的行为,添加了 FileProvider 的权限。(在 Android 7 Changelog 中他们解释了)
My feeling is that Android since Android 7 (and 7.1), is probably saving the File in a temporal folder, then sends the Broadcast FileDownloadedSuccessfully, and then it moves the file to the final destination folder.
我的感觉是,从 Android 7(和 7.1)开始,Android 可能将文件保存在一个临时文件夹中,然后发送 Broadcast FileDownloadedSuccessfully,然后将文件移动到最终目标文件夹。
Because the FileDownloaded Broadcast jumps before the file is moved, it is not able to open it. That is why while debugging or putting a sleep of 10 seconds, then it works.
因为 FileDownloaded Broadcast 在文件移动之前跳转,所以无法打开它。这就是为什么在调试或休眠 10 秒时,它可以工作的原因。
Did not find any solution for this problem more than stop using DownloaderManager for download&open and implement my own. (Only will use for just a download of a file, without any other action involved).
除了停止使用 DownloaderManager 进行下载和打开并实现我自己的之外,没有找到针对此问题的任何解决方案。(仅用于下载文件,不涉及任何其他操作)。
Hope it helps for the next who finds this problem.
希望它对下一个发现此问题的人有所帮助。
回答by Kev Thompson
Edit:
Fix FoundBit more digging has shown this seems to be a permission issue. Setting this permission fixed the issue, its very strange it worked at all with out them.
编辑:
修复发现更多挖掘表明这似乎是一个权限问题。设置这个权限解决了这个问题,很奇怪它在没有它们的情况下工作。
"android.permission.READ_EXTERNAL_STORAGE"
“android.permission.READ_EXTERNAL_STORAGE”
While this isnt an realy answer its more information to help identify it and provide a horrible work around, I cant make a comment yet.
虽然这不是一个真正的答案,它提供了更多信息来帮助识别它并提供一个可怕的解决方法,但我还不能发表评论。
I am having the same issue after downloading a PDF using AsyncTask.
使用 AsyncTask 下载 PDF 后,我遇到了同样的问题。
doInBackground() completes correctly, all Read / Write streams are closed, onPostExecute() is called using this code.
doInBackground() 正确完成,所有读/写流都关闭,使用此代码调用 onPostExecute()。
Intent target = new Intent(Intent.ACTION_VIEW);
target.setDataAndType(Uri.fromFile(file), "application/pdf");
target.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
Intent intent = Intent.createChooser(target, "View PDF Bill...");
and the PDF fails to launch with the invalid format error.
并且 PDF 因格式无效错误而无法启动。
The 2nd load ( loading over the top of the existing PDF ) the launching of the PDF viewer works fine most of the time but does still occasionally fail.
第二次加载(加载到现有 PDF 的顶部)PDF 查看器的启动在大多数情况下运行良好,但偶尔仍会失败。
If I debug it opens fine ( I assume due to the time it takes ), if I add a 10 second sleep it works fine, if I add a 9 second sleep it doens't. Its almost as if there is a failure on closing the file or some other termination call in the OS and it times out but no exceptions are thrown.
如果我调试它打开正常(我假设是因为它花费的时间),如果我添加 10 秒睡眠它工作正常,如果我添加 9 秒睡眠它不会。它几乎就像关闭文件或操作系统中的其他一些终止调用失败一样,它超时但没有抛出异常。
The 10 second delay applies even if I try to open the PDF from ES File Explorer
即使我尝试从 ES 文件资源管理器打开 PDF,10 秒延迟也适用
The code is working fine on all devices lower than Android 7.0.
该代码在低于 Android 7.0 的所有设备上运行良好。