1

I have a sample pdf URL "http://www.africau.edu/images/default/sample.pdf". I want to show this pdf file and display in my mobile app using Xamarin.Forms. I tried using webviews and some custom renderers but did not work.

public class PdfViewRenderer : WebViewRenderer
    {
        internal class PdfWebChromeClient : WebChromeClient
        {
            public override bool OnJsAlert(Android.Webkit.WebView view, string url, string message, JsResult result)
            {
                if (message != "PdfViewer_app_scheme:print")
                {
                    return base.OnJsAlert(view, url, message, result);
                }
                using (var printManager = Forms.Context.GetSystemService(Android.Content.Context.PrintService) as PrintManager)
                {
                    printManager?.Print(FileName, new FilePrintDocumentAdapter(FileName, Uri), null);
                }
                return true;
            }
            public string Uri { private get; set; }
            public string FileName { private get; set; }
        }
        protected override void OnElementChanged(ElementChangedEventArgs<WebView> e)
        {
            base.OnElementChanged(e);
            if (e.NewElement == null)
            {
                return;
            }
            var pdfView = Element as PdfView;
            if (pdfView == null)
            {
                return;
            }
            if (string.IsNullOrWhiteSpace(pdfView.Uri) == false)


        {
            Control.SetWebChromeClient(new PdfWebChromeClient
            {
                Uri = pdfView.Uri,
                //FileName = GetFileNameFromUri(pdfView.Uri)
            });
        }
        Control.Settings.AllowFileAccess = true;
        Control.Settings.AllowUniversalAccessFromFileURLs = true;
        LoadFile(pdfView.Uri);
    }
    private static string GetFileNameFromUri(string uri)
    {
        var lastIndexOf = uri?.LastIndexOf("/", StringComparison.InvariantCultureIgnoreCase);
        return lastIndexOf > 0 ? uri.Substring(lastIndexOf.Value, uri.Length - lastIndexOf.Value) : string.Empty;
    }
    protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
    {
        base.OnElementPropertyChanged(sender, e);

        if (e.PropertyName != PdfView.UriProperty.PropertyName)
        {
            return;
        }
        var pdfView = Element as PdfView;
        if (pdfView == null)
        {
            return;
        }
        if (string.IsNullOrWhiteSpace(pdfView.Uri) == false)
        {
            Control.SetWebChromeClient(new PdfWebChromeClient
            {
                Uri = pdfView.Uri,
               // FileName = GetFileNameFromUri(pdfView.Uri)
            });
        }
        LoadFile(pdfView.Uri);
    }
    private void LoadFile(string uri)
    {
        if (string.IsNullOrWhiteSpace(uri))
        {
            return;
        }
        //Control.Resources = new Uri(string.Format("ms-appx-web:///Assets/pdfjs/web/viewer.html?file={0}", string.Format("ms-appx-web:///Assets/Content/{0}", WebUtility.UrlEncode(PdfView.Uri))));
        Control.LoadUrl($"file:///android_asset/pdfjs/web/viewer.html?file=file://{uri}");
        //Control.LoadUrl(uri);
        Control.LoadUrl(string.Format("ms-appx-web:///Assets/pdfjs/web/viewer.html?file={0}", string.Format("ms-appx-web:///Assets/Content/{0}", WebUtility.UrlEncode(uri))));
    }
}
bolkay
  • 1,881
  • 9
  • 20
Naresh
  • 129
  • 1
  • 11
  • 2
    Possible duplicate of [Open Pdf File in Xamarin.forms](https://stackoverflow.com/questions/41176549/open-pdf-file-in-xamarin-forms) – GiampaoloGabba Jun 13 '19 at 07:53
  • No, it's not working with webviews I have already tried. – Naresh Jun 13 '19 at 09:34
  • well... "it's not working" is too generic. you should at least post the error/result. Webviews are working for everyone, including myself, so there should be something else in your code/project. As a last resort, you can try a third party control, like syncfusion (free for small business): https://www.syncfusion.com/jquery/aspnet-web-forms-ui-controls/pdf-viewer – GiampaoloGabba Jun 13 '19 at 10:21

2 Answers2

2

Your XAML

<WebView x:Name="Webview"  
             HeightRequest="1000"  
             WidthRequest="1000"              
             VerticalOptions="FillAndExpand"/>

Put your Webview source like this

 Webview.Source = "https://docs.google.com/gview?
    embedded=true&url="+"http://www.africau.edu/images/default/sample.pdf";

enter image description here

Anand
  • 1,866
  • 3
  • 26
  • 49
1

In Android

[assembly: ExportRenderer(typeof(CustomWebView), typeof(CustomWebViewRenderer))]
namespace DipsDemoXaml.Droid.Renderer

public class CustomWebViewRenderer : WebViewRenderer
{
    public CustomWebViewRenderer(Context context) : base(context)
    { 
    }

    protected override void OnElementChanged(ElementChangedEventArgs<WebView> e)
    {
        base.OnElementChanged(e);

        if (e.NewElement != null)
        {              
            Control.Settings.AllowUniversalAccessFromFileURLs = true;
            Control.Settings.BuiltInZoomControls = true;
            Control.Settings.DisplayZoomControls = true;

        }
        this.Control.SetBackgroundColor(Android.Graphics.Color.Transparent);
    }
    protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
    {
        if (e.PropertyName != "Uri") return;
        var customWebView = Element as CustomWebView;
        if (customWebView != null)
        {
            Control.LoadUrl(string.Format("file:///android_asset/pdfjs/web/viewer.html?file={0}", string.Format("file:///android_asset/Content/{0}", WebUtility.UrlEncode(customWebView.Uri))));        
        }
    }

}

}

for iOS

  [assembly: ExportRenderer(typeof(CustomWebView), typeof(CustomWebViewRenderer))]
 namespace DipsDemoXaml.iOS.Renderes
  {
  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;
        }

        this.Opaque = false;
        this.BackgroundColor = Color.Transparent.ToUIColor();
    }
}

}

In shared

   namespace DipsDemoXaml.Custom.Renderer
{
   public class CustomWebView : WebView
   {
    public static readonly BindableProperty UriProperty =



   BindableProperty.Create(nameof(Uri),typeof(string),
    typeof(CustomWebView),default(string)) 
   ;

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

}

In XAML You can Call Like this

             <renderer:CustomWebView Uri="{Binding SelectedJournal.Uri}"  />

I think Problem in your Custom Rendering You can Create a new property like URI in a string and You can Call the URI you need a way to access Android and iOS webview for that you can call android asset pdf viewer for android and for Ios you can pass a new NSUrl to load the pdf inside your app

ish1104
  • 401
  • 4
  • 19