Showing
6 changed files
with
72 additions
and
8 deletions
| @@ -30,6 +30,8 @@ import android.print.PdfConvert; | @@ -30,6 +30,8 @@ import android.print.PdfConvert; | ||
| 30 | import android.print.PrintAttributes; | 30 | import android.print.PrintAttributes; |
| 31 | import android.print.PrintDocumentAdapter; | 31 | import android.print.PrintDocumentAdapter; |
| 32 | import android.print.PrintDocumentInfo; | 32 | import android.print.PrintDocumentInfo; |
| 33 | +import android.print.PrintJob; | ||
| 34 | +import android.print.PrintJobInfo; | ||
| 33 | import android.print.PrintManager; | 35 | import android.print.PrintManager; |
| 34 | import android.print.pdf.PrintedPdfDocument; | 36 | import android.print.pdf.PrintedPdfDocument; |
| 35 | import android.webkit.WebView; | 37 | import android.webkit.WebView; |
| @@ -56,6 +58,7 @@ public class PrintingPlugin extends PrintDocumentAdapter implements MethodCallHa | @@ -56,6 +58,7 @@ public class PrintingPlugin extends PrintDocumentAdapter implements MethodCallHa | ||
| 56 | private final Activity activity; | 58 | private final Activity activity; |
| 57 | private final MethodChannel channel; | 59 | private final MethodChannel channel; |
| 58 | private PrintedPdfDocument mPdfDocument; | 60 | private PrintedPdfDocument mPdfDocument; |
| 61 | + private PrintJob printJob; | ||
| 59 | private byte[] documentData; | 62 | private byte[] documentData; |
| 60 | private String jobName; | 63 | private String jobName; |
| 61 | private LayoutResultCallback callback; | 64 | private LayoutResultCallback callback; |
| @@ -126,7 +129,33 @@ public class PrintingPlugin extends PrintDocumentAdapter implements MethodCallHa | @@ -126,7 +129,33 @@ public class PrintingPlugin extends PrintDocumentAdapter implements MethodCallHa | ||
| 126 | 129 | ||
| 127 | @Override | 130 | @Override |
| 128 | public void onFinish() { | 131 | public void onFinish() { |
| 129 | - // noinspection ResultOfMethodCallIgnored | 132 | + try { |
| 133 | + while (true) { | ||
| 134 | + int state = printJob.getInfo().getState(); | ||
| 135 | + | ||
| 136 | + if (state == PrintJobInfo.STATE_COMPLETED) { | ||
| 137 | + HashMap<String, Object> args = new HashMap<>(); | ||
| 138 | + args.put("completed", true); | ||
| 139 | + channel.invokeMethod("onCompleted", args); | ||
| 140 | + break; | ||
| 141 | + } else if (state == PrintJobInfo.STATE_CANCELED) { | ||
| 142 | + HashMap<String, Object> args = new HashMap<>(); | ||
| 143 | + args.put("completed", false); | ||
| 144 | + channel.invokeMethod("onCompleted", args); | ||
| 145 | + break; | ||
| 146 | + } | ||
| 147 | + | ||
| 148 | + Thread.sleep(200); | ||
| 149 | + } | ||
| 150 | + } catch (Exception e) { | ||
| 151 | + HashMap<String, Object> args = new HashMap<>(); | ||
| 152 | + args.put("completed", printJob.isCompleted()); | ||
| 153 | + args.put("error", e.getMessage()); | ||
| 154 | + channel.invokeMethod("onCompleted", args); | ||
| 155 | + } | ||
| 156 | + | ||
| 157 | + printJob = null; | ||
| 158 | + mPdfDocument = null; | ||
| 130 | } | 159 | } |
| 131 | 160 | ||
| 132 | @Override | 161 | @Override |
| @@ -136,7 +165,7 @@ public class PrintingPlugin extends PrintDocumentAdapter implements MethodCallHa | @@ -136,7 +165,7 @@ public class PrintingPlugin extends PrintDocumentAdapter implements MethodCallHa | ||
| 136 | jobName = | 165 | jobName = |
| 137 | call.argument("name") == null ? "Document" : (String) call.argument("name"); | 166 | call.argument("name") == null ? "Document" : (String) call.argument("name"); |
| 138 | assert jobName != null; | 167 | assert jobName != null; |
| 139 | - printManager.print(jobName, this, null); | 168 | + printJob = printManager.print(jobName, this, null); |
| 140 | result.success(0); | 169 | result.success(0); |
| 141 | break; | 170 | break; |
| 142 | case "writePdf": | 171 | case "writePdf": |
| @@ -30,9 +30,11 @@ class MyAppState extends State<MyApp> { | @@ -30,9 +30,11 @@ class MyAppState extends State<MyApp> { | ||
| 30 | 30 | ||
| 31 | Future<void> _printPdf() async { | 31 | Future<void> _printPdf() async { |
| 32 | print('Print ...'); | 32 | print('Print ...'); |
| 33 | - await Printing.layoutPdf( | 33 | + final bool result = await Printing.layoutPdf( |
| 34 | onLayout: (PdfPageFormat format) async => | 34 | onLayout: (PdfPageFormat format) async => |
| 35 | (await generateDocument(format)).save()); | 35 | (await generateDocument(format)).save()); |
| 36 | + | ||
| 37 | + print('Document printed: $result'); | ||
| 36 | } | 38 | } |
| 37 | 39 | ||
| 38 | Future<void> _saveAsFile() async { | 40 | Future<void> _saveAsFile() async { |
| @@ -87,13 +87,24 @@ public class SwiftPrintingPlugin: NSObject, FlutterPlugin, UIPrintInteractionCon | @@ -87,13 +87,24 @@ public class SwiftPrintingPlugin: NSObject, FlutterPlugin, UIPrintInteractionCon | ||
| 87 | if !completed, error != nil { | 87 | if !completed, error != nil { |
| 88 | print("Unable to print: \(error?.localizedDescription ?? "unknown error")") | 88 | print("Unable to print: \(error?.localizedDescription ?? "unknown error")") |
| 89 | } | 89 | } |
| 90 | + | ||
| 91 | + let data: NSDictionary = [ | ||
| 92 | + "completed": completed, | ||
| 93 | + "error": error?.localizedDescription as Any, | ||
| 94 | + ] | ||
| 95 | + channel?.invokeMethod("onCompleted", arguments: data) | ||
| 96 | + | ||
| 90 | renderer = nil | 97 | renderer = nil |
| 91 | } | 98 | } |
| 92 | 99 | ||
| 93 | func printPdf(_ name: String) { | 100 | func printPdf(_ name: String) { |
| 94 | let printing = UIPrintInteractionController.isPrintingAvailable | 101 | let printing = UIPrintInteractionController.isPrintingAvailable |
| 95 | if !printing { | 102 | if !printing { |
| 96 | - print("printing not available") | 103 | + let data: NSDictionary = [ |
| 104 | + "completed": false, | ||
| 105 | + "error": "Printing not available", | ||
| 106 | + ] | ||
| 107 | + channel?.invokeMethod("onCompleted", arguments: data) | ||
| 97 | return | 108 | return |
| 98 | } | 109 | } |
| 99 | 110 |
| @@ -22,6 +22,7 @@ mixin Printing { | @@ -22,6 +22,7 @@ mixin Printing { | ||
| 22 | static const MethodChannel _channel = MethodChannel('printing'); | 22 | static const MethodChannel _channel = MethodChannel('printing'); |
| 23 | static LayoutCallback _onLayout; | 23 | static LayoutCallback _onLayout; |
| 24 | static Completer<List<int>> _onHtmlRendered; | 24 | static Completer<List<int>> _onHtmlRendered; |
| 25 | + static Completer<bool> _onCompleted; | ||
| 25 | 26 | ||
| 26 | static Future<void> _handleMethod(MethodCall call) async { | 27 | static Future<void> _handleMethod(MethodCall call) async { |
| 27 | switch (call.method) { | 28 | switch (call.method) { |
| @@ -38,6 +39,15 @@ mixin Printing { | @@ -38,6 +39,15 @@ mixin Printing { | ||
| 38 | 'doc': Uint8List.fromList(bytes), | 39 | 'doc': Uint8List.fromList(bytes), |
| 39 | }; | 40 | }; |
| 40 | return await _channel.invokeMethod('writePdf', params); | 41 | return await _channel.invokeMethod('writePdf', params); |
| 42 | + case 'onCompleted': | ||
| 43 | + final bool completed = call.arguments['completed']; | ||
| 44 | + final String error = call.arguments['error']; | ||
| 45 | + if (completed == false && error != null) { | ||
| 46 | + _onCompleted.completeError(error); | ||
| 47 | + } else { | ||
| 48 | + _onCompleted.complete(completed); | ||
| 49 | + } | ||
| 50 | + break; | ||
| 41 | case 'onHtmlRendered': | 51 | case 'onHtmlRendered': |
| 42 | _onHtmlRendered.complete(call.arguments); | 52 | _onHtmlRendered.complete(call.arguments); |
| 43 | break; | 53 | break; |
| @@ -50,12 +60,20 @@ mixin Printing { | @@ -50,12 +60,20 @@ mixin Printing { | ||
| 50 | /// Prints a Pdf document to a local printer using the platform UI | 60 | /// Prints a Pdf document to a local printer using the platform UI |
| 51 | /// the Pdf document is re-built in a [LayoutCallback] each time the | 61 | /// the Pdf document is re-built in a [LayoutCallback] each time the |
| 52 | /// user changes a setting like the page format or orientation. | 62 | /// user changes a setting like the page format or orientation. |
| 53 | - static Future<void> layoutPdf( | ||
| 54 | - {@required LayoutCallback onLayout, String name = 'Document'}) async { | 63 | + /// |
| 64 | + /// returns a future with a `bool` set to true if the document is printed | ||
| 65 | + /// and false if it is canceled. | ||
| 66 | + /// throws an exception in case of error | ||
| 67 | + static Future<bool> layoutPdf({ | ||
| 68 | + @required LayoutCallback onLayout, | ||
| 69 | + String name = 'Document', | ||
| 70 | + }) async { | ||
| 71 | + _onCompleted = Completer<bool>(); | ||
| 55 | _onLayout = onLayout; | 72 | _onLayout = onLayout; |
| 56 | _channel.setMethodCallHandler(_handleMethod); | 73 | _channel.setMethodCallHandler(_handleMethod); |
| 57 | final Map<String, dynamic> params = <String, dynamic>{'name': name}; | 74 | final Map<String, dynamic> params = <String, dynamic>{'name': name}; |
| 58 | - return await _channel.invokeMethod('printPdf', params); | 75 | + await _channel.invokeMethod<int>('printPdf', params); |
| 76 | + return _onCompleted.future; | ||
| 59 | } | 77 | } |
| 60 | 78 | ||
| 61 | /// Prints a [PdfDocument] or a pdf stream to a local printer using the platform UI | 79 | /// Prints a [PdfDocument] or a pdf stream to a local printer using the platform UI |
| @@ -4,7 +4,7 @@ description: Plugin that allows Flutter apps to generate and print documents to | @@ -4,7 +4,7 @@ description: Plugin that allows Flutter apps to generate and print documents to | ||
| 4 | homepage: https://github.com/DavBfr/dart_pdf/tree/master/printing | 4 | homepage: https://github.com/DavBfr/dart_pdf/tree/master/printing |
| 5 | repository: https://github.com/DavBfr/dart_pdf | 5 | repository: https://github.com/DavBfr/dart_pdf |
| 6 | issue_tracker: https://github.com/DavBfr/dart_pdf/issues | 6 | issue_tracker: https://github.com/DavBfr/dart_pdf/issues |
| 7 | -version: 2.1.4 | 7 | +version: 2.1.5 |
| 8 | 8 | ||
| 9 | environment: | 9 | environment: |
| 10 | sdk: ">=2.1.0 <3.0.0" | 10 | sdk: ">=2.1.0 <3.0.0" |
-
Please register or login to post a comment