【问题标题】:Problems with FileProviderFileProvider 的问题
【发布时间】:2017-04-04 22:10:30
【问题描述】:

我从一个不同的问题开始,导致我来到这里,所以我只是从头开始。我有一个应用程序,允许用户为他们的客户创建报价。该应用程序为报价创建一个 pdf 文件并将其专门保存到外部存储中,以便其他应用程序可以访问它。最近,从我的应用程序中打开某些应用程序时,我似乎无法查看 pdf(谷歌 pdf 查看器、谷歌驱动器查看器显示空白屏幕,而 adobe acrobat 非常好)。我知道 pdf 很好,因为我可以从文件管理器中查看它而没有任何问题。只是从我的应用程序中打开它时它不起作用。

我提供了一个意图,其 uri 类似于 content://path/to/external/storage/MyApp/customerName/quote.pdf

我曾经以file://... 的形式提供它,但遇到了 sdk 24 中引入的暴露的 uri 异常,所以我只是将 file:// 重命名为 content:// 并且一切似乎都在工作,直到我发现了 google pdf 查看器应用程序。

现在我假设它与我显然应该使用的 fileProvider 类有关。但我似乎根本无法让它工作,而且我发现的有关该问题的其他问题似乎都没有工作,所以这就是我目前所拥有的:

file_paths.xml(尝试了几个不同的路径,似乎没有一个有效。还有用户创建的多个客户文件夹,我无法在 xml 文件中指定它们,因为我不知道它们将被命名,但是为了测试,我把一个放在那里只是为了看看这是否是问题,它仍然不起作用)

<?xml version="1.0" encoding="utf-8"?>
 <paths>
     <external-path name="external_files" path="." />
     <external-path name="myApp" path="MyApp/" />
     <external-path name="myAppa" path="MyApp/customerFolder/" />
     <external-path name="myAppb" path="/" />
 </paths> 

清单文件(其中一个包含使用的文件提供程序,这就是我有工具的原因:在其中替换行,我不知道这是否导致问题,它用于将照片保存到我试图从同一目录查看 pdf)

    <provider
        android:name="android.support.v4.content.FileProvider"
        android:authorities="${applicationId}.provider"
        android:exported="false"
        android:grantUriPermissions="true"
        tools:replace="authorities"
        >
        <meta-data
            android:name="android.support.FILE_PROVIDER_PATHS"
            android:resource="@xml/file_paths"
            tools:replace="android:resource"/>
    </provider>

以及启动查看 pdf 的意图的页面:

String url = "file:///storage/emulated/0/MyApp/customerFolder/quote.pdf";
File mFile = new File(url);
Uri pdfURI = FileProvider.getUriForFile(activity, activity.getApplicationContext().getPackageName() + ".provider", mFile);

Intent intent = new Intent(android.content.Intent.ACTION_VIEW);
            intent.setData(pdfURI);
            intent.setType("application/pdf");
            intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);                         
activity.startActivity(intent);

这一直给我以下错误 java.lang.IllegalArgumentException: Failed to find configured root that contains /file:/storage/emulated/0/MyApp/customerFolder/quote.pdf 在包含FileProvider.getUriForFile() 方法的行上。我检查了路径,它是正确的,

或者,这是我曾经拥有的代码,它适用于 Adob​​e Acrobat,但不适用于 Google pdf 查看器或 Google Drive 查看器。如果有某种方法可以解决我缺少的问题,那么我可以忘记 fileProvider:

String url = (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N ? "content://" : "file://") + "/storage/emulated/0/MyApp/customerFolder/quote.pdf";
Intent intent = new Intent(android.content.Intent.ACTION_VIEW);
intent.setDataAndType(Uri.parse(url),"application/pdf");
activity.startActivity(intent);

【问题讨论】:

    标签: android android-fileprovider


    【解决方案1】:

    我只是将 file:// 重命名为 content:// 并且似乎一切正常,直到我发现了 google pdf 查看器应用程序。

    这应该适用于零设备。 Adobe 可能会尝试像这样修复损坏的输入。

    String url = "file:///storage/emulated/0/MyApp/customerFolder/quote.pdf";
    File mFile = new File(url);
    

    file:///storage/emulated/0/MyApp/customerFolder/quote.pdf 不是文件系统路径。那是一个网址。对于您的实验,请使用/storage/emulated/0/MyApp/customerFolder/quote.pdf。最后,不要对路径进行硬编码。

    &lt;external-path name="myApp" path="MyApp/" /&gt; 元素将覆盖该特定文件系统路径。

    【讨论】:

    • 我写出了 url 以便我可以看到实际路径是什么,我通常使用 Environment.getExternalStorageDirectory()。但是在删除file:// 并仅使用/storage/emulated/... 之后,我似乎更近了一步,它创建了一个content://com.com.MyApp.provider/myApp/customerFolder/quote.pdf 的网址,但没有一个pdf查看器打开它,他们给出了“没有收到文件”或无法打开之类的错误文件。
    • 文件在那里,使用 external_files 路径给出了不同的 url,但结果相同。我觉得这和以前发生的事情很相似。 pdf 应用程序现在至少给我错误,但 adobe 根本不起作用。
    • @JStephen:这很奇怪。通常,如果你错过了FLAG_GRANT_READ_URI_PERMISSION,我会期待这种行为,但你有它。 This sample app of mine 有效,但我集成了一个修复程序以帮助提高 FileProvider 与编写不佳的客户端应用程序的兼容性。
    • 我检查了您的示例应用程序,它正在通过getFilesDir() 使用来自内部存储的文件,问题是我的文件通过Environment.getExternalStorageDirectory() 存储在外部存储中我能够将我的文件从外部复制到内部存储,然后使用内部文件打开。但理想情况下,我应该能够使用其外部链接打开 pdf。
    【解决方案2】:

    终于弄明白了。基于 CommonsWare 的示例应用程序,我通过将文件复制到内部存储并使用该内部存储 url 使其工作,但使用同一文件的外部存储 url 仍然无法工作。这导致我来到this answer here,显然setType() 将清除setData() 的数据集。不过使用内部url的时候就不是这样了,不过我还是试了一下,改了这个

    Intent intent = new Intent(android.content.Intent.ACTION_VIEW);
    intent.setData(pdfURI);
    intent.setType("application/pdf");
    

    到这里

    Intent intent = new Intent(android.content.Intent.ACTION_VIEW);
    intent.setDataAndType(pdfURI,"application/pdf");
    

    突然间它也与外部 url 一起工作了。一个非常令人沮丧的不一致,特别是在我的情况下,因为我最初是正确的,但将它分成两种方法,认为如果其中一个出错了,我会通过行号知道。

    我的清单保持不变,但我将路径文件减少到这个

    <paths>
        <external-path name="external_files" />
    </paths>
    

    希望这对其他人有所帮助。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-10-11
      • 2017-05-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-10-03
      • 1970-01-01
      相关资源
      最近更新 更多