)
We use cookies to give you the best experience on our website. If you continue to browse, then you agree to our privacy policy and cookie policy. (Last updated on: June 24, 2019).
Unfortunately, activation email could not send to your email. Please try again.
Syncfusion Feedback

How to print PDF documents in Xamarin.Forms platform?

Platform: Xamarin.Forms |
Control: PdfViewer |
Published Date: May 17, 2018 |
Last Revised Date: June 1, 2020 |
.NET Framework: 4.5.1

PDF documents can be printed in Xamarin Forms’ Android, iOS, and UWP platforms by obtaining the currently loaded PDF as stream and printing the stream using native printing functionalities available in the respective platforms using DependencyService of Xamarin Forms. These platform specific printing options can be used by defining an interface in the portable project and implementing the same in the platform projects using the specific code.

The following code snippets illustrate printing PDF documents in Xamarin Forms’ Android, iOS, and UWP platforms.

Portable

Define the following interface.

C#

namespace PDFPrintingSample
{
    public interface IPrintService
    {
        void Print(Stream inputStream, string fileName);
    }
}

 

Load the PDF to PdfViewer. Call the Print method with the stream obtained from PdfViewer and file name using DependencyService when the print button is clicked in the code behind. Give the name of the interface as the type parameter to the method DependencyService.Get<T>().

C#

public MainPage()
{
     InitializeComponent();
     documentStream =    typeof(App).GetTypeInfo().Assembly.GetManifestResourceStream("PDFPrintingSample.Assets.GIS Succinctly.pdf");
     pdfViewerControl.LoadDocument(documentStream);
     printButton.Clicked += PrintButton_Clicked;
}
 
private void PrintButton_Clicked(object sender, EventArgs e)
{
            //Obtain the PDF as a stream
            Stream stream = pdfViewerControl.SaveDocument();
            DependencyService.Get<IPrintService>().Print(stream, "GIS Succinctly.pdf");
}

 

Implement the interface in the platform projects with the available platform specific printing options.

Android

C#

//Register the Android implementation of the interface with DependencyService
[assembly: Dependency(typeof(PrintService))]
 
namespace PDFPrintingSample.Droid
{
    class PrintService : IPrintService
    {
        public void Print(Stream inputStream, string fileName)
        {
            if (inputStream.CanSeek)
                //Reset the position of PDF document stream to be printed
                inputStream.Position = 0;            
            //Create a new file in the Personal folder with the given name
            string createdFilePath = System.IO.Path.Combine(System.Environment.GetFolderPath(System.Environment.SpecialFolder.Personal), fileName);
            //Save the stream to the created file
            using (var dest = System.IO.File.OpenWrite(createdFilePath))
                inputStream.CopyTo(dest);
            string filePath = createdFilePath;
  var activity = Xamarin.Essentials.Platform.CurrentActivity;
            PrintManager printManager = (PrintManager)activity.GetSystemService(Context.PrintService);       
     PrintDocumentAdapter pda = new CustomPrintDocumentAdapter(filePath);
            //Print with null PrintAttributes
            printManager.Print(fileName, pda, null);
        }
    }
}

 

Define a class derived from the PrintDocumentAdapter and write the contents of the input file to the print destination in the OnWrite method.

C#

namespace PDFPrintingSample.Droid
{
    internal class CustomPrintDocumentAdapter : PrintDocumentAdapter
    {
        internal string FileToPrint { get; set; }
 
        internal CustomPrintDocumentAdapter(string fileDesc)
        {
            FileToPrint = fileDesc;
        }
        public override void OnLayout(PrintAttributes oldAttributes, PrintAttributes newAttributes, CancellationSignal cancellationSignal, LayoutResultCallback callback, Bundle extras)
        {
            if (cancellationSignal.IsCanceled)
            {
                callback.OnLayoutCancelled();
                return;
            }
 
 
            PrintDocumentInfo pdi = new PrintDocumentInfo.Builder(FileToPrint).SetContentType(Android.Print.PrintContentType.Document).Build();
 
            callback.OnLayoutFinished(pdi, true);
        }
 
