2016-11-07 64 views
0

我试图使用文件提供程序显示PDF文件。但是,当PDF阅读器打开时,它不包含文件的内容。该文件存储在应用程序的内部存储器中的文件夹中。FileProvider Xamarin不显示文件

清单:

<provider android:name="android.support.v4.content.FileProvider" android:authorities="com.mycom.myapp.fileprovider" android:exported="false" android:grantUriPermissions="true"> 
     <meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/file_paths" /> 
    </provider> 

File_paths:

<paths xmlns:android="http://schemas.android.com/apk/res/android"> 
    <files-path name="export" /> 
</paths> 

pdfViewRenderer.cs:

string libraryPath = Environment.GetFolderPath(Environment.SpecialFolder.Personal); 
var path = Path.Combine(libraryPath, fileName); 


string application = "application/pdf"; 
Java.IO.File javaFile = new Java.IO.File(fileName);//externalPath 


Android.Net.Uri androidURI = FileProvider.GetUriForFile(Forms.Context.ApplicationContext, "com.mycom.myapp.fileprovider", javaFile); 


Intent intent = new Intent(Intent.ActionView); 
intent.SetDataAndType(androidURI, Filetype); 
intent.AddFlags(ActivityFlags.GrantReadUriPermission); 
intent.SetFlags(ActivityFlags.NoHistory); 
intent.SetFlags(ActivityFlags.ClearWhenTaskReset); 


Forms.Context.StartActivity(Intent.CreateChooser(intent, "Open PDF")); 

回答

0

您可以在应用程序的.apk没有直接访问文件时,`。 apk“不会将其本身表现为a 文件系统。

您可以将AndroidAsset复制到您的应用程序缓存目录,然后授予FileProvider权限基于文件的Uri以允许外部应用程序访问你的应用程序的沙箱范围内的文件。

添加provider内的AndroidManifestapplication元素:

<provider 
android:name="android.support.v4.content.FileProvider" 
android:authorities="com.sushihangover.artificialgravitycalc" 
android:exported="false" 
android:grantUriPermissions="true"> 
<meta-data 
    android:name="android.support.FILE_PROVIDER_PATHS" 
    android:resource="@xml/cache_path" /> 

然后加入,其文件名匹配的XML文件提供者的android:resource:Resources/xml包含您授权路径访问:

<paths xmlns:android="http://schemas.android.com/apk/res/android"> 
    <cache-path name="appcache" path="." /> 
</paths> 

注意:您可能必须将xml目录添加到您的Resources文件夹中,因为默认情况下不会通过基本Xamarin.Android项目模板添加该目录。 (它必须被命名为xml,小写)

添加您.pdfAssets目录,并确保它被标记为AndroidAsset构建类型:

enter image description here

现在,您可以复制Asset到您的应用的缓存目录,创建一个基于FileProviderUri,授予对其的读取访问权限,并尝试将其打开。在这种情况下,你需要一个发布,它处理application/pdf的MIME类型的至少一个已安装应用程序:

var pdfAssetName = "PlayScriptLanguageSpecification.pdf"; 
var savePath = Path.GetTempFileName(); 
using (var assetStream = Application.Context.Assets.Open(pdfAssetName)) 
using (var fileStream = new FileStream(savePath, FileMode.Create, FileAccess.Write)) 
{ 
    byte[] buffer = new byte[1024]; 
    int readCount = 0; 
    do 
    { 
     readCount = assetStream.Read(buffer, 0, buffer.Length); 
     fileStream.Write(buffer, 0, readCount); 
    } while (readCount > 0); 
} 
var targetIntent = new Intent(Intent.ActionView); 
var file = new Java.IO.File(savePath); 
var uri = FileProvider.GetUriForFile(this, PackageName, file); 
targetIntent.SetDataAndType(uri, "application/pdf"); 
targetIntent.SetFlags(ActivityFlags.NoHistory); 
targetIntent.SetFlags(ActivityFlags.GrantReadUriPermission); 
Intent intent = Intent.CreateChooser(targetIntent, "Open File"); 
StartActivity(intent); 
+0

这看起来不错,但其结果产生的.tmp将一个PDF浏览器中这种开放? – Simon

+0

@Simon对我使用过的所有PDF查看器都很好,但是您可以使用'GetTempPath'并添加您选择的文件名.. i..e.'var savePath = Path.Combine(Path.GetTempPath(),pdfAssetName );' – SushiHangover

+0

我昨天就和它一起工作......而且你的解决方案很好,但是仍然给我带来了同样的问题。进一步看,我发现有一个权限问题。接收应用程序正在获得权限拒绝。通过授予URI许可,这解决了它,我可以使用我的原始代码..我使用内部存储如果它的工作是错误的吗? – Simon