Open Pdf File in Xamarin.forms

24,386

Solution 1

It all depends a bit on the fact if your PDF file is hosted elsewhere or locally on the device.

Hosted

If it is hosted online; the easiest way would be to just do a Device.OpenUri() with the URI of the PDF file, but this would open an external browser.

If you want to incorporate it within your app you can create a page with a WebView and navigate to the PDF in there. This should be pretty straight-forward.

Implement a page with a WebView, I'm going to assume you use XAML.

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="DisplayPDF.WebViewPage"
             Padding="0,20,0,0">
    <ContentPage.Content>
        <WebView Source="http://www.yoursite.com/your.pdf" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand" />
    </ContentPage.Content>
</ContentPage>

Local

Local on the device there is no unified way to do this. One way is to implement it through showing it in a WebView, which is basically the same as the WebView above, but you need to create a CustomRenderer for each platform you want to use. You can use the link provided by dylansturg as a reference.

Basically you implement the same page with a custom WebView component.

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:local="clr-namespace:DisplayPDF;assembly=DisplayPDF"
             x:Class="DisplayPDF.WebViewPage"
             Padding="0,20,0,0">
    <ContentPage.Content>
        <local:CustomWebView Uri="your.pdf" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand" />
    </ContentPage.Content>
</ContentPage>

Your custom WebView will look like this:

public class CustomWebView : WebView
{
    public static readonly BindableProperty UriProperty = BindableProperty.Create (propertyName:"Uri",
            returnType:typeof(string),
            declaringType:typeof(CustomWebView),
            defaultValue:default(string));

    public string Uri {
        get { return (string)GetValue (UriProperty); }
        set { SetValue (UriProperty, value); }
    }
}

It's basically just a WebView but we add a Uri property to it.

iOS

Now if you want to implement it for iOS, create a CustomRenderer in your platform project and implement it somewhat like this:

[assembly: ExportRenderer (typeof(CustomWebView), typeof(CustomWebViewRenderer))]
namespace DisplayPDF.iOS
{
    public class CustomWebViewRenderer : ViewRenderer<CustomWebView, UIWebView>
    {
        protected override void OnElementChanged (ElementChangedEventArgs<CustomWebView> e)
        {
            base.OnElementChanged (e);

            if (Control == null) {
                SetNativeControl (new UIWebView ());
            }
            if (e.OldElement != null) {
                // Cleanup
            }
            if (e.NewElement != null) {
                var customWebView = Element as CustomWebView;
                string fileName = Path.Combine (NSBundle.MainBundle.BundlePath, string.Format ("Content/{0}", WebUtility.UrlEncode (customWebView.Uri)));
                Control.LoadRequest (new NSUrlRequest (new NSUrl (fileName, false)));
                Control.ScalesPageToFit = true;
            }
        }
    }
}

Here you see how we create a native UIWebView and navigate it a file which is provided with our app. Note: the file should be in the Content file and marked as a BundleResource. If you are to download the file (or new versions of the policy) make sure you adjust the path accordingly.

Android

For Android it's a bit more work, you have to download the pdf.js library add it to you project under Assets. Make sure to check if the files are added to your repository as well. In my case the .js files where in my .gitignore file by default.

Now create a custom renderer like this:

[assembly: ExportRenderer (typeof(CustomWebView), typeof(CustomWebViewRenderer))]
namespace DisplayPDF.Droid
{
    public class CustomWebViewRenderer : WebViewRenderer
    {
        protected override void OnElementChanged (ElementChangedEventArgs<WebView> e)
        {
            base.OnElementChanged (e);

            if (e.NewElement != null) {
                var customWebView = Element as CustomWebView;
                Control.Settings.AllowUniversalAccessFromFileURLs = true;
                Control.LoadUrl (string.Format ("file:///android_asset/pdfjs/web/viewer.html?file={0}", string.Format ("file:///android_asset/Content/{0}", WebUtility.UrlEncode (customWebView.Uri))));
            }
        }
    }
}