        public override void OnWrite(PageRange[] pages, ParcelFileDescriptor destination, CancellationSignal cancellationSignal, WriteResultCallback callback)
        {
            InputStream input = null;
            OutputStream output = null;
 
            try
            {
                //Create FileInputStream object from the given file
                input = new FileInputStream(FileToPrint);
                //Create FileOutputStream object from the destination FileDescriptor instance
                output = new FileOutputStream(destination.FileDescriptor);
 
                byte[] buf = new byte[1024];
                int bytesRead;
 
                while ((bytesRead = input.Read(buf)) > 0)
                {
                    //Write the contents of the given file to the print destination
                    output.Write(buf, 0, bytesRead);
                }
 
                callback.OnWriteFinished(new PageRange[] { PageRange.AllPages });
 
            }
            catch (FileNotFoundException ee)
            {
                //Catch exception
            }
            catch (Exception e)
            {
                //Catch exception
            }
            finally
            {
                try
                {
                    input.Close();
                    output.Close();
                }
                catch (IOException e)
                {
                    e.PrintStackTrace();
                }
            }
        }
    }
}

 

iOS

C#

//Register the iOS implementation of the interface with DependencyService
[assembly: Dependency(typeof(PrintService))]
 
namespace PDFPrintingSample.iOS
{
    class PrintService : IPrintService
    {
        public void Print(Stream inputStream, string fileName)
        {
            var printInfo = UIPrintInfo.PrintInfo;
            printInfo.OutputType = UIPrintInfoOutputType.General;
            printInfo.JobName = "Print PDF Sample";
 
            //Get the path of the MyDocuments folder
            var documents = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
            //Get the path of the Library folder within the MyDocuments folder
            var library = Path.Combine(documents, "..", "Library");
            //Create a new file with the input file name in the Library folder
            var filepath = Path.Combine(library, fileName);
 
            //Write the contents of the input file to the newly created file
            using (MemoryStream tempStream = new MemoryStream())
            {
                inputStream.Position = 0;
                inputStream.CopyTo(tempStream);
                File.WriteAllBytes(filepath, tempStream.ToArray());
            }
 
            var printer = UIPrintInteractionController.SharedPrintController;
            printInfo.OutputType = UIPrintInfoOutputType.General;
 
            printer.PrintingItem = NSUrl.FromFilename(filepath);
            printer.PrintInfo = printInfo;
 
 
            printer.ShowsPageRange = true;
 
            printer.Present(true, (handler, completed, err) => {
                if (!completed && err != null)
                {
                    Console.WriteLine("error");
                }
            });
        }
    }
}

 

UWP

C#

//Register the UWP implementation of the interface with DependencyService
[assembly: Xamarin.Forms.Dependency(typeof(PrintService))]
 
namespace PDFPrintingSample.UWP
{
    class PrintService : IPrintService
    {
        internal int pageCount;
        internal global::Windows.Data.Pdf.PdfDocument pdfDocument;
        private PrintDocument printDocument;
        private IPrintDocumentSource printDocumentSource;
        string fileName;
        double marginWidth = 0;
 
        double marginHeight = 0;
     private Canvas pdfDocumentPanel = new Canvas();
 
        internal Dictionary<int, UIElement> printPreviewPages = new Dictionary<int, UIElement>();
        private List<string> imagePaths = new List<string>();
        IRandomAccessStream randomStream;
        public async void Print(Stream inputStream, string fileName)
        {
            inputStream.Position = 0;
            MemoryStream ms = new MemoryStream();
            //Copy the input stream to a new MemoryStream
            inputStream.CopyTo(ms);
            ms.Position = 0;
            //Convert the MemoryStream to a stream that allows random access
            randomStream = await ConvertToRandomAccessStream(ms);
            IAsyncOperation<global::Windows.Data.Pdf.PdfDocument> result = null;
            //Create the IAsyncOperation object from the given random stream
            result = global::Windows.Data.Pdf.PdfDocument.LoadFromStreamAsync(randomStream);
 
            result.AsTask().Wait();
            //Get the PdfDocument instance that represents the PDF document that is loaded
            pdfDocument = result.GetResults();
            result = null;
            pageCount = (int)pdfDocument.PageCount;
            fileName = fileName;
            await IncludeCanvas();
            try
            {
                UIDispatcher.Execute(async () =>
                {
                    RegisterForPrint();
                    //Show the UI window with printing options
                    await PrintManager.ShowPrintUIAsync();
                });
            }
            catch
            {
                UIDispatcher.Execute(async () =>
                {
                    RegisterForPrint();
                    //Show the UI window with printing options
                    PrintManager.ShowPrintUIAsync();
                });
            }
        }
 
