无法在存储中打开PDF文件,安卓10。

huangapple go评论101阅读模式
英文:

Can't Open PDF file in the storage android 10

问题

我在Download Storage中有一个PDF文件,并尝试使用意图(intent)显示它,我已经安装了三个PDF查看器应用,但它们都无法成功显示该文件,但如果我通过文件浏览器直接打开PDF文件,则可以正常显示。

以下是我的代码:

  1. File kuda = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS);
  2. File file1 = new File(kuda, "KK.pdf");
  3. Intent intent = new Intent(Intent.ACTION_VIEW);
  4. Uri uri = FileProvider.getUriForFile(getContext(), BuildConfig.APPLICATION_ID + ".provider", file1);
  5. intent.setDataAndType(uri, "application/pdf");
  6. intent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY | Intent.FLAG_GRANT_READ_URI_PERMISSION);
  7. startActivity(intent);

以下是我的清单文件(manifest):

  1. <provider
  2. android:name="androidx.core.content.FileProvider"
  3. android:authorities="${applicationId}.provider"
  4. android:exported="false"
  5. android:grantUriPermissions="true">
  6. <meta-data
  7. android:name="android.support.FILE_PROVIDER_PATHS"
  8. android:resource="@xml/provider_paths"/>
  9. </provider>

以下是provider_paths.xml文件的内容:

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <paths xmlns:android="http://schemas.android.com/apk/res/android">
  3. <external-path name="external_files" path="Download/"/>
  4. <files-path name="files" path="files/" />
  5. </paths>

我正在使用Android 10版本。

请帮忙看看,谢谢。

英文:

I have a pdf file in the Download Storage and I try show it using intent, I already have three PDF viewer apps, but none of them sucessfully show the file, but if I open the pdf directly via file explorer its show just fine.

here is my code :

  1. File kuda = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS);
  2. File file1 = new File(kuda,&quot;KK.pdf&quot;);
  3. Intent intent = new Intent(Intent.ACTION_VIEW);
  4. Uri uri= FileProvider.getUriForFile(getContext(), BuildConfig.APPLICATION_ID+&quot;.provider&quot;,file1);
  5. intent.setDataAndType(uri, &quot;application/pdf&quot;);
  6. intent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY | Intent.FLAG_GRANT_READ_URI_PERMISSION);
  7. startActivity(intent);

my manifest :

  1. &lt;provider
  2. android:name=&quot;androidx.core.content.FileProvider&quot;
  3. android:authorities=&quot;${applicationId}.provider&quot;
  4. android:exported=&quot;false&quot;
  5. android:grantUriPermissions=&quot;true&quot;&gt;
  6. &lt;meta-data
  7. android:name=&quot;android.support.FILE_PROVIDER_PATHS&quot;
  8. android:resource=&quot;@xml/provider_paths&quot;/&gt;
  9. &lt;/provider&gt;

provider paths :

  1. &lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
  2. &lt;paths xmlns:android=&quot;http://schemas.android.com/apk/res/android&quot;&gt;
  3. &lt;external-path name=&quot;external_files&quot; path=&quot;Download/&quot;/&gt;
  4. &lt;files-path name=&quot;files&quot; path=&quot;files/&quot; /&gt;
  5. &lt;/paths&gt;

I'm using android 10

please help. thanks

答案1

得分: 1

是的,在OS 10之后,需要以新的方式编写逻辑。以下是使用Retrofit获取某些响应并使用byte[]的示例,适用于我的应用程序。将此代码放入您的Android组件(例如活动)中。调用viewModel.getPdfBytes()将从后端获得响应!

  1. private static final int CREATE_FILE = 23;
  2. private void saveFileToStorageIntent() {
  3. Intent intent = new Intent(Intent.ACTION_CREATE_DOCUMENT);
  4. intent.addCategory(Intent.CATEGORY_OPENABLE);
  5. intent.setType(MimeTypeMap.getSingleton().getMimeTypeFromExtension("pdf"));
  6. intent.putExtra(Intent.EXTRA_TITLE, getString(R.string.text_export_pdf_file_first) + getDateString() + getString(R.string.text_export_pdf_file));
  7. startActivityForResult(intent, CREATE_FILE);
  8. }
  9. @Override
  10. protected void onActivityResult(int requestCode, int resultCode, Intent data) {
  11. super.onActivityResult(requestCode, resultCode, data);
  12. if (requestCode == CREATE_FILE) {
  13. if (resultCode == Activity.RESULT_OK && data != null) {
  14. writePDFToFile(data.getData(), viewModel.getPdfBytes());
  15. }
  16. }
  17. }
  18. private void writePDFToFile(Uri uri, ResponseBody body){
  19. InputStream inputStream = null;
  20. OutputStream outputStream = null;
  21. try {
  22. byte[] fileReader = new byte[4096];
  23. long fileSize = body.contentLength();
  24. long fileSizeDownloaded = 0;
  25. inputStream = body.byteStream();
  26. outputStream = getContentResolver().openOutputStream(uri);
  27. while (true) {
  28. int read = inputStream.read(fileReader);
  29. if (read == -1) {
  30. break;
  31. }
  32. outputStream.write(fileReader, 0, read);
  33. fileSizeDownloaded += read;
  34. Logger.print(TAG, "file download: " + fileSizeDownloaded + " of " + fileSize);
  35. }
  36. outputStream.flush();
  37. openFileWithIntent(uri, "pdf", getString(R.string.open_file));
  38. } catch (Exception e) {
  39. Logger.print(TAG, e.getMessage());
  40. } finally {
  41. if (inputStream != null) {
  42. try {
  43. inputStream.close();
  44. } catch (IOException e) {
  45. e.printStackTrace();
  46. }
  47. }
  48. if (outputStream != null) {
  49. try {
  50. outputStream.close();
  51. } catch (IOException e) {
  52. e.printStackTrace();
  53. }
  54. }
  55. }
  56. }
  57. private void openFileWithIntent(Uri fileUri, String typeString, String openTitle) {
  58. Intent target = new Intent(Intent.ACTION_VIEW);
  59. target.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
  60. target.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
  61. target.setDataAndType(
  62. fileUri,
  63. MimeTypeMap.getSingleton().getMimeTypeFromExtension(typeString)
  64. ); // For now there is only type 1 (PDF).
  65. Intent intent = Intent.createChooser(target, openTitle);
  66. if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
  67. intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
  68. }
  69. try {
  70. startActivity(intent);
  71. } catch (ActivityNotFoundException e) {
  72. if (BuildConfig.DEBUG) e.printStackTrace();
  73. Toast.makeText(context, getString(R.string.error_no_pdf_app), Toast.LENGTH_SHORT).show();
  74. FirebaseCrashlytics.getInstance().log(getString(R.string.error_no_pdf_app));
  75. FirebaseCrashlytics.getInstance().recordException(e);
  76. }
  77. }
