使用 Xamarin Forms 打开 PDF

2023-12-21

我有一个 pdf 文件,已使用 xamarin 表单添加为 Android 和 IOS 项目的 AndroidAsset 和 BundleResource。

我只是希望能够使用设备默认的任何 pdf 查看器从任何设备打开这些文件。

本质上,我只想能够做类似的事情:

Device.OpenUri("file:///android_asset/filename.pdf");

但这似乎不起作用。没有任何反应,也不会提示用户打开 pdf 文件。我不想使用任何允许 pdf 在应用程序中打开的第三方库,我只是希望它将用户重定向到 pdf 查看器或浏览器。

有任何想法吗?


首先,您需要一个接口类,因为您需要调用依赖项服务才能将文档传递给应用程序的本机实现:

因此,在您的共享代码中添加一个名为“IDocumentView.cs”的界面:

public interface IDocumentView
{
    void DocumentView(string file, string title);
}

Android

现在在你的android项目中创建相应的实现“DocumentView.cs”:

assembly: Dependency(typeof(DocumentView))]
namespace MyApp.Droid.Services
{
public class DocumentView: IDocumentView
{
    void IDocumentView.DocumentView(string filepath, string title)
    {
        try
        {
            File file = new File(filepath);

            String mime = FileTypes.GetMimeTypeByExtension(MimeTypeMap.GetFileExtensionFromUrl(filepath));
            File extFile = new File (Android.OS.Environment.GetExternalStoragePublicDirectory(Android.OS.Environment.DirectoryDocuments), file.Name);
            File extDir = extFile.ParentFile;
            // Copy file to external storage to allow other apps to access ist
            if (System.IO.File.Exists(extFile.AbsolutePath))
                System.IO.File.Delete(extFile.AbsolutePath);

            System.IO.File.Copy(file.AbsolutePath, extFile.AbsolutePath);
            file.AbsolutePath, extFile.AbsolutePath);
            // if copying was successful, start Intent for opening this file
            if (System.IO.File.Exists(extFile.AbsolutePath))
            {
                Intent intent = new Intent();
                intent.SetAction(Android.Content.Intent.ActionView);
                intent.SetDataAndType(Android.Net.Uri.FromFile(extFile), mime);
                MainApplication.FormsContext.StartActivityForResult(intent, 10);
            }
        }
        catch (ActivityNotFoundException anfe)
        {
            // android could not find a suitable app for this file
            var alert = new AlertDialog.Builder(MainApplication.FormsContext);
            alert.SetTitle("Error");
            alert.SetMessage("No suitable app found to open this file");
            alert.SetCancelable(false);
            alert.SetPositiveButton("Okay", (object sender, DialogClickEventArgs e) => ((AlertDialog)sender).Hide());
            alert.Show();
        }
        catch (Exception ex)
        {
            // another exception
            var alert = new AlertDialog.Builder(MainApplication.FormsContext);
            alert.SetTitle("Error");
            alert.SetMessage("Error when opening document");
            alert.SetCancelable(false);
            alert.SetPositiveButton("Okay", (object sender, DialogClickEventArgs e) => ((AlertDialog)sender).Hide());
            alert.Show();
        }
    }
}
}

请注意,MainApplication.FormsContext 是我添加到 MainApplication.cs 中的静态变量,以便能够快速访问应用程序的上下文。

在您的 Android 清单中,添加

在您的应用程序资源中,添加名为 file_paths.xml 的 xml 资源(到文件夹“xml”中),其中包含以下内容:

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

此外,您还需要确保目标设备上安装了能够处理相关文件的应用程序。 (Acrobat Reader、Word、Excel 等)。

iOS

iOS 已经内置了一个相当不错的文档预览,因此您可以简单地使用它(再次在您的 iOS 项目中创建一个名为“DocumentView.cs”的文件):

[assembly: Dependency(typeof(DocumentView))]
namespace MyApp.iOS.Services
{
public class DocumentView: IDocumentView
{
    void IDocumentView.DocumentView(string file, string title)
    {
        UIApplication.SharedApplication.InvokeOnMainThread(() =>
        {
            QLPreviewController previewController = new QLPreviewController();

            if (File.Exists(file))
            {
                previewController.DataSource = new PDFPreviewControllerDataSource(NSUrl.FromFilename(file), title);
                UIApplication.SharedApplication.KeyWindow.RootViewController.PresentViewController(previewController, true, null);
            }
        });
    }
}

public class PDFItem : QLPreviewItem
{
    public PDFItem(string title, NSUrl uri)
    {
        this.Title = title;
        this.Url = uri;
    }
    public string Title { get; set; }
    public NSUrl Url { get; set; }
    public override NSUrl ItemUrl { get { return Url; } }
    public override string ItemTitle { get { return Title; } }
}

public class PDFPreviewControllerDataSource : QLPreviewControllerDataSource
{
    PDFItem[] sources;