        //Method to convert the given MemoryStream to a stream that allows random access.
        public async Task<IRandomAccessStream> ConvertToRandomAccessStream(MemoryStream memoryStream)
        {
            var randomAccessStream = new InMemoryRandomAccessStream();
            MemoryStream contentStream = new MemoryStream();
            memoryStream.CopyTo(contentStream);
            using (var outputStream = randomAccessStream.GetOutputStreamAt(0))
            {
                using (var dw = new DataWriter(outputStream))
                {
                    var task = new Task(() => dw.WriteBytes(contentStream.ToArray()));
                    task.Start();
 
                    await task;
                    await dw.StoreAsync();
 
                    await outputStream.FlushAsync();
                    await dw.FlushAsync();
                    outputStream.Dispose();
                    dw.DetachStream();
                    dw.Dispose();
                }
            }
            return randomAccessStream;
        }
        PrintManager printMan;
        private void RegisterForPrint()
        {
            printDocument = new PrintDocument();
 
            // Save the DocumentSource.
            printDocumentSource = printDocument.DocumentSource;
            // Add an event handler which creates preview pages.
            printDocument.Paginate += CreatePrintPreviewPages;
 
            // Add an event handler which provides a specified preview page.
            printDocument.GetPreviewPage += GetPrintPreviewPage;
 
            // Add an event handler which provides all final print pages.
            printDocument.AddPages += AddPrintPages;
 
            // Create a PrintManager and add a handler for printing initialization.
            printMan = PrintManager.GetForCurrentView();
            printMan.PrintTaskRequested += PrintTaskRequested;
        }
        
        Image imageCtrl = new Image();
        private async void AddPrintPages(object sender, AddPagesEventArgs e)
        {
            try
            {
                await PrepareForPrint(0, pageCount);
                PrintDocument printDoc = (PrintDocument)sender;
                printDoc.AddPagesComplete();
            }
            catch
            {
                PrintDocument printDoc = (PrintDocument)sender;
                printDoc.InvalidatePreview();
            }
        }
        private async Task<int> PrepareForPrint(int startIndex, int count)
        {
            StorageFolder tempFolder = ApplicationData.Current.TemporaryFolder;
            int result = await PrepareForPrint(startIndex, count, tempFolder);
            tempFolder = null;
            return result;
        }
        private async Task<int> PrepareForPrint(int p, int count, StorageFolder tempfolder)
        {
            for (int i = p; i < count; i++)
            {
                float zoomfactor = 1;
                //Adjust the zoom factor according to the display properties
                double customZoomFactor = zoomfactor * 96 / DisplayProperties.LogicalDpi;                
                ApplicationLanguages.PrimaryLanguageOverride = CultureInfo.InvariantCulture.TwoLetterISOLanguageName;
                //Get the page from the PDF document with a given index
                var pdfPage = pdfDocument.GetPage(uint.Parse(i.ToString()));
                double pdfPagePreferredZoom = pdfPage.PreferredZoom /** m_pdfViewer.PrinterSettings.QualityFactor*/;
                IRandomAccessStream randomStream = new InMemoryRandomAccessStream();
                global::Windows.Data.Pdf.PdfPageRenderOptions pdfPageRenderOptions = new global::Windows.Data.Pdf.PdfPageRenderOptions();
                Size pdfPageSize = pdfPage.Size;
                //Set the height to which the page is to be printed
                pdfPageRenderOptions.DestinationHeight = (uint)(pdfPageSize.Height * pdfPagePreferredZoom);
                //Set the width to which the page is to be printed
                pdfPageRenderOptions.DestinationWidth = (uint)(pdfPageSize.Width * pdfPagePreferredZoom);
                await pdfPage.RenderToStreamAsync(randomStream, pdfPageRenderOptions);
                //Create a new Image to which the page will be rendered
                imageCtrl = new Image();
                BitmapImage src = new BitmapImage();
                randomStream.Seek(0);
                //Obtain image source from the randomstream
                src.SetSource(randomStream);
                //set the image source to the image
                imageCtrl.Source = src;
                var DisplayInformation = Windows.Graphics.Display.DisplayInformation.GetForCurrentView();
 
                var dpi = DisplayInformation.LogicalDpi/96;
                imageCtrl.Height = src.PixelHeight/dpi;
                imageCtrl.Width = src.PixelWidth/dpi;
                randomStream.Dispose();
                pdfPage.Dispose();
                printDocument.AddPage(imageCtrl);
            }
            return 0;
        }
       private void CreatePrintPreviewPages(object sender, PaginateEventArgs e)
        {
            PrintTaskOptions printingOptions = ((PrintTaskOptions)e.PrintTaskOptions);
            PrintPageDescription pageDescription = printingOptions.GetPageDescription((uint)e.CurrentPreviewPageNumber);
            marginWidth = pageDescription.PageSize.Width;
            marginHeight = pageDescription.PageSize.Height;
            AddOnePrintPreviewPage();
 
            PrintDocument printDoc = (PrintDocument)sender;
            printDoc.SetPreviewPageCount(pageCount, PreviewPageCountType.Final);
        }
        private void AddOnePrintPreviewPage()
        {
            for (int i = pdfDocumentPanel.Children.Count - 1; i >= 0; i--)
            {
                Canvas print = pdfDocumentPanel.Children[i] as Canvas;
                if (print != null)
                {
                    print.Width = marginWidth;
                    print.Height = marginHeight;
                    printPreviewPages.Add(i, print);
 
                }
            }
        }
 