Notice how we navigate to the pdf.js library here and provide it with a query parameter to specify our PDF file. Again, this is when you provide the file with the app. Also this is only available from API 19 and up.

For Windows you should also use the pdf.js library.

As per Nikolai's kind response it seems there is also a lightweight pdf.js lib for mobile I didn't us it myself yet, but it seems better to use for mobile use.

Since this question still seems relevant I thought it would be nice to update it with a more thorough blog post I did on this.

Solution 2

Recently I ran into a similar issue and wrote a blog and added sample code to github. I used PDfJs for displaying PDF in a custom webview.

Links :

  1. Xamarin.Forms PDF Viewer
  2. Project Url

Solution 3

  • Hosted

Hosted PDF Files are not opening in Webview. as iOS Webview can open PDF, While android Webview can not open the PDF Files. so if PDF url is Public, Then you can use below code for Android without use any library as well as you did not required to platform specific code.

    var pdfUrl = "http://yourdomain.com/pdffile.pdf";
    var googleUrl = "http://drive.google.com/viewerng/viewer?embedded=true&url=";
    if(Device.RuntimePlatform == Device.iOS)
    {
        webView.Source = pdfUrl;
    }
    else if(Device.RuntimePlatform == Device.Android)
    {
        webView.Source = new UrlWebViewSource() { Url = googleUrl + pdfUrl };
    }
Share:
24,386
Eng Soon Cheah
Author by

Eng Soon Cheah

Updated on July 05, 2022

Comments

  • Eng Soon Cheah
    Eng Soon Cheah about 2 years

    Currently I'm writing a Privacy policy for apps that I put in PDF format.
    May I ask about how to open PDF file for Xamarin.Forms? Any references Source Code?

  • Mikalai Daronin
    Mikalai Daronin over 7 years
    I would not recommend to use pdf.js web viewer as it's quite heavy. I would rather use pdf.js mobile viewer.
  • Gerald Versluis
    Gerald Versluis over 7 years
    Thank you @NikolaiDoronin I've added it to the answer as a note
  • Eng Soon Cheah
    Eng Soon Cheah over 7 years
    I use the web view <WebView Source="yoursite.com/your.pdf" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand" /> but in the emulator does not display anything.
  • Gerald Versluis
    Gerald Versluis over 7 years
    Does your URL exists? Can you access it from the emulator browser?
  • Admin
    Admin about 7 years
    @NikolaiDoronin I can't seem to figure out how to build the mobile viewer code. Any suggestions?
  • Alessandro Caliaro
    Alessandro Caliaro over 6 years
    @GeraldVersluis I have used the "WebView" approach but I have a white view... if I try to use the browser, it ask me some permissions... download file and something else... Do I give some permission to my app to visualize the PDF with a WebView?
  • Gerald Versluis
    Gerald Versluis over 6 years
    Please reach out to me on my email and I’ll have a look
  • Daniel
    Daniel over 6 years
    @GeraldVersluis Hello, could you please explain to me how we would use the mobile pdfjs view instead of the default one? Thanks :)
  • Gerald Versluis
    Gerald Versluis over 6 years
    Hi @Daniel as I recall you don't have to do anything special. Just use the mobile files instead of the full pdf.js library. Filenames etc. are the same, just the functionality is somewhat limited and more optimized for mobile usage. I have updated the answer with a link to my blog with a more thorough example.
  • Daniel
    Daniel over 6 years
    @GeraldVersluis Hey, so when I do exactly that, it says "The page at file:// says: Please build the pdfjs-dist library using 'gulp dist-install'"
  • Gerald Versluis
    Gerald Versluis over 6 years
    You need to build te library through gulp first or find a already prepared version
  • Mattia Ducci
    Mattia Ducci about 4 years
    following your suggestiona saved me hours of wasting time trying to find how to open a PDF in Xamarin.Android. Tested in Xamarin.Forms 4.5. Thank you