英文:

Yea, things changed after OS 10, you have to write logic in new way. Sample where we get some response using retrofit and using those byte[], working in my apps. Put this code in your android component(activity for example). Invoking viewModel.getPdfBytes() is response from backend!

  1. private static final int CREATE_FILE = 23;
  2. private void saveFileToStorageIntent() {
  3. Intent intent = new Intent(Intent.ACTION_CREATE_DOCUMENT);
  4. intent.addCategory(Intent.CATEGORY_OPENABLE);
  5. intent.setType(MimeTypeMap.getSingleton().getMimeTypeFromExtension(&quot;pdf&quot;));
  6. intent.putExtra(Intent.EXTRA_TITLE, getString(R.string.text_export_pdf_file_first) + getDateString() + getString(R.string.text_export_pdf_file));
  7. startActivityForResult(intent, CREATE_FILE);
  8. }
  9. @Override
  10. protected void onActivityResult(int requestCode, int resultCode, Intent data) {
  11. super.onActivityResult(requestCode, resultCode, data);
  12. if (requestCode == CREATE_FILE) {
  13. if (resultCode == Activity.RESULT_OK &amp;&amp; data != null) {
  14. writePDFToFile(data.getData(), viewModel.getPdfBytes());
  15. }
  16. }
  17. }
  18. private void writePDFToFile(Uri uri, ResponseBody body){
  19. InputStream inputStream = null;
  20. OutputStream outputStream = null;
  21. try {
  22. byte[] fileReader = new byte[4096];
  23. long fileSize = body.contentLength();
  24. long fileSizeDownloaded = 0;
  25. inputStream = body.byteStream();
  26. outputStream = getContentResolver().openOutputStream(uri);
  27. while (true) {
  28. int read = inputStream.read(fileReader);
  29. if (read == -1) {
  30. break;
  31. }
  32. outputStream.write(fileReader, 0, read);
  33. fileSizeDownloaded += read;
  34. Logger.print(TAG, &quot;file download: &quot; + fileSizeDownloaded + &quot; of &quot; + fileSize);
  35. }
  36. outputStream.flush();
  37. openFileWithIntent(uri,&quot;pdf&quot;, getString(R.string.open_file));
  38. } catch (Exception e) {
  39. Logger.print(TAG, e.getMessage());
  40. } finally {
  41. if (inputStream != null) {
  42. try {
  43. inputStream.close();
  44. } catch (IOException e) {
  45. e.printStackTrace();
  46. }
  47. }
  48. if (outputStream != null) {
  49. try {
  50. outputStream.close();
  51. } catch (IOException e) {
  52. e.printStackTrace();
  53. }
  54. }
  55. }
  56. }
  57. private void openFileWithIntent(Uri fileUri, String typeString, String openTitle) {
  58. Intent target = new Intent(Intent.ACTION_VIEW);
  59. target.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
  60. target.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
  61. target.setDataAndType(
  62. fileUri,
  63. MimeTypeMap.getSingleton().getMimeTypeFromExtension(typeString)
  64. ); // For now there is only type 1 (PDF).
  65. Intent intent = Intent.createChooser(target, openTitle);
  66. if (Build.VERSION.SDK_INT &gt;= Build.VERSION_CODES.N) {
  67. intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
  68. }
  69. try {
  70. startActivity(intent);
  71. } catch (ActivityNotFoundException e) {
  72. if (BuildConfig.DEBUG) e.printStackTrace();
  73. Toast.makeText(context, getString(R.string.error_no_pdf_app), Toast.LENGTH_SHORT).show();
  74. FirebaseCrashlytics.getInstance().log(getString(R.string.error_no_pdf_app));
  75. FirebaseCrashlytics.getInstance().recordException(e);
  76. }
  77. }

huangapple
  • 本文由 发表于 2020年9月17日 15:43:19
  • 转载请务必保留本文链接:https://go.coder-hub.com/63933432.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定