        private async void GetPrintPreviewPage(object sender, GetPreviewPageEventArgs e)
        {
            PrintDocument printDoc = (PrintDocument)sender;
            pdfDocumentPanel.Children.Remove(printPreviewPages[e.PageNumber - 1]);
            printDoc.SetPreviewPage(e.PageNumber, printPreviewPages[e.PageNumber - 1]);
        }
 
        private async Task<int> IncludeCanvas()
        {
            for (int i = 0; i < pageCount; i++)
            {
                int pageIndex = i;
                var pdfPage = pdfDocument.GetPage(uint.Parse(i.ToString()));
                double width = pdfPage.Size.Width;
                double height = pdfPage.Size.Height;
                Canvas page = new Canvas();
                page.Width = width;
                page.Height = height;
                page.VerticalAlignment = global::Windows.UI.Xaml.VerticalAlignment.Top;
                page.HorizontalAlignment = global::Windows.UI.Xaml.HorizontalAlignment.Center;
                page.Background = new Windows.UI.Xaml.Media.SolidColorBrush(global::Windows.UI.Color.FromArgb(255, 255, 255, 255));
                page.Margin = new Thickness(0, 0, 0, 0);
 
                double pdfPagePreferredZoom = pdfPage.PreferredZoom /** m_pdfViewer.PrinterSettings.QualityFactor*/;
                IRandomAccessStream randomStream = new InMemoryRandomAccessStream();
                global::Windows.Data.Pdf.PdfPageRenderOptions pdfPageRenderOptions = new global::Windows.Data.Pdf.PdfPageRenderOptions();
                Size pdfPageSize = pdfPage.Size;
                //Set the height to which the page is to be printed
                pdfPageRenderOptions.DestinationHeight = (uint)(pdfPageSize.Height * pdfPagePreferredZoom);
                //Set the width to which the page is to be printed
                pdfPageRenderOptions.DestinationWidth = (uint)(pdfPageSize.Width * pdfPagePreferredZoom);
                await pdfPage.RenderToStreamAsync(randomStream, pdfPageRenderOptions);
                //Create a new Image to which the page will be rendered
                imageCtrl = new Image();
                BitmapImage src = new BitmapImage();
                randomStream.Seek(0);
                //Obtain image source from the randomstream
                src.SetSource(randomStream);
                //set the image source to the image
                imageCtrl.Source = src;
                var DisplayInformation = Windows.Graphics.Display.DisplayInformation.GetForCurrentView();
 
                var dpi = DisplayInformation.LogicalDpi / 96;
                imageCtrl.Height = src.PixelHeight / dpi;
                imageCtrl.Width = src.PixelWidth / dpi;
                randomStream.Dispose();
                pdfPage.Dispose();
 
                page.Children.Add(imageCtrl);
                pdfDocumentPanel.Children.Add(page);
            }
            return 0;
        }
        PrintTask printTask;
        MessageDialog msgDialog;
 
        private async void PrintTaskRequested(PrintManager sender, PrintTaskRequestedEventArgs e)
        {
 
            printTask = e.Request.CreatePrintTask(fileName, sourceRequested => sourceRequested.SetSource(printDocumentSource));
 
                printTask.Completed += printTask_Completed;
            
        }
 
     
        //Called when the printing operation completes
        private void printTask_Completed(PrintTask sender, PrintTaskCompletedEventArgs args)
        {
            printTask.Completed -= printTask_Completed;
            printMan.PrintTaskRequested -= PrintTaskRequested;
 
 
            UIDispatcher.Execute(async () =>
            {
 
                
                msgDialog = new MessageDialog("Printing operation has been completed");
                await msgDialog.ShowAsync();                
 
            });
        }  
    }
 
