使用Xamarin表单打开PDF

时间:2018-09-12 01:56:21

标签: c# mobile xamarin.forms

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

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

本质上,我只希望能够执行以下操作:

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

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

有什么想法吗?

1 个答案:

答案 0 :(得分:2)

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

因此,在您的共享代码中添加一个名为“ 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"); 

显示相关文件。