    public PDFPreviewControllerDataSource(NSUrl url, string filename)
    {
        sources = new PDFItem[1];
        sources[0] = new PDFItem(filename, url);
    }

    public override IQLPreviewItem GetPreviewItem(QLPreviewController controller, nint index)
    {
        int idx = int.Parse(index.ToString());
        if (idx < sources.Length)
            return sources.ElementAt(idx);
        return null;
    }

    public override nint PreviewItemCount(QLPreviewController controller)
    {
        return (nint)sources.Length;
    }
}
}

终于可以打电话了

DependencyService.Get<IDocumentView>().DocumentView(file.path, "Title of the view"); 

显示有问题的文件。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用 Xamarin Forms 打开 PDF 的相关文章

  • 如何在 Cassandra 中存储无符号整数?

    我通过 Datastax 驱动程序在 Cassandra 中存储一些数据 并且需要存储无符号 16 位和 32 位整数 对于无符号 16 位整数 我可以轻松地将它们存储为有符号 32 位整数 并根据需要进行转换 然而 对于无符号 64 位整
  • std::list 线程push_back、front、pop_front

    std list 线程安全吗 我假设不是这样 所以我添加了自己的同步机制 我认为我有正确的术语 但我仍然遇到问题 每个函数都由单独的线程调用 Thread1 不能等待 它必须尽可能快 std list
  • 如何在 C# 中打开 Internet Explorer 属性窗口

    我正在开发一个 Windows 应用程序 我必须向用户提供一种通过打开 IE 设置窗口来更改代理设置的方法 Google Chrome 使用相同的方法 当您尝试更改 Chrome 中的代理设置时 它将打开 Internet Explorer
  • 如何从本机 C(++) DLL 调用 .NET (C#) 代码?

    我有一个 C app exe 和一个 C my dll my dll NET 项目链接到本机 C DLL mynat dll 外部 C DLL 接口 并且从 C 调用 C DLL 可以正常工作 通过使用 DllImport mynat dl
  • 如何在 C++ 中标记字符串?

    Java有一个方便的分割方法 String str The quick brown fox String results str split 在 C 中是否有一种简单的方法可以做到这一点 The 增强分词器 http www boost o
  • 需要帮助优化算法 - 两百万以下所有素数的总和

    我正在尝试做一个欧拉计划 http projecteuler net问题 我正在寻找 2 000 000 以下所有素数的总和 这就是我所拥有的 int main int argc char argv unsigned long int su
  • ASP.NET Core 3.1登录后如何获取用户信息

    我试图在登录 ASP NET Core 3 1 后获取用户信息 如姓名 电子邮件 id 等信息 这是我在登录操作中的代码 var claims new List
  • 使用 C# 中的 CsvHelper 将不同文化的 csv 解析为十进制

    C 中 CsvHelper 解析小数的问题 我创建了一个从 byte 而不是文件获取 csv 文件的类 并且它工作正常 public static List
  • 如何获取 EF 中与组合(键/值)列表匹配的记录?

    我有一个数据库表 其中包含每个用户 年份组合的记录 如何使用 EF 和用户 ID 年份组合列表从数据库获取数据 组合示例 UserId Year 1 2015 1 2016 1 2018 12 2016 12 2019 3 2015 91
  • 两个静态变量同名(两个不同的文件),并在任何其他文件中 extern 其中一个

    在一个文件中将变量声明为 static 并在另一个文件中进行 extern 声明 我认为这会在链接时出现错误 因为 extern 变量不会在任何对象中看到 因为在其他文件中声明的变量带有限定符 static 但不知何故 链接器 瑞萨 没有显
  • 如何在 Android 中使用 C# 生成的 RSA 公钥?

    我想在无法假定 HTTPS 可用的情况下确保 Android 应用程序和 C ASP NET 服务器之间的消息隐私 我想使用 RSA 来加密 Android 设备首次联系服务器时传输的对称密钥 RSA密钥对已在服务器上生成 私钥保存在服务器
  • 编译时展开 for 循环内的模板参数?

    维基百科 here http en wikipedia org wiki Template metaprogramming Compile time code optimization 给出了 for 循环的编译时展开 我想知道我们是否可以
  • 有没有办法让 doxygen 自动处理未记录的 C 代码?

    通常它会忽略未记录的 C 文件 但我想测试 Callgraph 功能 例如 您知道在不更改 C 文件的情况下解决此问题的方法吗 设置变量EXTRACT ALL YES在你的 Doxyfile 中
  • 在 WPF 中使用 ReactiveUI 提供长时间运行命令反馈的正确方法

    我有一个 C WPF NET 4 5 应用程序 用户将用它来打开某些文件 然后 应用程序将经历很多动作 读取文件 通过许多插件和解析器传递它 这些文件可能相当大 gt 100MB 因此这可能需要一段时间 我想让用户了解 UI 中发生的情况
  • 相当于Linux中的导入库

    在 Windows C 中 当您想要链接 DLL 时 您必须提供导入库 但是在 GNU 构建系统中 当您想要链接 so 文件 相当于 dll 时 您就不需要链接 为什么是这样 是否有等效的 Windows 导入库 注意 我不会谈论在 Win
  • C# 中的 IPC 机制 - 用法和最佳实践

    不久前我在 Win32 代码中使用了 IPC 临界区 事件和信号量 NET环境下场景如何 是否有任何教程解释所有可用选项以及何时使用以及为什么 微软最近在IPC方面的东西是Windows 通信基础 http en wikipedia org
  • 为什么C++代码执行速度比java慢?

    我最近用 Java 编写了一个计算密集型算法 然后将其翻译为 C 令我惊讶的是 C 的执行速度要慢得多 我现在已经编写了一个更短的 Java 测试程序和一个相应的 C 程序 见下文 我的原始代码具有大量数组访问功能 测试代码也是如此 C 的
  • C++ 中的参考文献

    我偶尔会在 StackOverflow 上看到代码 询问一些涉及函数的重载歧义 例如 void foo int param 我的问题是 为什么会出现这种情况 或者更确切地说 你什么时候会有 对参考的参考 这与普通的旧参考有何不同 我从未在现
  • 指针和内存范围

    我已经用 C 语言编程有一段时间了 但对 C 语言还是很陌生 有时我对 C 处理内存的方式感到困惑 考虑以下有效的 C 代码片段 const char string void where is this pointer variable l
  • 类型或命名空间“MyNamespace”不存在等

    我有通常的类型或命名空间名称不存在错误 除了我引用了程序集 using 语句没有显示为不正确 并且我引用的类是公共的 事实上 我在不同的解决方案中引用并使用相同的程序集来执行相同的操作 并且效果很好 顺便说一句 这是VS2010 有人有什么

随机推荐

  • TotalResults 计数与 YouTube v3 搜索 API 返回的实际结果不匹配

    我们正在使用 youtube v3 搜索 API 我们发现 totalResults 计数与response items 字段中返回的项目列表不匹配 我在请求中请求 50 个视频 返回的响应显示 TotalResults 计数为 65 但响
  • 请解释一下 Amazon RDS/Mysql 中的这种内存消耗模式?

    Folks 有人可以解释运行 Mysql 的 Amazon RDS 上的这种内存消耗模式吗 在此图中 我在 03 30 升级到了 db m2 2xlarge 具有 34GB 可用内存 您可以非常清楚地看到切换 当客户端开始连接并访问该实例时
  • 空间数据类型(几何)到 GeoJSON

    我想转换geom geometry 数据类型转换为 GeoJSON 我怎么能这么做呢 例如 WKT 中的几何图形 POLYGON 455216 346127297 4288433 28426224 455203 386722146 4288
  • 在 Groovy 中动态添加元素到 ArrayList

    我是 Groovy 的新手 尽管阅读了很多有关此的文章和问题 但我仍然不清楚发生了什么 据我目前的了解 当您在 Groovy 中创建一个新数组时 底层类型是 Java ArrayList 这意味着它应该是可调整大小的 您应该能够将其初始化为
  • 如何防止遗传算法收敛于局部极小值?

    我正在尝试使用遗传算法构建 4 x 4 数独求解器 我对值收敛到局部最小值有一些问题 我正在使用排名方法并删除排名底部的两个答案可能性 并将它们替换为排名最高的两个答案可能性之间的交叉 为了获得避免局部最小值的额外帮助 我还使用了突变 如果
  • 文字字符串 [Lua 5.1]

    所以我开始学习Lua 5 1 我看到了一个叫做文字字符串的东西 我不知道这些是做什么的 手册上说 a 是一个铃声 但是当我输入时 print hello athere IDE 打印一个奇怪的正方形 上面写着 bel 因此 如果有人可以帮助我
  • 为什么结构标签不是 C 中的类型名称? [关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • 有人知道一个好的 MSI 日志查看器吗?

    相当简单的问题 有谁知道浏览 msi 日志文件的好实用程序吗 对任何提供过滤 不同标准和自定义操作 操作排序 属性和错误的良好视图的事物感兴趣 Thanks I found Rob Mensching 关于在 MSI 日志中查找的第一件事的
  • 如何使用 ReactJS 在 CKEditor 5 中使用 MathType 插件?

    我已经安装了三个包 ckeditor ckeditor5 react ckeditor ckeditor5 build classic wiris mathtype ckeditor5 src plugin 我可以设置简单的 ckedito
  • 如何优化具有数千个 WHERE 子句的 SQL 查询

    我对一个非常大的数据库进行了一系列查询 并且 WHERE 子句中有数十万个 OR 优化此类 SQL 查询的最佳且最简单的方法是什么 我找到了一些有关创建临时表和使用联接的文章 但我不确定 我是严肃 SQL 的新手 并且一直在将结果从一个SQ
  • iOS 15+ contextMenu 中的反向 ScrollView 错误

    感谢您花时间帮助他人 例如 我已经检查了所有解决方案这个帖子 https stackoverflow com questions 61726424 swiftui chat app the woes of reversed list and
  • 泛型:为什么编译器在这种情况下无法推断类型参数?

    我想编写一个扩展方法 该方法适用于其值是某种序列的字典 不幸的是 编译器似乎无法从我对该方法的使用中推断出通用参数 我需要明确指定它们 public static void SomeMethod
  • 找不到模块 java.xml.bind

    我是新来的javafx和日食 我从 eclipse market 安装了 eclipse 然后 javafx 我使用场景生成器生成了 fxml 代码 但无法执行它 我真的很受阻 找不到任何解决方案 I added add modules j
  • jQuery Datatables - 从其他页面检索信息

    我在从 jQuery 数据表获取信息时遇到问题 这是表格 我想获取表中存储的信息 我尝试通过以下方式做到这一点 var languages var people select name languageID each function la
  • 确定 WindowsIdentity 实例的嵌套组

    假设我有一个实例WindowsIdentity并想要获取它所属的组 我使用以下代码来获取列表 WindowsIdentity identity null get identity here identity Groups Translate
  • 检测到零个或 2 个或多个 [DropdownMenuItem] 具有相同的值

    我是 Flutter 新手 但我正在尝试创建一个 DropdownButtonFormField 但它不起作用 我收到一条错误消息 提示我有重复的值 有趣的是 我没有包含重复值的列表 我在 SO 上发现了一个类似的问题 解决方案说用一个值启
  • 在 Eclipse 中,我可以同时拥有多个控制台视图,每个视图显示不同的控制台吗?

    我正在开发一些在调试模式下记录到控制台的应用程序 我想从 Eclipse 内部运行和调试它们 并同时查看每个的控制台 但是 我有一个控制台选项卡 一次显示一个控制台输出 有没有办法可以将控制台拆分为多个视图 以便可以并排控制台输出 Yes
  • 以 Rails 4 形式将

    我有一个 Rails 4 表单 它在表单页面上使用 AJAX 构建部件列表 一旦零件清单建立在 ul 我想将列表作为 params 哈希中的参数值数组提交 My form div h2 prohibited this service fro
  • 如何使用下载链接从 Azure Blob 存储下载文件

    我制作了一个 Azure 云服务 您可以在其中使用 Blob 将文件上传和删除到云存储 我成功编写了一个方法 您可以从云服务中删除上传的 blob public string DeleteImage string Name Uri uri
  • 使用 Xamarin Forms 打开 PDF

    我有一个 pdf 文件 已使用 xamarin 表单添加为 Android 和 IOS 项目的 AndroidAsset 和 BundleResource 我只是希望能够使用设备默认的任何 pdf 查看器从任何设备打开这些文件 本质上 我只