【问题标题】:Open local pdf file in Xamarin Forms在 Xamarin Forms 中打开本地 pdf 文件
【发布时间】:2020-07-29 14:30:53
【问题描述】:

我正在尝试以 xamarin 形式打开一个本地 pdf 文件,我的代码:

var context = Forms.Context;
Java.IO.File javaFile = new Java.IO.File(filePath);
Android.Net.Uri uri = FileProvider.GetUriForFile(context, "myAuth.fileprovider", javaFile);
context.GrantUriPermission(context.PackageName, uri, ActivityFlags.GrantReadUriPermission);                        
Intent intent = new Intent(Intent.ActionView);
intent.SetDataAndType(uri, "application/pdf");
intent.SetFlags(ActivityFlags.ClearWhenTaskReset | ActivityFlags.NewTask);
Xamarin.Forms.Forms.Context.StartActivity(intent);

我遵循了几个这样的教程:How to get actual path from Uri xamarin android

但现在我的问题是我不知道 uri 是否正在获取文件的真实路径:

我明白了:

javaFile = "/storage/emulated/0/Download/myReport.pdf"(勾选并存在)

uri = "content://myAuth.fileprovider/external_files/Download/myReport.pdf"

但我在我的 pdf 应用程序上收到此错误“无法访问此文件”。我需要改变什么来获取文件的真实路径?我认为问题出在这里:

Android.Net.Uri uri = FileProvider.GetUriForFile(context, "myAuth.fileprovider", javaFile);

但不知道还有什么变化才能起作用。非常感谢!

【问题讨论】:

    标签: xamarin.forms


    【解决方案1】:

    你应该在AndroidManifest.xmlapplication标签中设置FileProvider。

    <manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="1" android:versionName="1.0" package="com.companyname.boxviewcolordemo" android:installLocation="auto">
        <uses-sdk android:minSdkVersion="21" android:targetSdkVersion="28" />
        <application android:label="BoxViewColorDemo.Android">
    
        <provider android:name="android.support.v4.content.FileProvider"
              android:authorities="${applicationId}.fileprovider"
              android:exported="false"
              android:grantUriPermissions="true">
    
          <meta-data android:name="android.support.FILE_PROVIDER_PATHS"
                           android:resource="@xml/file_paths"></meta-data>
        </provider>
      </application>
        <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
        <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
        <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    </manifest>
    

    然后在xml文件夹中创建file_paths.xml

    file_paths.xml添加以下代码。

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

    那么在你的dependenceService成就中,你应该使用下面的代码。注意: FileProvider.GetUriForFile(context, context.ApplicationContext.PackageName + ".fileprovider", file);第二个属性是你的包名和“.fileprovider”

    [assembly: Dependency(typeof(OpenPDF))]
    namespace BoxViewColorDemo.Droid
    {
        public class OpenPDF : IOpenFile
        {
            public void OpenPDf(string filePath)
            {
                var rs = System.IO.File.Exists(filePath);
                if (rs)
                {
                    var context = Android.App.Application.Context;
                    var file = new Java.IO.File(filePath);
    
                    var uri = FileProvider.GetUriForFile(context, context.ApplicationContext.PackageName  + ".fileprovider", file);
                    try
                    {
                        var intent = new Intent(Intent.ActionView);
                        intent.AddCategory(Intent.CategoryDefault);
                        intent.AddFlags(ActivityFlags.GrantReadUriPermission);
               
                        intent.AddFlags(ActivityFlags.ClearWhenTaskReset | ActivityFlags.NewTask);
                        intent.SetDataAndType(uri, "application/pdf");
                        context.StartActivity(intent);
                    }
                    catch (Exception e)
                    {
                        Toast.MakeText(context, e.Message, ToastLength.Long).Show();
                    }
                }
                
            }
        }
    }
    

    并且不要忘记在运行时授予读/写权限。为了测试,可以在MainActivity.csOnCreate方法中添加如下代码。

      if (ContextCompat.CheckSelfPermission(this, Manifest.Permission.WriteExternalStorage) != (int)Permission.Granted)
                {
                    RequestPermissions(new string[] { Manifest.Permission.ReadExternalStorage, Manifest.Permission.WriteExternalStorage }, 0);
                }
    

    我把pdf文件放到Download文件夹下,我的filePath是DependencyService.Get&lt;IOpenFile&gt;().OpenPDf("/storage/emulated/0/Download/test.pdf");

    【讨论】:

    • 我遵循所有这些步骤,但最终问题出在上下文中。所以这是正确的解决方案,但我需要更改 MainActivity.Current 的上下文,并创建一个新变量“public static MainActivity Current = null;”并在 OnCreate 方法“Current = this;”中初始化。
    【解决方案2】:

    如果有人按照之前的步骤操作但仍然无法正常工作,并且问题在 var uri = FileProvider.GetUriForFile(context, context.ApplicationContext.PackageName + ".fileprovider", file); 行中继续存在。也检查一下:

    1 - 检查它是否在应用程序标签中

    2 - 检查权限,通常您会使用“${applicationId}.provider”,但如果不起作用,请使用文字,例如 myAuth.fileprovider

    <application>
    ...
        <provider ..android:authorities="myAuth.fileprovider" ..>
            <meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/file_paths"></meta-data>
        </provider>
    </application>
    

    3 - 检查上下文,var context = Android.App.Application.Context; 通常是这样,但如果这个不起作用,您可以尝试MainActivity.Current,但您需要先在 MainActivity 类中创建一个静态变量,如下所示:@ 987654325@ 并初始化为 OnCreate 方法Current = this;。那是我的问题

    4 - 检查数据的 MimeType 类型,intent.SetDataAndType(uri, "application/pdf");

    再次感谢 Leon Lu - MSFT 的回答,这只是针对与我面临同样问题的任何人的扩展。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-12-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-04-02
      • 1970-01-01
      相关资源
      最近更新 更多