    //Helper class to run operations async
    internal class UIDispatcher
    {
        private static CoreDispatcher Dispatcher = CoreApplication.MainView.CoreWindow.Dispatcher;
        /// <summary>
        /// Executes the action using UIElement.
        /// </summary>
        /// <param name="action">An Action.</param>
        internal static void Execute(Action action)
        {
            if (CoreApplication.MainView.CoreWindow == null
                || Dispatcher.HasThreadAccess)
                action();
            else
                Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => action()).AsTask().Wait();
        }
    }
}
 

 

Sample link:

https://www.syncfusion.com/downloads/support/directtrac/general/ze/PDFPrintingSample1519956005.zip

2X faster development

The ultimate Xamarin UI toolkit to boost your development speed.
ADD COMMENT
You must log in to leave a comment
Comments
Bharathi
Mar 13, 2019

hi, for ios it is fine.but coming to android ,at the time of calling dependency services ,i got null reference error.can u please help me out from this.

Reply
Sathish Sivakumar [Syncfusion]
Mar 13, 2019

Hi Bharathi,

We can able to print the PDF documents properly with the sample available in this KB. Kindly provide the following details to analyze more on your issue.

  • Simple sample
  • Android device details
  • PDF document with which the issue could be reproduced.
Regards,
Sathish
Bharathi
Mar 15, 2019

Hi , i didnt register the dedepnacy service.so that is the reason for my error.now running properly with out faceing any errors.

i found the printer device name in my mobile(using above your printer code).after choosing printer asked enter the password which gives printer device.later in printer device shows as "connected".but print is not coming (for android).

could you please point to me right direction to print the pdf file.

and in ios ,even if i connected same networks ,it is showing "no airprint printers found".


Thanks

Bharathi.


Reply
Gayathri Ramalingam [Syncfusion]
Mar 20, 2019

Hi Bharathi,

Can you please share the following details to analyze more on the issue?

  1. Are you printing the PDF document in physical printer (not an option print to PDF)
  2. Can you please confirm if you are printing the PDF document through blue tooth or WiFi connectivity

These details will be helpful for us to analyze more on your and assist you with better solution.

Regards, Sathish

Dmitriy Reznik
Mar 25, 2019

Thank you for the solution. I used it for UWP. I can print documents successfully, but the preview never ends loading. Could you please help?

Reply
Sathish Sivakumar [Syncfusion]
Apr 04, 2019

Hi Dmitriy,

We have modified the code changes to resolve the reported issue. Please try the sample refreshed in the KB and let us know if you still facing the same issue.

Regards, Sathish

Bharathi
May 17, 2019

Hi,

I am trying to print the pdf document in physical device via wifi using the above mentioned code. Here when i run the code,my device is detected in printer as well as in my phone also got printer name.once selected the printer,it is asking password which is generated by printer.after entering password , in printer i found that is "connected". but pdf file is not printed.

Please help me out.i have been trying from long time.

Thanks Bharathi.

Reply
Sathish Sivakumar [Syncfusion]
May 20, 2019

Hi Bharathi,

Printing the PDF document doesn’t depend on SfPdfViewerControl, we need to contact the Xamarin forum members to check your issue and get the solution. Please raise your question in the below forum to get the solution.

https://forums.xamarin.com/categories/xamarin-forms

Regards, Sathish

white wabbit
May 30, 2019

If I print on Android, it will say "Failed to change the settings. Try again." and on the notification of the device, it says "Print services not enable.".. How to fix this? Please help. Thanks!

Reply
Sathish Sivakumar [Syncfusion]
Jun 03, 2019

Hi White,

Printing the PDF document doesn’t depend on SfPdfViewerControl, we need to contact the Xamarin forum members to check your issue and get the solution. Please raise your question in the below forum to get the solution.

https://forums.xamarin.com/categories/xamarin-forms

Regards, Sathish

Please sign in to access our KB

This page will automatically be redirected to the sign-in page in 10 seconds.

Up arrow icon

Warning Icon You are using an outdated version of Internet Explorer that may not display all features of this and other websites. Upgrade to Internet Explorer 8 or newer for a better experience.Close Icon

Live Chat Icon For mobile
Live Chat Icon