Open Pdf File in Xamarin.forms
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 :
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 };
}
Eng Soon Cheah
Updated on July 05, 2022Comments
-
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 over 7 yearsI would not recommend to use pdf.js web viewer as it's quite heavy. I would rather use pdf.js mobile viewer.
-
Gerald Versluis over 7 yearsThank you @NikolaiDoronin I've added it to the answer as a note
-
Eng Soon Cheah over 7 yearsI use the web view <WebView Source="yoursite.com/your.pdf" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand" /> but in the emulator does not display anything.
-
Gerald Versluis over 7 yearsDoes your URL exists? Can you access it from the emulator browser?
-
Admin about 7 years@NikolaiDoronin I can't seem to figure out how to build the mobile viewer code. Any suggestions?
-
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 over 6 yearsPlease reach out to me on my email and I’ll have a look
-
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 over 6 yearsHi @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 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 over 6 yearsYou need to build te library through gulp first or find a already prepared version
-
Mattia Ducci about 4 yearsfollowing 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