Opening a PDF with Xamarin Forms

后端 未结 1 1946
小鲜肉
小鲜肉 2021-01-27 14:40

I have a pdf i\'ve added as an AndroidAsset and a BundleResource for my Android and IOS projects using xamarin forms.

I just want to be able to open those files from any

1条回答
  •  抹茶落季
    2021-01-27 15:14

    First of all you will need an interface class, since you need to call the dependency service in order to pass your document to the native implementation(s) of your app:

    so in your shared code add an interface, called "IDocumentView.cs":

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

    Android

    Now in your android project create the corresponding implementation "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();
            }
        }
    }
    }
    

    Please note that MainApplication.FormsContext is a static variable I added to my MainApplication.cs in order to be able to access the Context of the app quickly.

    In your Android manifest, add

    In your application resources, add an xml resource (into folder "xml") called file_paths.xml with the following content:

    
       
       
    
    

    Also you need to ensure that there are apps installed on the target device, which are able to handle the file in question. (Acrobat Reader, Word, Excel, etc...).

    iOS

    iOS already comes with a quite nice document preview built in, so you can simply use that (again create a file named "DocumentView.cs" in your iOS Project):

    [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;
        }
    }
    }
    

    Finally you can call

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

    to display the file in question.

    0 讨论(0)
提交回复
热议问题