Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Direct print implementation #37

Closed
TristanPct opened this issue Feb 21, 2019 · 17 comments
Closed

Direct print implementation #37

TristanPct opened this issue Feb 21, 2019 · 17 comments
Labels
enhancement New feature or request

Comments

@TristanPct
Copy link

I'm currently developing an iOS Flutter app who need background printing.
I look at this plugin and starting a fork to implement the iOS UIPrintInteractionController printToPrinter method allowing to print without showing the native UI.

I simply made a copy of printPdf method (in PrintingPlugin.m) and replacing

[controller presentAnimated:YES completionHandler:completionHandler];

with

NSURL* printerURL = [NSURL URLWithString:printerID];
UIPrinter* printer = [UIPrinter printerWithURL:printerURL];

[controller printToPrinter:printer completionHandler:completionHandler];

Having printerID a NSString passed as parameter.

But when I call this method, a popup show up saying:

Printing to "my-printer.local."
Contacting printer...

And the popups "Cancel" button doesn't work...

Anyone seeing what's happens?

Here is my fork with PrintingPlugin.m and printing/example modified: https://github.com/TristanPct/dart_pdf

Here is the StackOverflow issue referencing the same issue: https://stackoverflow.com/questions/54810047/ios-uiprintinteractioncontroller-printtoprinter-contacting-printer

@DavBfr
Copy link
Owner

DavBfr commented Feb 22, 2019

If you end up with something, I'd be happy to integrate it into this plugin.

@DavBfr DavBfr added the enhancement New feature or request label Feb 27, 2019
@DavBfr
Copy link
Owner

DavBfr commented Mar 1, 2019

@TristanPct Could you make something that works?

@TristanPct
Copy link
Author

TristanPct commented Mar 1, 2019

Hi, I'm still investigating on this.
I'm currently looking at that Cordova plugin which implements this functionality (and make it works) to find some answers: https://github.com/katzer/cordova-plugin-printer

EDIT: replacing renderer = [[PdfPrintPageRenderer alloc] init:channel]; with UIPrintPageRenderer* renderer = [[UIPrintPageRenderer alloc] init]; make the print order complete but with a blank page instead of the PDF.

@DavBfr
Copy link
Owner

DavBfr commented Mar 3, 2019

The iOS code is now full Swift.

@TristanPct
Copy link
Author

I saw it recently, I rebase my fork to continue with the Swift version, but the issue is still there for the moment...

@TristanPct
Copy link
Author

Problem seems to come from:

channel?.invokeMethod("onLayout", arguments: arg)

On a normal print (with print preview) invokeMethod is called and trigger the Dart onLayout callback, but using the direct print invokeMethod is called but the Dart callback is never triggered...
(And lock?.unlock() is not called so the UI stays frozen.)

A breakpoint here is never hit with direct print:

switch (call.method) {

Have you an idea why in this use case the invokeMethod doesn't trigger the Dart callback ?

@DavBfr
Copy link
Owner

DavBfr commented Mar 5, 2019

It is because controller.print does not spawn a new thread and you are stuck in a deadlock.

The best would be to:

  1. get the paper size and margins from the UIPrinter,
  2. start a new thread to wait the onWrite finishes (lock.lock())
  3. call onLayout
  4. call controller.print(..)

If we can also have a list of printers on the dart side, that would be better instead of relying on iOS default interface, but that's the second part.

Then we need the same for Android ;)

@TristanPct
Copy link
Author

I'm not very comfortable with Swift (first time using it, same with Objective-C), I don't fully understand the thread system here...

On the code, onLayout is called by the renderer which is called by controller.print(), do we have to change call order?

I've not look yet for a Dart side list of printers, I don't know if you can get printer without using native UI.

For Android a native printer picker UI exist but apparently no native way to make a background print...

@DavBfr
Copy link
Owner

DavBfr commented Mar 5, 2019

I'm not the most experienced iOS developer too.
I think the order must be a little different: We might need the full page rendered before calling the controller.print() method. And as we control every aspect before that, it's fine.
With the dialog print, the OS calls the rendering in a separated thread, that's why I have some locks to synchronize and simulate an event system like on Android.

@TristanPct
Copy link
Author

UIPrinter doesn't give information about paper size and margin.
I tried to get renderer.paperRect to give it to onLayout before calling controller.print but size and margins are set to 0 at this point.

I tried all combinations of lock?.lock() around onLayout invocation, the Dart code is fully executed (contrary to what I said before), but when the Dart code run await _channel.invokeMethod('writePdf', params); the Swift writePdf method is not called (with and without lock around invoke).

For what I understood, a first lock is needed before onLayout invocation, to make invocation thread safe, then a second lock is needed to wait for writePdf invocation, this one is unlock in renderer.setDocument() and then an another unlock for the first lock.

Also, controller.print() trigger renderer.numberOfPages which call onLayout too.

@DavBfr
Copy link
Owner

DavBfr commented Mar 5, 2019

Yes, it was quite tricky to make it work correctly with the print dialog. The Android version is much more simple.

@joeblew99
Copy link

i am working on Windows and Mac versions, so a NON Native Print Window is really helpful.

Will let you knwo when i get somewhere with it.
Yell if you are interested...

@DavBfr
Copy link
Owner

DavBfr commented Apr 17, 2019

NON-Native Print Window seems to be impossible with Android, and Apple messed-up the threading model on iOS and it is hard to say if it will be possible.
So you can implement some new functions in the Printing class for your Desktop version.

By the way, AHHHHHHHHH 😱!!!!

@joeblew99
Copy link

no worries :)

I ended up using the Native PDF Viewer for now on desktop. Life is too short !

What about this as a quick and dirty one for now...
Convert the PDF to a Bitmap and display it in a Flutter View. If the Bitmap is 2 to 3 times larger than the screen size it will still be sort of OK for previewing and then printing.

@DavBfr
Copy link
Owner

DavBfr commented Sep 21, 2019

Implemented in Printing version 2.1.7

@DavBfr DavBfr closed this as completed Sep 21, 2019
@KevinBeckers
Copy link

Is there a way to hide the Printing to "my-printer.local." and Contacting printer... popups on iOS?

@DavBfr
Copy link
Owner

DavBfr commented Nov 27, 2019

I don't think it's possible. This is part of iOS, not the plugin.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

4 participants