baskren / Forms9Patch

Simplify image management and text formatting in your Xamarin.Forms apps
http://Forms9Patch.com
Other
127 stars 33 forks source link

ToPdfAsync on Android returns blank pdf for Android Q [API 29] #89

Closed mistryhardik closed 3 years ago

mistryhardik commented 3 years ago

Description

Steps to Reproduce

  1. Add reference to latest or any other version of the Forms9Patch nuget package to a Xamarin Forms app [Shared and the platform specific projects] OR create a new Xamarin project and add reference to the latest or any other version of the Forms9Patch nuget package
  2. Implement a Webview and handle to create PDF on button click or any other event.
  3. Load WebView with an HTML string or download from an Uri
  4. Ensure the target framework for Android project is Android Q [API 29]
  5. Run the app and click the button to generate the pdf.

Expected Behavior

Return a pdf file with content inside

Actual Behavior

The pdf file has no content [NOTE: The file does get created]

Basic Information

Thank you for an awesome library @baskren. We cannot see why the same code will not work for API 29. Did you see a similar issue with your apps and/or from other community members?

I will love to collaborate and try to mitigate this.

I spent time during the weekend to get the master branch and see what can I do to handle this, but not sure if I am doing anything right as the behavior is still the same.

Please share if you have any thoughts around this.

touhidul-udoy commented 3 years ago

I'm also facing the same error for API 29, emulator and real device

wagenheimer commented 3 years ago

I'm also facing the same error for API 29, emulator and real device!

wagenheimer commented 3 years ago

In my case, I'm not 100% sure, but it seems that the problem was with the sharing routine and not with the pdf creation itself.

  if (Forms9Patch.ToPdfService.IsAvailable)
            {
                if (await myWebView.ToPdfAsync("Celmi", Forms9Patch.PageSize.IsoA4) is ToFileResult pdfResult)
                {
                    if (pdfResult.IsError)
                        using (Toast.Create("PDF Failure", pdfResult.Result))
                        {
                        }
                    else
                    {
                        var collection = new Forms9Patch.MimeItemCollection();
                        collection.AddBytesFromFile("application/pdf", pdfResult.Result);
                        Forms9Patch.Sharing.Share(collection, RelatorioView.instance.PrintButton);
                    }
                }
            }

To make it work, I added this to my manifest : android:requestLegacyExternalStorage="true" (I'm not sure this is really necessary)

And changed my code to:

       if (await myWebView.ToPdfAsync("Celmi", Forms9Patch.PageSize.IsoA4) is ToFileResult pdfResult)
            {
                if (pdfResult.IsError)
                    using (Toast.Create("PDF Failure", pdfResult.Result))
                    {
                    }
                else
                {
                    await Share.RequestAsync(new ShareFileRequest
                    {
                        File = new ShareFile(pdfResult.Result),
                        PresentationSourceBounds = new Rectangle(0, 0, 1, 1) // Fixes iPad share option
                    });
                }
            }

Now it works!

wagenheimer commented 3 years ago

I had several problems, both using "HTML to a PDF" and "HTML to PNG".

I came to the conclusion that PDF / PNG is being generated BEFORE HTML finishes rendering. I had several problems, tested it in different ways, and sometimes it worked, sometimes not. On iOS, it even got stuck on Spinning when generating the PDF.

To definitely resolve the problem, I displayed the HTML in a WebView first, and then on that screen, I added a button to export to PNG or PDF. Since WebView already displayed HTML before generating PDF / PNG, it now worked 100% of the time on both iOS and Android.

baskren commented 3 years ago

This is a bit more difficult problem than I have ever hoped. In the UNO version of this functionality, I have most of these issues resolved but there is a little more work left. Once I complete some related work in UNO, I'll be able to update the Xamarin implementation.

mistryhardik commented 3 years ago

We have moved to an alternative approach instead of generating a pdf. I will mark it close for now and try with a new package version when it is available. Thank you.

Mourad57 commented 3 years ago

Hello @mistryhardik ,

Any chance to get infos about this alternative approach ?

Thanks

UnreachableCode commented 1 year ago

Has this issue been fixed in the develop branch? It's still in the 2.4.9 release

UnreachableCode commented 1 year ago

Using wagenheimer's advice, I've opted for a custom event for when the source of both the iOS and Android WebView renderer is fully loaded before any button to create a PDF is enabled.

I did this using this answer here https://stackoverflow.com/a/67528473/812013 for iOS. And I built on this approach in Android using this code here https://github.com/seansparkman/CookiesWebView/blob/master/Cookies.Android/CookieWebViewRenderer.cs#L45.