将多个URI发送到浏览器(由FileProvider从内部存储打开HTML文件)

时间:2018-04-27 08:47:22

标签: android android-intent uri android-fileprovider internal-storage

前言:我使用C#和Xamarin,但工作流程是一样的。 我想在Android上的浏览器中打开/显示(离线)HTML文件(与其他HTML,CSS和JavaScript文件链接)。这是index.html

<!DOCTYPE html>
<html data-mc-runtime-file-type="Default" class="_Skins_HTML5___Top_Navigation">
    <head>
        <meta http-equiv="X-UA-Compatible" content="IE=edge" />
        <meta charset="utf-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" /><title></title>
        <script type="text/javascript" src="Resources/Scripts/custom.modernizr.js">
        </script>
        <script type="text/javascript" src="Resources/Scripts/jquery.min.js">
        </script>
        <script type="text/javascript" src="Resources/Scripts/plugins.min.js">
        </script>
        <script type="text/javascript" src="Resources/Scripts/require.min.js">
        </script>
        <script type="text/javascript" src="Resources/Scripts/require.config.js">
        </script>
        <script type="text/javascript" src="Resources/Scripts/MadCapAll.js">
        </script>
    </head>
    <body>
    </body>
</html>

这些文件位于内部应用存储空间/data/data/com.xxx.xxx/files/help中,它们位于不同的子文件夹中,如下所示:

drwxrwxr-x 4 root root   4096 2018-04-26 09:22 Content
drwxrwxr-x 2 root root   4096 2018-04-26 09:22 Data
-rw-rw-rw- 1 root root  11327 2018-01-12 17:24 HTML5 - Top Navigation.mclog
drwxrwxr-x 3 root root   4096 2018-04-26 09:22 Resources
drwxrwxr-x 4 root root   4096 2018-04-26 09:22 Skins
-rw-rw-rw- 1 root root 344798 2018-01-12 17:24 csh.js
-rw-rw-rw- 1 root root    951 2018-01-12 17:24 index.html
-rw-rw-rw- 1 root root 348211 2018-01-12 17:24 index.js
-rw-rw-rw- 1 root root   1269 2018-01-12 17:24 index.mcwebhelp
-rw-rw-rw- 1 root root   2622 2018-01-12 17:24 index_CSH.html

我正在使用FileProvider(类似于Android Manifest中定义的):

[ContentProvider(new[] { "${applicationId}.html.fileprovider" }, Name = "com.xxx.xxx.HelpFileProvider", GrantUriPermissions = true, Exported = false)]
[MetaData("android.support.FILE_PROVIDER_PATHS", Resource = "@xml/help_html_provider_paths")]
class HelpFileProvider : FileProvider
{

}

我在XML文件(help_html_provider_paths.xml)中添加了路径:

<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
  <files-path name="help" path="help/"/>
</paths>

要从应用程序外部打开index.html文件,需要创建一个Uri:

Android.Net.Uri contentUri = FileProvider.GetUriForFile(_context, _context.PackageName + ".html.fileprovider", newFile);

但仅限于index.html,试图打开它会导致空白屏幕和以下错误(其中多个):

01-01 01:36:38.096 E/DatabaseUtils( 4924): Writing exception to parcel
01-01 01:36:38.096 E/DatabaseUtils( 4924): java.lang.SecurityException: Permission Denial: reading com.xxx.xxx.HelpFileProvider uri content://com.xxx.xxx.html.fileprovider/help/Resources/Scripts/jquery.min.js from pid=4989, uid=10052 requires the provider be exported, or grantUriPermission()
01-01 01:36:38.096 E/DatabaseUtils( 4924):  at android.content.ContentProvider.enforceReadPermissionInner(ContentProvider.java:608)
01-01 01:36:38.096 E/DatabaseUtils( 4924):  at android.content.ContentProvider$Transport.enforceReadPermission(ContentProvider.java:483)
01-01 01:36:38.096 E/DatabaseUtils( 4924):  at android.content.ContentProvider$Transport.enforceFilePermission(ContentProvider.java:474)
01-01 01:36:38.096 E/DatabaseUtils( 4924):  at android.content.ContentProvider$Transport.openTypedAssetFile(ContentProvider.java:419)
01-01 01:36:38.096 E/DatabaseUtils( 4924):  at android.content.ContentProviderNative.onTransact(ContentProviderNative.java:313)
01-01 01:36:38.096 E/DatabaseUtils( 4924):  at android.os.Binder.execTransact(Binder.java:565)

我知道 - 这意味着其他文件无法打开,因为它们没有URI,只有index.html。

然后我尝试了不同的方法(获取所有文件URI并使用ClipData发送它们)没有成功,如下所示:

public void OpenHtml(string directory, string file) // "PATH/TO/help/" and "index.html"
{
    try
    {
        Java.IO.File filePath = new File(_context.FilesDir.AbsolutePath, directory);
        Java.IO.File newFile = new File(filePath, file);

        List<File> allFiles = new List<File>();
        Listfiles(filePath.AbsolutePath, allFiles); // Get recursiv all files from each subfolder

        Android.Net.Uri contentUri = FileProvider.GetUriForFile(_context, _context.PackageName + ".html.fileprovider", newFile);
        ClipData clipData = ClipData.NewUri(_context.ContentResolver, "com.xxx.xxx", contentUri);

        allFiles.ForEach(file1 =>
        {
            Android.Net.Uri uri = FileProvider.GetUriForFile(_context, _context.PackageName + ".html.fileprovider", file1);
            clipData.AddItem(new ClipData.Item(uri));
        });

        var intent = new Intent(Intent.ActionView, contentUri);

        intent.ClipData = clipData;
        intent.AddFlags(ActivityFlags.GrantReadUriPermission);
        _context.StartActivity(intent);
    }
    catch (ActivityNotFoundException ex)
    {
        Logger.Error("No Browser installed!!", ex);
        throw new ApplicationException();
    }
    catch (Exception ex)
    {
        Logger.Error("Failed to display html", ex);
    }
}

我忘了什么吗?或者这种特殊情况是不可能的,因为html文件中的链接与URI不匹配?

0 个答案:

没有答案