From b74d9f1825dd43a040c408fa89dbe8ea121040e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Katzer?= Date: Sun, 15 Dec 2013 11:09:02 +0100 Subject: [PATCH 01/21] Add KitKat support - requires Android SDK 19 or higher --- README.md | 25 +-- plugin.xml | 5 +- src/android/KitKatPrinter.java | 142 ---------------- src/android/Printer.java | 293 ++++++--------------------------- www/printer.js | 12 +- 5 files changed, 52 insertions(+), 425 deletions(-) delete mode 100644 src/android/KitKatPrinter.java diff --git a/README.md b/README.md index b800d67..d2e5da5 100644 --- a/README.md +++ b/README.md @@ -9,11 +9,7 @@ by Sebastián Katzer ([github.com/katzer](https://github.com/katzer)) - **iOS** *(Print from iOS devices to AirPrint compatible printers)*
See [Drawing and Printing Guide for iOS](http://developer.apple.com/library/ios/documentation/2ddrawing/conceptual/drawingprintingios/Printing/Printing.html) for detailed informations and screenshots. -- **Android** *(Print through 3rd party printing apps on SDK <= 18)* - -## Dependencies -Cordova will check all dependencies and install them if they are missing. -- [org.apache.cordova.device](https://github.com/apache/cordova-plugin-device) *(since v0.5.0)* +- **Android** *(SDK 19)* ## Adding the Plugin to your project Through the [Command-line Interface](http://cordova.apache.org/docs/en/3.0.0/guide_cli_index.md.html#The%20Command-line%20Interface): @@ -29,7 +25,7 @@ cordova plugin rm de.appplant.cordova.plugin.printer ``` ## Release Notes -#### Version 0.5.0 (not yet released) +#### Version 0.5.0 (11.12.2013) - Release under the Apache 2.0 license. - [***change:***] Removed the `callback` property from the `print` interface. - [enhancement:] Added Android KitKat support
@@ -79,23 +75,6 @@ var page = document.body.innerHTML; window.plugin.printer.print(page); ``` -## Platform specifics - -### Get all available printing apps on Android <= 4.3 -The callback function will be called with a second argument which is an array, indicating which printer apps are available for printing. -```javascript -window.plugin.printer.isServiceAvailable( - function (isAvailable, installedAppIds) { - alert('The following print apps are installed on your device: ' + installedAppIds.join(', ')); - } -); -``` - -### Specify printing app on Android <= 4.3 -An App-ID can be assigned as a platform configuration to indicate which 3rd party printing app shall be used. Otherwise the first found application will be used. -```javascript -window.plugin.printer.print(page, { appId: 'epson.print' }); -``` ## Quirks diff --git a/plugin.xml b/plugin.xml index fbe0ca3..3200a63 100644 --- a/plugin.xml +++ b/plugin.xml @@ -9,7 +9,7 @@ A bunch of printig plugins for Cordova 3.x.x https://github.com/katzer/cordova-plugin-printer.git - print, printer, ios, android + print, printer, ios, android, kitkat Apache 2.0 Sebastián Katzer @@ -50,8 +50,7 @@ - - + diff --git a/src/android/KitKatPrinter.java b/src/android/KitKatPrinter.java deleted file mode 100644 index 75805d5..0000000 --- a/src/android/KitKatPrinter.java +++ /dev/null @@ -1,142 +0,0 @@ -/* - Copyright 2013 appPlant UG - - Licensed to the Apache Software Foundation (ASF) under one - or more contributor license agreements. See the NOTICE file - distributed with this work for additional information - regarding copyright ownership. The ASF licenses this file - to you under the Apache License, Version 2.0 (the - "License"); you may not use this file except in compliance - with the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, - software distributed under the License is distributed on an - "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - KIND, either express or implied. See the License for the - specific language governing permissions and limitations - under the License. -*/ - -package de.appplant.cordova.plugin.printer; - -import org.apache.cordova.CallbackContext; -import org.apache.cordova.CordovaPlugin; -import org.apache.cordova.PluginResult; - -import org.json.JSONArray; -import org.json.JSONException; - -import android.annotation.TargetApi; -import android.content.Context; -import android.os.Build; -import android.print.PrintAttributes; -import android.print.PrintDocumentAdapter; -import android.print.PrintManager; -import android.view.View; -import android.webkit.WebView; -import android.webkit.WebViewClient; - -@TargetApi(19) -public class KitKatPrinter extends CordovaPlugin { - - @Override - public boolean execute (String action, JSONArray args, CallbackContext callbackContext) throws JSONException { - // Es soll überprüft werden, ob ein Dienst zum Ausdrucken von Inhalten zur Verfügung steht - if (action.equalsIgnoreCase("isServiceAvailable")) { - isServiceAvailable(callbackContext); - - return true; - } - - // Etwas soll ausgedruckt werden - if (action.equalsIgnoreCase("print")) { - print(args, callbackContext); - - return true; - } - - // Returning false results in a "MethodNotFound" error. - return false; - } - - /** - * Überprüft, ob ein Drucker zur Verfügung steht. - */ - private void isServiceAvailable (CallbackContext ctx) { - Boolean supported = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT; - PluginResult result = new PluginResult(PluginResult.Status.OK, supported); - - ctx.sendPluginResult(result); - } - - /** - * Druckt den HTML Content aus. - */ - private void print (final JSONArray args, CallbackContext ctx) { - final KitKatPrinter self = this; - - cordova.getActivity().runOnUiThread( new Runnable() { - public void run() { - String content = args.optString(0, ""); - WebView controller = self.getPrintController(); - - self.loadContentIntoPrintController(content, controller); - - self.startPrinterApp(controller); - } - }); - } - - /** - * Erstellt den Print-View. - */ - private WebView getPrintController () { - WebView webview = new WebView(cordova.getActivity()); - - webview.setVisibility(View.INVISIBLE); - webview.getSettings().setJavaScriptEnabled(false); - - return webview; - } - - /** - * Lädt den zu druckenden Content in ein WebView, welcher vom Drucker ausgedruckt werden soll. - */ - private void loadContentIntoPrintController (String content, WebView webview) { - //Set base URI to the assets/www folder - String baseURL = webView.getUrl(); - baseURL = baseURL.substring(0, baseURL.lastIndexOf('/') + 1); - - webview.loadDataWithBaseURL(baseURL, content, "text/html", "UTF-8", null); - } - - /** - * Öffnet die Printer App, damit der Content ausgedruckt werden kann. - */ - private void startPrinterApp (WebView webview) { - webview.setWebViewClient (new WebViewClient() { - public boolean shouldOverrideUrlLoading (WebView view, String url) { - return false; - } - - public void onPageFinished (WebView webview, String url) { - // Get a PrintManager instance - PrintManager printManager = (PrintManager) cordova.getActivity() - .getSystemService(Context.PRINT_SERVICE); - - // Get a print adapter instance - PrintDocumentAdapter printAdapter = webView.createPrintDocumentAdapter(); - - // Get a print builder instance - PrintAttributes.Builder builder = new PrintAttributes.Builder(); - - builder.setMinMargins(PrintAttributes.Margins.NO_MARGINS); - - // Create a print job with name and adapter instance - printManager.print("Print Document", printAdapter, builder.build()); - } - }); - } -} diff --git a/src/android/Printer.java b/src/android/Printer.java index 7c6d1b4..15fae6a 100644 --- a/src/android/Printer.java +++ b/src/android/Printer.java @@ -21,81 +21,38 @@ package de.appplant.cordova.plugin.printer; -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; +import org.apache.cordova.CallbackContext; +import org.apache.cordova.CordovaPlugin; +import org.apache.cordova.PluginResult; import org.json.JSONArray; import org.json.JSONException; -import org.json.JSONObject; -import android.app.Activity; -import android.content.Intent; -import android.content.pm.PackageInfo; -import android.content.pm.PackageManager; -import android.graphics.Bitmap; -import android.graphics.Canvas; -import android.graphics.Picture; -import android.net.Uri; -import android.os.Handler; +import android.annotation.TargetApi; +import android.content.Context; +import android.os.Build; +import android.print.PrintAttributes; +import android.print.PrintDocumentAdapter; +import android.print.PrintManager; import android.view.View; -import android.view.ViewGroup; import android.webkit.WebView; import android.webkit.WebViewClient; -import org.apache.cordova.CordovaPlugin; -import org.apache.cordova.CallbackContext; -import org.apache.cordova.PluginResult; - +@TargetApi(19) public class Printer extends CordovaPlugin { - private CallbackContext ctx; - - /** - * Auflistung von App-IDs, welche den Content ausdrucken können - */ - private String printAppIds[] = { - "kr.co.iconlab.BasicPrintingProfile", // Bluetooth Smart Printing - "com.blueslib.android.app", // Bluetooth SPP Printer API - "com.brother.mfc.brprint", // Brother iPrint&Scan - "com.brother.ptouch.sdk", // Brother Print Library - "jp.co.canon.bsd.android.aepp.activity", // Canon Easy-PhotoPrint - "com.pauloslf.cloudprint", // Cloud Print - "com.dlnapr1.printer", // CMC DLNA Print Client - "com.dell.mobileprint", // Dell Mobile Print - "com.printjinni.app.print", // PrintJinni - "epson.print", // Epson iPrint - "jp.co.fujixerox.prt.PrintUtil.PCL", // Fuji Xerox Print Utility - "jp.co.fujixerox.prt.PrintUtil.Karin", // Fuji Xeros Print&Scan (S) - "com.hp.android.print", // HP ePrint" "com.hp.android.print - "com.blackspruce.lpd", // Let's Print Droid - "com.threebirds.notesprint", // NotesPrint print your notes - "com.xerox.mobileprint", // Print Portal (Xerox) - "com.zebra.kdu", // Print Station (Zebra) - "net.jsecurity.printbot", // PrintBot - "com.dynamixsoftware.printhand", // PrintHand Mobile Print - "com.dynamixsoftware.printhand.premium", // PrintHand Mobile Print Premium - "com.sec.print.mobileprint", // Samsung Mobile Print - "com.rcreations.send2printer", // Send 2 Printer - "com.ivc.starprint", // StarPrint - "com.threebirds.easyviewer", // WiFi Print - "com.woosim.android.print", // Woosim BT printer - "com.woosim.bt.app", // WoosimPrinter - "com.zebra.android.zebrautilities", // Zebra Utilities - }; - @Override public boolean execute (String action, JSONArray args, CallbackContext callbackContext) throws JSONException { - // Etwas soll ausgedruckt werden - if ("print".equals(action)) { - print(args, callbackContext); + // Es soll überprüft werden, ob ein Dienst zum Ausdrucken von Inhalten zur Verfügung steht + if (action.equalsIgnoreCase("isServiceAvailable")) { + isServiceAvailable(callbackContext); return true; } - // Es soll überprüft werden, ob ein Dienst zum Ausdrucken von Inhalten zur Verfügung steht - if ("isServiceAvailable".equals(action)) { - isServiceAvailable(callbackContext); + // Etwas soll ausgedruckt werden + if (action.equalsIgnoreCase("print")) { + print(args, callbackContext); return true; } @@ -108,9 +65,8 @@ public class Printer extends CordovaPlugin { * Überprüft, ob ein Drucker zur Verfügung steht. */ private void isServiceAvailable (CallbackContext ctx) { - JSONArray appIds = this.getInstalledAppIds(); - Boolean available = appIds.length() > 0; - PluginResult result = new PluginResult(PluginResult.Status.OK, available); + Boolean supported = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT; + PluginResult result = new PluginResult(PluginResult.Status.OK, supported); ctx.sendPluginResult(result); } @@ -119,24 +75,13 @@ public class Printer extends CordovaPlugin { * Druckt den HTML Content aus. */ private void print (final JSONArray args, CallbackContext ctx) { - final Printer self = this; - - this.ctx = ctx; + final KitKatPrinter self = this; cordova.getActivity().runOnUiThread( new Runnable() { public void run() { - JSONObject platformConfig = args.optJSONObject(1); - String appId = self.getPrintAppId(platformConfig); + String content = args.optString(0, ""); + WebView controller = self.getPrintController(); - if (appId == null) { - self.ctx.success(4); - return; - }; - - String content = args.optString(0, ""); - Intent controller = self.getPrintController(appId); - - self.adjustSettingsForPrintController(controller); self.loadContentIntoPrintController(content, controller); self.startPrinterApp(controller); @@ -144,200 +89,54 @@ public class Printer extends CordovaPlugin { }); } - /** - * Gibt die zu verwendende App-ID an. - */ - private String getPrintAppId (JSONObject platformConfig) { - String appId = platformConfig.optString("appId", null); - - if (appId != null) { - return (this.isAppInstalled(appId)) ? appId : null; - } else { - return this.getFirstInstalledAppId(); - } - } - /** * Erstellt den Print-View. */ - private Intent getPrintController (String appId) { - String intentId = "android.intent.action.SEND"; + private WebView getPrintController () { + WebView webview = new WebView(cordova.getActivity()); - if (appId.equals("com.rcreations.send2printer")) { - intentId = "com.rcreations.send2printer.print"; - } else if (appId.equals("com.dynamixsoftware.printershare")) { - intentId = "android.intent.action.VIEW"; - } else if (appId.equals("com.hp.android.print")) { - intentId = "org.androidprinting.intent.action.PRINT"; - } + webview.setVisibility(View.INVISIBLE); + webview.getSettings().setJavaScriptEnabled(false); - Intent intent = new Intent(intentId); - - if (appId != null) - intent.setPackage(appId); - - return intent; - } - - /** - * Stellt die Eigenschaften des Druckers ein. - */ - private void adjustSettingsForPrintController (Intent intent) { - String mimeType = "image/png"; - String appId = intent.getPackage(); - - // Check for special cases that can receive HTML - if (appId.equals("com.rcreations.send2printer") || appId.equals("com.dynamixsoftware.printershare")) { - mimeType = "text/html"; - } - - intent.setType(mimeType); + return webview; } /** * Lädt den zu druckenden Content in ein WebView, welcher vom Drucker ausgedruckt werden soll. */ - private void loadContentIntoPrintController (String content, Intent intent) { - String mimeType = intent.getType(); - - if (mimeType.equals("text/html")) { - loadContentAsHtmlIntoPrintController(content, intent); - } else { - loadContentAsBitmapIntoPrintController(content, intent); - } - } - - /** - * Lädt den zu druckenden Content als HTML in ein WebView, welcher vom Drucker ausgedruckt werden soll. - */ - private void loadContentAsHtmlIntoPrintController (String content, Intent intent) { - intent.putExtra(Intent.EXTRA_TEXT, content); - } - - /** - * Lädt den zu druckenden Content als BMP in ein WebView, welcher vom Drucker ausgedruckt werden soll. - */ - private void loadContentAsBitmapIntoPrintController (String content, final Intent intent) { - Activity ctx = cordova.getActivity(); - final WebView page = new WebView(ctx); - final Printer self = this; - - page.setVisibility(View.INVISIBLE); - page.getSettings().setJavaScriptEnabled(false); - - page.setWebViewClient( new WebViewClient() { - @Override - public void onPageFinished(final WebView page, String url) { - new Handler().postDelayed( new Runnable() { - @Override - public void run() { - Bitmap screenshot = self.takeScreenshot(page); - File tmpFile = self.saveScreenshotToTmpFile(screenshot); - ViewGroup vg = (ViewGroup)(page.getParent()); - - intent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(tmpFile)); - - vg.removeView(page); - } - }, 1000); - } - }); - + private void loadContentIntoPrintController (String content, WebView webview) { //Set base URI to the assets/www folder String baseURL = webView.getUrl(); - baseURL = baseURL.substring(0, baseURL.lastIndexOf('/') + 1); + baseURL = baseURL.substring(0, baseURL.lastIndexOf('/') + 1); - ctx.addContentView(page, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT)); - page.loadDataWithBaseURL(baseURL, content, "text/html", "UTF-8", null); - } - - /** - * Nimmt einen Screenshot der Seite auf. - */ - private Bitmap takeScreenshot (WebView page) { - Picture picture = page.capturePicture(); - Bitmap bitmap = Bitmap.createBitmap(picture.getWidth(), picture.getHeight(), Bitmap.Config.ARGB_8888); - Canvas canvas = new Canvas(bitmap); - - picture.draw(canvas); - - return bitmap; - } - - /** - * Speichert den Screenshot der Seite in einer tmp. Datei ab. - */ - private File saveScreenshotToTmpFile (Bitmap screenshot) { - try { - File tmpFile = File.createTempFile("screenshot", ".tmp"); - FileOutputStream stream = new FileOutputStream(tmpFile); - - screenshot.compress(Bitmap.CompressFormat.PNG, 100, stream); - stream.close(); - - return tmpFile; - } catch (IOException e) { - e.printStackTrace(); - } - - return null; + webview.loadDataWithBaseURL(baseURL, content, "text/html", "UTF-8", null); } /** * Öffnet die Printer App, damit der Content ausgedruckt werden kann. */ - private void startPrinterApp (Intent intent) { - cordova.startActivityForResult(this, intent, 0); - } - - /** - * Findet heraus, ob die Anwendung installiert ist. - */ - private boolean isAppInstalled (String appId) { - PackageManager pm = cordova.getActivity().getPackageManager(); - - try { - PackageInfo pi = pm.getPackageInfo(appId, 0); - - if (pi != null){ - return true; + private void startPrinterApp (WebView webview) { + webview.setWebViewClient (new WebViewClient() { + public boolean shouldOverrideUrlLoading (WebView view, String url) { + return false; } - } catch (PackageManager.NameNotFoundException e) {} - return false; - } + public void onPageFinished (WebView webview, String url) { + // Get a PrintManager instance + PrintManager printManager = (PrintManager) cordova.getActivity() + .getSystemService(Context.PRINT_SERVICE); - /** - * Die IDs aller verfügbaren Drucker-Apps. - */ - private JSONArray getInstalledAppIds () { - JSONArray appIds = new JSONArray(); + // Get a print adapter instance + PrintDocumentAdapter printAdapter = webView.createPrintDocumentAdapter(); - for (int i = 0; i < printAppIds.length; i++) { - String appId = printAppIds[i]; - Boolean isInstalled = this.isAppInstalled(appId); + // Get a print builder instance + PrintAttributes.Builder builder = new PrintAttributes.Builder(); - if (isInstalled){ - appIds.put(appId); + builder.setMinMargins(PrintAttributes.Margins.NO_MARGINS); + + // Create a print job with name and adapter instance + printManager.print("Print Document", printAdapter, builder.build()); } - } - - return appIds; - } - - /** - * Die erste ID in der Liste, deren App installiert ist. - */ - private String getFirstInstalledAppId () { - for (int i = 0; i < printAppIds.length; i++) { - String appId = printAppIds[i]; - Boolean isInstalled = this.isAppInstalled(appId); - - if (isInstalled){ - return appId; - } - } - - return null; + }); } } diff --git a/www/printer.js b/www/printer.js index 0df05dd..7b8d6e9 100755 --- a/www/printer.js +++ b/www/printer.js @@ -39,11 +39,7 @@ Printer.prototype = { callback.apply(scope || window, args); }; - if (device.platform == 'Android' && device.version >= '4.4') { - cordova.exec(callbackFn, null, 'KitKatPrinter', 'isServiceAvailable', []); - } else { - cordova.exec(callbackFn, null, 'Printer', 'isServiceAvailable', []); - }; + cordova.exec(callbackFn, null, 'Printer', 'isServiceAvailable', []); }, /** @@ -61,11 +57,7 @@ Printer.prototype = { return; } - if (device.platform == 'Android' && device.version >= '4.4') { - cordova.exec(null, null, 'KitKatPrinter', 'print', [page, options]); - } else { - cordova.exec(null, null, 'Printer', 'print', [page, options]); - }; + cordova.exec(null, null, 'Printer', 'print', [page, options]); } }; From 43bd2ff428b76433a3e8f3c8eccb0e8837e74b21 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Katzer?= Date: Sun, 7 Sep 2014 22:32:50 +0200 Subject: [PATCH 02/21] Fix unknown class error --- src/android/Printer.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/android/Printer.java b/src/android/Printer.java index 15fae6a..edc4363 100644 --- a/src/android/Printer.java +++ b/src/android/Printer.java @@ -75,7 +75,7 @@ public class Printer extends CordovaPlugin { * Druckt den HTML Content aus. */ private void print (final JSONArray args, CallbackContext ctx) { - final KitKatPrinter self = this; + final Printer self = this; cordova.getActivity().runOnUiThread( new Runnable() { public void run() { From 86689d9942e08edeebebe0c23272848152ef7705 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Katzer?= Date: Sun, 7 Sep 2014 22:34:38 +0200 Subject: [PATCH 03/21] Remove not needed dependencies --- plugin.xml | 2 -- 1 file changed, 2 deletions(-) diff --git a/plugin.xml b/plugin.xml index 3200a63..5293392 100644 --- a/plugin.xml +++ b/plugin.xml @@ -18,8 +18,6 @@ - - From 125f2e6828b05f51484cd5fab3399d743a8f421f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Katzer?= Date: Sun, 7 Sep 2014 22:35:05 +0200 Subject: [PATCH 04/21] Clean up not existing source --- plugin.xml | 3 --- 1 file changed, 3 deletions(-) diff --git a/plugin.xml b/plugin.xml index 5293392..7818b48 100644 --- a/plugin.xml +++ b/plugin.xml @@ -43,9 +43,6 @@ - - - From 43625bd313465e8e5921ddb0f700f80776809952 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Katzer?= Date: Sun, 7 Sep 2014 22:52:36 +0200 Subject: [PATCH 05/21] Update ios --- src/ios/APPPrinter.h | 10 +-- src/ios/APPPrinter.m | 178 ++++++++++++++++++++++++++++--------------- 2 files changed, 122 insertions(+), 66 deletions(-) diff --git a/src/ios/APPPrinter.h b/src/ios/APPPrinter.h index addca7f..e652c2a 100755 --- a/src/ios/APPPrinter.h +++ b/src/ios/APPPrinter.h @@ -1,5 +1,5 @@ /* - Copyright 2013 appPlant UG + Copyright 2013-2014 appPlant UG Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file @@ -23,13 +23,11 @@ #import -@interface APPPrinter : CDVPlugin { - -} +@interface APPPrinter : CDVPlugin // Prints the content - (void) print:(CDVInvokedUrlCommand*)command; // Find out whether printing is supported on this platform -- (void) isServiceAvailable:(CDVInvokedUrlCommand*)command; +- (void) isAvailable:(CDVInvokedUrlCommand*)command; -@end +@end \ No newline at end of file diff --git a/src/ios/APPPrinter.m b/src/ios/APPPrinter.m index 987bddb..ef5020d 100755 --- a/src/ios/APPPrinter.m +++ b/src/ios/APPPrinter.m @@ -1,5 +1,5 @@ /* - Copyright 2013 appPlant UG + Copyright 2013-2014 appPlant UG Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file @@ -21,18 +21,9 @@ #import "APPPrinter.h" -@interface APPPrinter (Private) +@interface APPPrinter () -// Erstellt den PrintController -- (UIPrintInteractionController*) getPrintController; -// Stellt die Eigenschaften des Druckers ein. -- (UIPrintInteractionController*) adjustSettingsForPrintController:(UIPrintInteractionController*)controller; -// Lädt den zu druckenden Content in ein WebView, welcher vom Drucker ausgedruckt werden soll. -- (void) loadContent:(NSString*)content intoPrintController:(UIPrintInteractionController*)controller; -// Ruft den Callback auf und informiert diesen über den das Ergebnis des Druckvorgangs. -- (void) informAboutResult:(int)code callbackId:(NSString*)callbackId; -// Überprüft, ob der Drucker-Dienst verfügbar ist -- (BOOL) isPrintServiceAvailable; +@property (retain) NSString* callbackId; @end @@ -40,108 +31,175 @@ @implementation APPPrinter /* - * Is printing available. + * Checks if the printing service is available. + * + * @param {Function} callback + * A callback function to be called with the result */ -- (void) isServiceAvailable:(CDVInvokedUrlCommand*)command +- (void) isAvailable:(CDVInvokedUrlCommand*)command { CDVPluginResult* pluginResult; + BOOL isAvailable = [self isPrintingAvailable]; pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK - messageAsBool:[self isPrintServiceAvailable]]; + messageAsBool:isAvailable]; - [self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId]; + [self.commandDelegate sendPluginResult:pluginResult + callbackId:command.callbackId]; } /** - * Öffnet den Drucker-Kontroller zur Auswahl des Druckers. - * Callback gibt Meta-Informationen an. + * Sends the printing content to the printer controller and opens them. + * + * @param {NSString} content + * The (HTML encoded) content */ - (void) print:(CDVInvokedUrlCommand*)command { - if (![self isPrintServiceAvailable]) - { + if (!self.isPrintingAvailable) { return; } - NSArray* arguments = [command arguments]; - NSString* content = [arguments objectAtIndex:0]; + _callbackId = command.callbackId; - UIPrintInteractionController* controller = [self getPrintController]; + NSArray* arguments = [command arguments]; + NSString* content = [arguments objectAtIndex:0]; + NSMutableDictionary* settings = [arguments objectAtIndex:1]; - [self adjustSettingsForPrintController:controller]; + UIPrintInteractionController* controller = [self printController]; + + [self adjustPrintController:controller withSettings:settings]; [self loadContent:content intoPrintController:controller]; - - [self openPrintController:controller]; - - [self commandDelegate]; + [self presentPrintController:controller]; } /** - * Erstellt den PrintController. + * Retrieves an instance of shared print controller. + * + * @return {UIPrintInteractionController*} */ -- (UIPrintInteractionController*) getPrintController +- (UIPrintInteractionController*) printController { return [UIPrintInteractionController sharedPrintController]; } /** - * Stellt die Eigenschaften des Druckers ein. + * Adjusts the settings for the print controller. + * + * @param {UIPrintInteractionController} controller + * The print controller instance + * + * @return {UIPrintInteractionController} controller + * The modified print controller instance */ -- (UIPrintInteractionController*) adjustSettingsForPrintController:(UIPrintInteractionController*)controller +- (UIPrintInteractionController*) adjustPrintController:(UIPrintInteractionController*)controller + withSettings:(NSMutableDictionary*)settings { - UIPrintInfo* printInfo = [UIPrintInfo printInfo]; - printInfo.outputType = UIPrintInfoOutputGeneral; + UIPrintInfo* printInfo = [UIPrintInfo printInfo]; + UIPrintInfoOrientation orientation = UIPrintInfoOrientationPortrait; + UIPrintInfoOutputType outputType = UIPrintInfoOutputGeneral; + + if ([[settings objectForKey:@"landscape"] boolValue]) { + orientation = UIPrintInfoOrientationLandscape; + } + + if ([[settings objectForKey:@"graystyle"] boolValue]) { + outputType = UIPrintInfoOutputGrayscale; + } + + printInfo.outputType = outputType; + printInfo.orientation = orientation; + printInfo.jobName = [settings objectForKey:@"name"]; + printInfo.duplex = [[settings objectForKey:@"duplex"] boolValue]; + printInfo.printerID = [settings objectForKey:@"printerId"]; + controller.printInfo = printInfo; - controller.showsPageRange = YES; + controller.showsPageRange = NO; return controller; } /** - * Lädt den zu druckenden Content in ein WebView, welcher vom Drucker ausgedruckt werden soll. + * Adjusts the web view and page renderer. + */ +- (void) adjustWebView:(UIWebView*)page + andPrintPageRenderer:(UIPrintPageRenderer*)renderer +{ + UIViewPrintFormatter* formatter = [page viewPrintFormatter]; + // margin not required - done in web page + formatter.contentInsets = UIEdgeInsetsMake(0.0f, 0.0f, 0.0f, 0.0f); + + renderer.headerHeight = -30.0f; + renderer.footerHeight = -30.0f; + [renderer addPrintFormatter:formatter startingAtPageAtIndex:0]; + + page.scalesPageToFit = YES; + page.dataDetectorTypes = UIDataDetectorTypeNone; + page.userInteractionEnabled = NO; + page.autoresizingMask = (UIViewAutoresizingFlexibleWidth | + UIViewAutoresizingFlexibleHeight); +} + +/** + * Loads the content into the print controller. + * + * @param {NSString} content + * The (HTML encoded) content + * @param {UIPrintInteractionController} controller + * The print controller instance */ - (void) loadContent:(NSString*)content intoPrintController:(UIPrintInteractionController*)controller { + UIWebView* page = [[UIWebView alloc] init]; + UIPrintPageRenderer* renderer = [[UIPrintPageRenderer alloc] init]; + + [self adjustWebView:page andPrintPageRenderer:renderer]; + // Set the base URL to be the www directory. - NSString* wwwFilePath = [[NSBundle mainBundle] pathForResource:@"www" ofType:nil]; - NSURL* baseURL = [NSURL fileURLWithPath:wwwFilePath]; - // Load page into a webview and use its formatter to print the page - UIWebView* webPage = [[UIWebView alloc] init]; + NSString* wwwFilePath = [[NSBundle mainBundle] pathForResource:@"www" + ofType:nil]; + NSURL* baseURL = [NSURL fileURLWithPath:wwwFilePath]; - [webPage loadHTMLString:content baseURL:baseURL]; - // Get formatter for web (note: margin not required - done in web page) - UIViewPrintFormatter* formatter = [webPage viewPrintFormatter]; + [page loadHTMLString:content baseURL:baseURL]; - controller.printFormatter = formatter; - controller.showsPageRange = YES; + controller.printPageRenderer = renderer; } /** - * Zeigt den PrintController an. + * Opens the print controller so that the user can choose between + * available iPrinters. + * + * @param {UIPrintInteractionController} controller + * The prepared print controller with a content */ -- (void) openPrintController:(UIPrintInteractionController*)controller +- (void) presentPrintController:(UIPrintInteractionController*)controller { - //[self.commandDelegate runInBackground:^{ - [controller presentAnimated:YES completionHandler:NULL]; - //}]; + [controller presentAnimated:YES completionHandler: + ^(UIPrintInteractionController *ctrl, BOOL ok, NSError *e) { + CDVPluginResult* pluginResult = + [CDVPluginResult resultWithStatus:CDVCommandStatus_OK]; + + [self.commandDelegate sendPluginResult:pluginResult + callbackId:_callbackId]; + }]; } /** - * Überprüft, ob der Drucker-Dienst verfügbar ist. + * Checks either the printing service is avaible or not. + * + * @return {BOOL} */ -- (BOOL) isPrintServiceAvailable +- (BOOL) isPrintingAvailable { - Class printController = NSClassFromString(@"UIPrintInteractionController"); + Class controllerCls = NSClassFromString(@"UIPrintInteractionController"); - if (printController) - { - UIPrintInteractionController* controller = [UIPrintInteractionController sharedPrintController]; - - return (controller != nil) && [UIPrintInteractionController isPrintingAvailable]; + if (!controllerCls) { + return NO; } - return NO; + return [self printController] && [UIPrintInteractionController + isPrintingAvailable]; } -@end +@end \ No newline at end of file From 33b4c14557e96f61e1e8ac94847dc9be1dd38c8a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Katzer?= Date: Sun, 7 Sep 2014 22:52:47 +0200 Subject: [PATCH 06/21] Update js --- www/printer.js | 108 ++++++++++++++++++++++++++++++++----------------- 1 file changed, 70 insertions(+), 38 deletions(-) diff --git a/www/printer.js b/www/printer.js index 7b8d6e9..9af6c02 100755 --- a/www/printer.js +++ b/www/printer.js @@ -1,5 +1,5 @@ /* - Copyright 2013 appPlant UG + Copyright 2013-2014 appPlant UG Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file @@ -19,48 +19,80 @@ under the License. */ -var Printer = function () { +var exec = require('cordova/exec'); +/** + * The default document/job name. + */ +exports.DEFAULT_DOC_NAME = 'unknown'; + +/** + * Checks if the printer service is avaible (iOS) + * or if connected to the Internet (Android). + * + * @param {Function} callback + * A callback function + * @param {Object?} scope + * The scope of the callback (default: window) + * + * @return {Boolean} + */ +exports.isAvailable = function (callback, scope) { + var fn = this._createCallbackFn(callback); + + exec(fn, null, 'Printer', 'isAvailable', []); }; -Printer.prototype = { - /** - * Überprüft, ob der Drucker-Dienst verfügbar ist. - * - * @param {Function} callback - * @param {Object?} scope callback scope (default: window) - * - * @return {Boolean} - */ - isServiceAvailable: function (callback, scope) { - var callbackFn = function () { - var args = typeof arguments[0] == 'boolean' ? arguments : arguments[0]; +/** + * Sends the content to the Google Cloud Print service. + * + * @param {String} content + * HTML string or DOM node + * if latter, innerHTML is used to get the content + * @param {Object} options + * Options for the print job + * @param {Function?} callback + * A callback function + * @param {Object?} scope + * The scope of the callback (default: window) + */ +exports.print = function (content, options, callback, scope) { + var page = content.innerHTML || content, + params = options || {}, + fn = this._createCallbackFn(callback); - callback.apply(scope || window, args); - }; - - cordova.exec(callbackFn, null, 'Printer', 'isServiceAvailable', []); - }, - - /** - * Übergibt den HTML-Content an den Drucker-Dienst. - * - * @param {String} content HTML string or DOM node (if latter, innerHTML is used to get the contents) - * @param {Object?} options platform specific options - */ - print: function (content, options) { - var page = content.innerHTML || content, - options = options || {}; - - if (typeof page != 'string') { - console.log('Print function requires an HTML string. Not an object'); - return; - } - - cordova.exec(null, null, 'Printer', 'print', [page, options]); + if (typeof page != 'string') { + console.log('Print function requires an HTML string. Not an object'); + return; } + + if (typeof params == 'string') + params = { name: params }; + + if ([null, undefined, ''].indexOf(params.name) > -1) + params.name = this.DEFAULT_DOC_NAME; + + exec(fn, null, 'Printer', 'print', [page, params]); }; -var plugin = new Printer(); +/** + * @private + * + * Creates a callback, which will be executed within a specific scope. + * + * @param {Function} callbackFn + * The callback function + * @param {Object} scope + * The scope for the function + * + * @return {Function} + * The new callback function + */ +exports._createCallbackFn = function (callbackFn, scope) { + if (typeof callbackFn != 'function') + return; -module.exports = plugin; \ No newline at end of file + return function () { + callbackFn.apply(scope || this, arguments); + }; +}; \ No newline at end of file From b9036834867ce2e7e0398dbcba69c156d556f995 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Katzer?= Date: Sun, 7 Sep 2014 22:53:04 +0200 Subject: [PATCH 07/21] Update plugin spec --- plugin.xml | 30 ++++++++++++++++++++---------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/plugin.xml b/plugin.xml index 7818b48..8e2419f 100644 --- a/plugin.xml +++ b/plugin.xml @@ -3,17 +3,28 @@ + version="0.7.0-dev"> - Printer + AirPrint and Android Printing Framework + + + Cordova plugin to print HTML documents using AirPrint for iOS + and Android Printing Framework. + + + + https://github.com/katzer/cordova-plugin-printer.git + + + + print, printer, ios, android, google cloud, air print + - A bunch of printig plugins for Cordova 3.x.x - https://github.com/katzer/cordova-plugin-printer.git - print, printer, ios, android, kitkat Apache 2.0 Sebastián Katzer + @@ -21,15 +32,15 @@ + - - - - + + + @@ -47,5 +58,4 @@ - From c54a18a5a28b0b9decf3753f429083a16dfd5566 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Katzer?= Date: Sun, 7 Sep 2014 23:05:25 +0200 Subject: [PATCH 08/21] Rename isServiceAvailable to isAvailable --- src/android/Printer.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/android/Printer.java b/src/android/Printer.java index edc4363..5c8fb2c 100644 --- a/src/android/Printer.java +++ b/src/android/Printer.java @@ -44,8 +44,8 @@ public class Printer extends CordovaPlugin { @Override public boolean execute (String action, JSONArray args, CallbackContext callbackContext) throws JSONException { // Es soll überprüft werden, ob ein Dienst zum Ausdrucken von Inhalten zur Verfügung steht - if (action.equalsIgnoreCase("isServiceAvailable")) { - isServiceAvailable(callbackContext); + if (action.equalsIgnoreCase("isAvailable")) { + isAvailable(callbackContext); return true; } @@ -64,7 +64,7 @@ public class Printer extends CordovaPlugin { /** * Überprüft, ob ein Drucker zur Verfügung steht. */ - private void isServiceAvailable (CallbackContext ctx) { + private void isAvailable (CallbackContext ctx) { Boolean supported = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT; PluginResult result = new PluginResult(PluginResult.Status.OK, supported); From cdd721d24bc6c350a6ad8b47b3b4873724c9f599 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Katzer?= Date: Mon, 8 Sep 2014 09:31:14 +0200 Subject: [PATCH 09/21] Update README.md --- README.md | 250 +++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 201 insertions(+), 49 deletions(-) diff --git a/README.md b/README.md index d2e5da5..20c53b7 100644 --- a/README.md +++ b/README.md @@ -1,85 +1,220 @@ -Cordova Printer-Plugin -====================== -A bunch of printing plugins for Cordova 3.x.x +

+ master +   + v0.6 +   + v0.5 +

+ +Cordova Print Plugin +==================== + +[Cordova][cordova] plugin to print HTML documents using [AirPrint][AirPrint] for iOS and [Android Printing Framework][APF] for Android KitKat and above. + +__Choose the right branch for you!__ + +The plugin provides multiple branches to support different printer types and android versions while _AirPrint_ is supported with each one. This is the _master_ branch. + +- [master Branch][master_branch] for iOS and Android >= 4.4 (>= v0.7.x) +- [google-cloud-print Branch][google-cloud-print_branch] for Android <= 4.3 (~> v0.6.x) +- __Deprecated__ [network-printer Branch][network-printer_branch] for Android <= 4.3 (<= v0.5.x) + +### About Apple AirPrint +AirPrint is an Apple™ technology that helps you create full-quality printed output without the need to download or install drivers. AirPrint is built in to many printer models from most popular printer manufacturers. Just select an AirPrint printer on your local network to print from your favorite iOS or OS X app.
+AirPrint printers are available for these devices when using the latest version of iOS available for them: + - iPad (all models) + - iPhone (3GS or later) + - iPod touch (3rd generation or later) + + + +### Android Printing Framework +Printing in __Android 4.4__ and later is provided by the Printing framework. By default, most Android devices have print service plugins installed to enable printing using the Google Cloud Print and Google Drive services. Print service plugins from other printer manufactures are available through the App Store though the Google Cloud Print service plugin can also be used to print from an Android device to just about any printer type and model.
+In addition to supporting physical printers, it is also possible to save printed output to your Google Drive account or locally as a PDF file on the Android device. + + + +### Supported Printers +Printing is supported on AirPrint- and Google Cloud Print-enabled printers or from Android devices to compatible network printers over Wi-Fi. The following pages contain more information: + - AirPrint-enabled printers: http://www.apple.com/ipad/features/airprint.html + - Enabling AirPrint on your computer: http://reviews.cnet.com/8301-19512_7-20023976-233.html, or http://www.ecamm.com/mac/printopia/ + - Google Cloud-ready printers: http://www.google.com/cloudprint/learn/printers.html + - Connect network printers with Google Cloud Print: https://support.google.com/cloudprint/answer/1686197?rd=1 + - Printing with the Android Printing Framework: http://www.techotopia.com/index.php/Printing_with_the_Android_Printing_Framework + +### Plugin's Purpose +This Cordova plugin serves as a platform independent JavaScript bridge to call the underlying native SDKs. -by Sebastián Katzer ([github.com/katzer](https://github.com/katzer)) ## Supported Platforms - **iOS** *(Print from iOS devices to AirPrint compatible printers)*
-See [Drawing and Printing Guide for iOS](http://developer.apple.com/library/ios/documentation/2ddrawing/conceptual/drawingprintingios/Printing/Printing.html) for detailed informations and screenshots. +See [Drawing and Printing Guide for iOS][ios_guide] for detailed informations and screenshots. -- **Android** *(SDK 19)* +- **Android KitKat** *(Print from Android devices to compatible printers over Wi-Fi or cloud-hosted services such as Google Cloud Print)* -## Adding the Plugin to your project -Through the [Command-line Interface](http://cordova.apache.org/docs/en/3.0.0/guide_cli_index.md.html#The%20Command-line%20Interface): +## Installation +The plugin can either be installed from git repository, from local file system through the [Command-line Interface][CLI] or cloud based through [PhoneGap Build][PGB]. + +### Local development environment +From master: ```bash +# ~~ from master ~~ cordova plugin add https://github.com/katzer/cordova-plugin-printer.git ``` - -## Removing the Plugin from your project -Through the [Command-line Interface](http://cordova.apache.org/docs/en/3.0.0/guide_cli_index.md.html#The%20Command-line%20Interface): +from a local folder: +```bash +# ~~ local folder ~~ +cordova plugin add de.appplant.cordova.plugin.printer --searchpath path/to/plugin ``` +or to use the last stable version: +```bash +# ~~ stable version ~~ +cordova plugin add de.appplant.cordova.plugin.printer +``` + +### PhoneGap Build +Add the following xml to your config.xml to always use the latest version of this plugin: +```xml + +``` +or to use an specific version: +```xml + +``` +More informations can be found [here][PGB_plugin]. + +### Removing the Plugin +Through the [Command-line Interface][CLI]: +```bash cordova plugin rm de.appplant.cordova.plugin.printer ``` -## Release Notes -#### Version 0.5.0 (11.12.2013) -- Release under the Apache 2.0 license. -- [***change:***] Removed the `callback` property from the `print` interface. -- [enhancement:] Added Android KitKat support
- *Based on the Print Android plugin made by* ***Eion Robb*** -#### Version 0.4.0 (24.08.2013) -- [feature]: Added Android support
- *Based on the Print Android plugin made by* ***Eion Robb*** -- [feature]: `print()` accepts a 4th arguments for platform specific properties. -- [change]: the callback of `print()` will be called with a result code about the user action. +## ChangeLog +#### Version 0.7.0 (not yet released) +- AirPrint support +- Android Printing Framework support +- [__change__:] Renamed `isServiceAvailable` to `isAvailable`. +- [enhancement:] New print options like `name`, `landscape` or `duplex`. -#### Version 0.2.1 (13.08.2013) -- [feature]: Support for callback scopes. +#### Further informations +- See [CHANGELOG.md][changelog] to get the full changelog for the plugin. -#### Version 0.2.0 (11.08.2013) -- [feature]: Added iOS support
- *Based on the Print iOS plugin made by* ***Randy McMillan*** ## Using the plugin -The plugin creates the object ```window.plugin.printer``` with two methods: +The plugin creates the object `cordova.plugins.printer` with the following methods: -### isServiceAvailable() -Printing is only available on devices capable of multi-tasking (iPhone 3GS, iPhone 4 etc.) running iOS 4.2 or later. You can use this function to hide print functionality from users who will be unable to use it.
-Function takes a callback function, passed to which is a boolean property. Optionally you can assign the scope in which the callback will be executed as a second parameter (default to *window*). +1. [printer.isAvailable][available] +2. [printer.print][print] + +### Plugin initialization +The plugin and its methods are not available before the *deviceready* event has been fired. ```javascript -/* - * Find out if printing is available. Use this for showing/hiding print buttons. +document.addEventListener('deviceready', function () { + // cordova.plugins.printer is now available +}, false); +``` + +### Find out if printing is available on the device +The device his printing capabilities can be reviewed through the `printer.isAvailable` interface. +You can use this function to hide print functionality from users who will be unable to use it.
+The method takes a callback function, passed to which is a boolean property. Optionally you can assign the scope in which the callback will be executed as a second parameter (default to *window*). + +__Note:__ Printing is only available on devices capable of multi-tasking (iPhone 3GS, iPhone 4 etc.) running iOS 4.2 or later or Android KitKat and above.
+ +```javascript +/** + * Checks if the printer service is avaible (iOS) + * or if connected to the Internet (Android). + * + * @param {Function} callback + * A callback function + * @param {Object?} scope + * The scope of the callback (default: window) + * + * @return {Boolean} */ -window.plugin.printer.isServiceAvailable( +cordova.plugins.printer.isAvailable( function (isAvailable) { alert(isAvailable ? 'Service is available' : 'Service NOT available'); } ); ``` -### print() -Function takes an html string. +### Send content to a printer +Content can be send to a printer through the `printer.print` interface.
+The method takes a string or a HTML DOM node. Optional parameters allows to specify the name of the document and a callback. The callback will be called if the user cancels or completes the print job. -**Note:** All required CSS rules needs to be included as well. +#### Available Options +| Name | Description | Type | Support | +| ---- | ----------- |:----:| -------:| +| name | The name of the print job and of the document | String | all | +| printerId| An identifier of the printer to use for the print job. | String | iOS | +| duplex | Specifies the duplex mode to use for the print job.
Either double-sided (duplex:true) or single-sided (duplex:false).
Double-sided by default. | Boolean | iOS | +| landscape| The orientation of the printed content, portrait or landscape.
_Portrait_ by default. | Boolean | all | +| graystyle | If your application only prints black text, setting this property to _true_ can result in better performance in many cases.
_False_ by default. | Boolean | all | + +#### Further informations +- See the [isAvailable][available] method to find out if printing is available on the device. +- All CSS rules needs to be embedded or accessible via absolute URLs in order to print out HTML encoded content. +- See the [examples][examples] to get an overview on how to use the plugin. ```javascript -// Get HTML string -var page = document.body.innerHTML; +/** + * Sends the content to the Google Cloud Print service. + * + * @param {String} content + * HTML string or DOM node + * if latter, innerHTML is used to get the content + * @param {Object} options + * Options for the print job + * @param {Function?} callback + * A callback function + * @param {Object?} scope + * The scope of the callback (default: window) + */ +cordova.plugins.printer.print(content, options, callback, scope); +``` -// Pass the HTML -window.plugin.printer.print(page); + +## Examples +__NOTE:__ All CSS rules needs to be embedded or accessible via absolute URLs in order to print out HTML encoded content. + +#### 1. Print the whole HTML page +```javascript +// Either a DOM node or a string +var page = document.body; + +cordova.plugins.printer.print(page, 'Document.html', function () { + alert('printing finished or canceled') +}); +``` + +#### 2. Print custom specific content +```javascript +// Either a DOM node or a string +var page = '

Hello Document

'; + +cordova.plugins.printer.print(page, 'Document.html', function () { + alert('printing finished or canceled') +}); +``` + +#### 3. Adjust the page +```javascript +cordova.plugins.printer.print('123', { name:'Document.html', landscape:true }, function () { + alert('printing finished or canceled') +}); ``` ## Quirks ### Testing in the iOS Simulator -There's no need to waste lots of paper when testing - if you're using the iOS simulator, select File->Open Printer Simulator to open some dummy printers (print outs will appear as PDF files). +There's no need to waste lots of paper when testing - if you're using the iOS simulator, select _File -> Open Printer Simulator_ to open some dummy printers (print outs will appear as PDF files). ### Adding Page Breaks to Printouts Use the 'page-break-before' property to specify a page break, e.g. @@ -96,14 +231,9 @@ Second page. See W3Schools for more more information: http://www.w3schools.com/cssref/pr_print_pagebb.asp -Note: you will need to add an extra top margin to new pages. +__Note:__ You will need to add an extra top margin to new pages. -### Printing on Real Printers (iOS) -Printing is only supported on AirPrint-enabled printers or with the use of third-party software on your computer. The following pages contain more information: - - AirPrint-enabled printers: http://www.apple.com/ipad/features/airprint.html - - Enabling AirPrint on your computer: http://reviews.cnet.com/8301-19512_7-20023976-233.html, or http://www.ecamm.com/mac/printopia/ - ## Contributing 1. Fork it @@ -114,4 +244,26 @@ Printing is only supported on AirPrint-enabled printers or with the use of third ## License -This software is released under the [Apache 2.0 License](http://opensource.org/licenses/Apache-2.0). +This software is released under the [Apache 2.0 License][apache2_license]. + +© 2013-2014 appPlant UG, Inc. All rights reserved + + +[cordova]: https://cordova.apache.org +[GCP]: http://www.google.com/cloudprint/learn/index.html +[APF]: http://www.techotopia.com/index.php/Printing_with_the_Android_Printing_Framework +[AirPrint]: http://support.apple.com/kb/ht4356 +[master_branch]: # +[google-cloud-print_branch]: https://github.com/katzer/cordova-plugin-printer/tree/google-cloud-print +[network-printer_branch]: https://github.com/katzer/cordova-plugin-printer/tree/network-printer +[ios_guide]: http://developer.apple.com/library/ios/documentation/2ddrawing/conceptual/drawingprintingios/Printing/Printing.html +[CLI]: http://cordova.apache.org/docs/en/edge/guide_cli_index.md.html#The%20Command-line%20Interface +[PGB]: http://docs.build.phonegap.com/en_US/index.html +[PGB_plugin]: https://build.phonegap.com/plugins/ +[changelog]: CHANGELOG.md +[available]: #find-out-if-printing-is-available-on-the-device +[print]: #send-content-to-a-printer +[examples]: #examples +[apache2_license]: http://opensource.org/licenses/Apache-2.0 +[katzer]: katzer@appplant.de +[appplant]: www.appplant.de \ No newline at end of file From 6053b1f83ac5b56bd2a1edd0a25c4a91ee62a9ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Katzer?= Date: Mon, 8 Sep 2014 09:32:54 +0200 Subject: [PATCH 10/21] Add ChangeLog --- CHANGELOG.md | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 CHANGELOG.md diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..adef259 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,6 @@ +## ChangeLog +#### Version 0.7.0 (not yet released) +- AirPrint support +- Android Printing Framework support +- [__change__:] Renamed `isServiceAvailable` to `isAvailable`. +- [enhancement:] New print options like `name`, `landscape` or `duplex`. \ No newline at end of file From 7cae0fa4a588309ba281d10e881383943cb3d64d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Katzer?= Date: Thu, 11 Sep 2014 23:14:18 +0200 Subject: [PATCH 11/21] Ability to print remote content via URI --- src/ios/APPPrinter.m | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/src/ios/APPPrinter.m b/src/ios/APPPrinter.m index ef5020d..9056a66 100755 --- a/src/ios/APPPrinter.m +++ b/src/ios/APPPrinter.m @@ -155,13 +155,20 @@ [self adjustWebView:page andPrintPageRenderer:renderer]; - // Set the base URL to be the www directory. - NSString* wwwFilePath = [[NSBundle mainBundle] pathForResource:@"www" - ofType:nil]; - NSURL* baseURL = [NSURL fileURLWithPath:wwwFilePath]; + if ([NSURL URLWithString:content]) { + NSURL *url = [NSURL URLWithString:content]; + + [page loadRequest:[NSURLRequest requestWithURL:url]]; + } + else { + // Set the base URL to be the www directory. + NSString* wwwFilePath = [[NSBundle mainBundle] pathForResource:@"www" + ofType:nil]; + NSURL* baseURL = [NSURL fileURLWithPath:wwwFilePath]; - [page loadHTMLString:content baseURL:baseURL]; + [page loadHTMLString:content baseURL:baseURL]; + } controller.printPageRenderer = renderer; } From 922870f95c4c9efdc526595ee71a06534e792ca9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Katzer?= Date: Thu, 11 Sep 2014 23:14:47 +0200 Subject: [PATCH 12/21] Rewrite JAVA code --- src/android/Printer.java | 164 +++++++++++++++++++++++++++++---------- 1 file changed, 124 insertions(+), 40 deletions(-) diff --git a/src/android/Printer.java b/src/android/Printer.java index 5c8fb2c..a213302 100644 --- a/src/android/Printer.java +++ b/src/android/Printer.java @@ -1,5 +1,5 @@ /* - Copyright 2013 appPlant UG + Copyright 2013-2014 appPlant UG Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file @@ -17,42 +17,67 @@ KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. -*/ + */ package de.appplant.cordova.plugin.printer; import org.apache.cordova.CallbackContext; import org.apache.cordova.CordovaPlugin; import org.apache.cordova.PluginResult; - import org.json.JSONArray; import org.json.JSONException; +import org.json.JSONObject; import android.annotation.TargetApi; +import android.app.Activity; import android.content.Context; import android.os.Build; +import android.os.Looper; import android.print.PrintAttributes; import android.print.PrintDocumentAdapter; +import android.print.PrintJob; import android.print.PrintManager; -import android.view.View; import android.webkit.WebView; import android.webkit.WebViewClient; @TargetApi(19) public class Printer extends CordovaPlugin { + private WebView view; + + private CallbackContext command; + + private static final String DEFAULT_DOC_NAME = "unknown"; + + /** + * Executes the request. + * + * This method is called from the WebView thread. + * To do a non-trivial amount of work, use: + * cordova.getThreadPool().execute(runnable); + * + * To run on the UI thread, use: + * cordova.getActivity().runOnUiThread(runnable); + * + * @param action The action to execute. + * @param rawArgs The exec() arguments in JSON form. + * @param callbackContext The callback context used when calling back into JavaScript. + * @return Whether the action was valid. + */ @Override - public boolean execute (String action, JSONArray args, CallbackContext callbackContext) throws JSONException { - // Es soll überprüft werden, ob ein Dienst zum Ausdrucken von Inhalten zur Verfügung steht + public boolean execute (String action, JSONArray args, + CallbackContext callbackContext) throws JSONException { + + command = callbackContext; + if (action.equalsIgnoreCase("isAvailable")) { - isAvailable(callbackContext); + isAvailable(); return true; } - // Etwas soll ausgedruckt werden if (action.equalsIgnoreCase("print")) { - print(args, callbackContext); + print(args); return true; } @@ -62,69 +87,95 @@ public class Printer extends CordovaPlugin { } /** - * Überprüft, ob ein Drucker zur Verfügung steht. + * Informs if the device is able to print documents. + * A Internet connection is required to load the cloud print dialog. */ - private void isAvailable (CallbackContext ctx) { + private void isAvailable () { Boolean supported = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT; PluginResult result = new PluginResult(PluginResult.Status.OK, supported); - ctx.sendPluginResult(result); + command.sendPluginResult(result); } /** - * Druckt den HTML Content aus. + * Loads the HTML content into the web view and invokes the print manager. + * + * @param args + * The exec arguments as JSON */ - private void print (final JSONArray args, CallbackContext ctx) { - final Printer self = this; + private void print (final JSONArray args) { + final String content = args.optString(0, ""); + final JSONObject props = args.optJSONObject(1);; cordova.getActivity().runOnUiThread( new Runnable() { + @Override public void run() { - String content = args.optString(0, ""); - WebView controller = self.getPrintController(); - - self.loadContentIntoPrintController(content, controller); - - self.startPrinterApp(controller); + initWebView(content, props); + loadContent(content); } }); } /** - * Erstellt den Print-View. + * Loads the content into the web view. + * + * @param content + * Either an HTML string or URI */ - private WebView getPrintController () { - WebView webview = new WebView(cordova.getActivity()); + private void loadContent(String content) { + if (content.startsWith("http") || content.startsWith("file:")) { + view.loadUrl(content); + } else { + //Set base URI to the assets/www folder + String baseURL = webView.getUrl(); + baseURL = baseURL.substring(0, baseURL.lastIndexOf('/') + 1); - webview.setVisibility(View.INVISIBLE); - webview.getSettings().setJavaScriptEnabled(false); - - return webview; + view.loadDataWithBaseURL(baseURL, content, "text/html", "UTF-8", null); + } } /** - * Lädt den zu druckenden Content in ein WebView, welcher vom Drucker ausgedruckt werden soll. + * Configures the WebView components which will call the Google Cloud Print + * Service. + * + * @param content + * HTML encoded string + * @param props + * The JSON object with the containing page properties */ - private void loadContentIntoPrintController (String content, WebView webview) { - //Set base URI to the assets/www folder - String baseURL = webView.getUrl(); - baseURL = baseURL.substring(0, baseURL.lastIndexOf('/') + 1); + private void initWebView (String content, JSONObject props) { + Activity ctx = cordova.getActivity(); + view = new WebView(ctx); - webview.loadDataWithBaseURL(baseURL, content, "text/html", "UTF-8", null); + view.getSettings().setDatabaseEnabled(true); + + setWebViewClient(content, props); } /** - * Öffnet die Printer App, damit der Content ausgedruckt werden kann. + * Creates the web view client which sets the print document. + * + * @param content + * HTML encoded string + * @param props + * The JSON object with the containing page properties */ - private void startPrinterApp (WebView webview) { - webview.setWebViewClient (new WebViewClient() { + private void setWebViewClient (final String content, JSONObject props) { + final String docName = props.optString("name", DEFAULT_DOC_NAME); + final boolean landscape = props.optBoolean("landscape", false); + final boolean graystyle = props.optBoolean("graystyle", false); + + view.setWebViewClient(new WebViewClient() { + @Override public boolean shouldOverrideUrlLoading (WebView view, String url) { return false; } - public void onPageFinished (WebView webview, String url) { + @Override + public void onPageFinished (WebView webView, String url) { // Get a PrintManager instance PrintManager printManager = (PrintManager) cordova.getActivity() - .getSystemService(Context.PRINT_SERVICE); + .getSystemService(Context.PRINT_SERVICE); // Get a print adapter instance PrintDocumentAdapter printAdapter = webView.createPrintDocumentAdapter(); @@ -132,10 +183,43 @@ public class Printer extends CordovaPlugin { // Get a print builder instance PrintAttributes.Builder builder = new PrintAttributes.Builder(); + // The page does itself set its own margins builder.setMinMargins(PrintAttributes.Margins.NO_MARGINS); + builder.setColorMode(graystyle ? PrintAttributes.COLOR_MODE_MONOCHROME + : PrintAttributes.COLOR_MODE_COLOR); + + builder.setMediaSize(landscape ? PrintAttributes.MediaSize.UNKNOWN_LANDSCAPE + : PrintAttributes.MediaSize.UNKNOWN_PORTRAIT); + // Create a print job with name and adapter instance - printManager.print("Print Document", printAdapter, builder.build()); + PrintJob job = printManager.print(docName, printAdapter, builder.build()); + + invokeCallbackOnceCompletedOrCanceled(job); + + view = null; + } + }); + } + + /** + * Invokes the callback once the print job is complete or was canceled. + * + * @param job + * The reference to the print job + */ + private void invokeCallbackOnceCompletedOrCanceled (final PrintJob job) { + cordova.getThreadPool().execute(new Runnable() { + @Override + public void run() { + Looper.prepare(); + + for (;;) { + if (job.isCancelled() || job.isCompleted() || job.isFailed()) { + command.success(); + break; + } + } } }); } From 9017b62b040cd02e73a43ede8af45dcedc497c4f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Katzer?= Date: Thu, 11 Sep 2014 23:27:17 +0200 Subject: [PATCH 13/21] Update README about the URL feature --- README.md | 34 +++++++++++++++++++++++++++------- 1 file changed, 27 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 20c53b7..d6e6dd7 100644 --- a/README.md +++ b/README.md @@ -96,8 +96,10 @@ cordova plugin rm de.appplant.cordova.plugin.printer #### Version 0.7.0 (not yet released) - AirPrint support - Android Printing Framework support -- [__change__:] Renamed `isServiceAvailable` to `isAvailable`. -- [enhancement:] New print options like `name`, `landscape` or `duplex`. +- [__change__:] Renamed `isServiceAvailable` to `isAvailable` +- [enhancement:] New print options like `name`, `landscape` or `duplex` +- [enhancement:] Ability to print remote content via URI +- [enhancement:] Callback support #### Further informations - See [CHANGELOG.md][changelog] to get the full changelog for the plugin. @@ -146,7 +148,7 @@ cordova.plugins.printer.isAvailable( ### Send content to a printer Content can be send to a printer through the `printer.print` interface.
-The method takes a string or a HTML DOM node. Optional parameters allows to specify the name of the document and a callback. The callback will be called if the user cancels or completes the print job. +The method takes a string or a HTML DOM node. The string can contain HTML content or an URI pointing to another web page. Optional parameters allows to specify the name of the document and a callback. The callback will be called if the user cancels or completes the print job. #### Available Options | Name | Description | Type | Support | @@ -160,6 +162,7 @@ The method takes a string or a HTML DOM node. Optional parameters allows to spec #### Further informations - See the [isAvailable][available] method to find out if printing is available on the device. - All CSS rules needs to be embedded or accessible via absolute URLs in order to print out HTML encoded content. +- The string can contain HTML content or an URI pointing to another web page. - See the [examples][examples] to get an overview on how to use the plugin. ```javascript @@ -185,15 +188,25 @@ __NOTE:__ All CSS rules needs to be embedded or accessible via absolute URLs in #### 1. Print the whole HTML page ```javascript -// Either a DOM node or a string -var page = document.body; +// URI for the index.html +var page = location.href; cordova.plugins.printer.print(page, 'Document.html', function () { alert('printing finished or canceled') }); ``` -#### 2. Print custom specific content +#### 1. Print the content of a part of the page +```javascript +// Either a DOM node or a string +var page = document.getElementById('legal-notice'); + +cordova.plugins.printer.print(page, 'Document.html', function () { + alert('printing finished or canceled') +}); +``` + +#### 3. Print custom specific content ```javascript // Either a DOM node or a string var page = '

Hello Document

'; @@ -203,7 +216,14 @@ cordova.plugins.printer.print(page, 'Document.html', function () { }); ``` -#### 3. Adjust the page +#### 4. Print remote web page +```javascript +cordova.plugins.printer.print('http://blackberry.de', 'BB!!!', function () { + alert('printing finished or canceled') +}); +``` + +#### 5. Adjust the page ```javascript cordova.plugins.printer.print('123', { name:'Document.html', landscape:true }, function () { alert('printing finished or canceled') From 887edb94b19cfd6c955b30e96f658a36408a936e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Katzer?= Date: Thu, 11 Sep 2014 23:29:35 +0200 Subject: [PATCH 14/21] Update CHANGELOG.md --- CHANGELOG.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index adef259..44e3705 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,5 +2,7 @@ #### Version 0.7.0 (not yet released) - AirPrint support - Android Printing Framework support -- [__change__:] Renamed `isServiceAvailable` to `isAvailable`. -- [enhancement:] New print options like `name`, `landscape` or `duplex`. \ No newline at end of file +- [__change__:] Renamed `isServiceAvailable` to `isAvailable` +- [enhancement:] New print options like `name`, `landscape` or `duplex` +- [enhancement:] Ability to print remote content via URI +- [enhancement:] Callback support \ No newline at end of file From 4be468dc9d780e45826c002c6fbbf6ffe86159f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Katzer?= Date: Thu, 11 Sep 2014 23:39:21 +0200 Subject: [PATCH 15/21] Update README.md Fix html issue --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index d6e6dd7..89b02e6 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@

- master + master   v0.6   @@ -286,4 +286,4 @@ This software is released under the [Apache 2.0 License][apache2_license]. [examples]: #examples [apache2_license]: http://opensource.org/licenses/Apache-2.0 [katzer]: katzer@appplant.de -[appplant]: www.appplant.de \ No newline at end of file +[appplant]: www.appplant.de From 2fbb039cd4b84fd99da0191eb31b7fb2dff6bd1c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Katzer?= Date: Fri, 12 Sep 2014 10:35:54 +0200 Subject: [PATCH 16/21] Some styling --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 89b02e6..5981afe 100644 --- a/README.md +++ b/README.md @@ -10,9 +10,9 @@ Cordova Print Plugin ==================== -[Cordova][cordova] plugin to print HTML documents using [AirPrint][AirPrint] for iOS and [Android Printing Framework][APF] for Android KitKat and above. +[Cordova][cordova] plugin to print HTML documents using [AirPrint][AirPrint] and [Android Printing Framework][APF]. -__Choose the right branch for you!__ +:bangbang: __Choose the right branch for you!__ :bangbang: The plugin provides multiple branches to support different printer types and android versions while _AirPrint_ is supported with each one. This is the _master_ branch. @@ -55,7 +55,7 @@ See [Drawing and Printing Guide for iOS][ios_guide] for detailed informations an ## Installation -The plugin can either be installed from git repository, from local file system through the [Command-line Interface][CLI] or cloud based through [PhoneGap Build][PGB]. +The plugin can either be installed from git repository, from local file system through the [Command-line Interface][CLI]. Or cloud based through [PhoneGap Build][PGB]. ### Local development environment From master: @@ -196,7 +196,7 @@ cordova.plugins.printer.print(page, 'Document.html', function () { }); ``` -#### 1. Print the content of a part of the page +#### 2. Print the content from a part of the page ```javascript // Either a DOM node or a string var page = document.getElementById('legal-notice'); From 15870f8a4e0af16ef5f24907c8c8cf2198fce568 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Katzer?= Date: Fri, 12 Sep 2014 10:41:44 +0200 Subject: [PATCH 17/21] Styling --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 5981afe..049193f 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ Cordova Print Plugin ==================== -[Cordova][cordova] plugin to print HTML documents using [AirPrint][AirPrint] and [Android Printing Framework][APF]. +[Cordova][cordova] plugin to print HTML documents using [__AirPrint__][AirPrint] and [__Android Printing Framework__][APF]. :bangbang: __Choose the right branch for you!__ :bangbang: From 5493c652fd299d9142c6c3534a15f8df38421c7f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Katzer?= Date: Fri, 12 Sep 2014 10:53:44 +0200 Subject: [PATCH 18/21] `isAvailable` does not block the main thread anymore --- CHANGELOG.md | 3 ++- README.md | 1 + src/ios/APPPrinter.m | 14 ++++++++------ 3 files changed, 11 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 44e3705..787a77c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,4 +5,5 @@ - [__change__:] Renamed `isServiceAvailable` to `isAvailable` - [enhancement:] New print options like `name`, `landscape` or `duplex` - [enhancement:] Ability to print remote content via URI -- [enhancement:] Callback support \ No newline at end of file +- [enhancement:] Callback support +- [bugfix:] `isAvailable` does not block the main thread anymore. \ No newline at end of file diff --git a/README.md b/README.md index 049193f..1589c11 100644 --- a/README.md +++ b/README.md @@ -100,6 +100,7 @@ cordova plugin rm de.appplant.cordova.plugin.printer - [enhancement:] New print options like `name`, `landscape` or `duplex` - [enhancement:] Ability to print remote content via URI - [enhancement:] Callback support +- [bugfix:] `isAvailable` does not block the main thread anymore. #### Further informations - See [CHANGELOG.md][changelog] to get the full changelog for the plugin. diff --git a/src/ios/APPPrinter.m b/src/ios/APPPrinter.m index 9056a66..80ab2ef 100755 --- a/src/ios/APPPrinter.m +++ b/src/ios/APPPrinter.m @@ -38,14 +38,16 @@ */ - (void) isAvailable:(CDVInvokedUrlCommand*)command { - CDVPluginResult* pluginResult; - BOOL isAvailable = [self isPrintingAvailable]; + [self.commandDelegate runInBackground:^{ + CDVPluginResult* pluginResult; + BOOL isAvailable = [self isPrintingAvailable]; - pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK - messageAsBool:isAvailable]; + pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK + messageAsBool:isAvailable]; - [self.commandDelegate sendPluginResult:pluginResult - callbackId:command.callbackId]; + [self.commandDelegate sendPluginResult:pluginResult + callbackId:command.callbackId]; + }]; } /** From 423aba70a7d40efd223f8f22b83b4eb730ee33fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Katzer?= Date: Fri, 12 Sep 2014 10:57:09 +0200 Subject: [PATCH 19/21] AirPrint support was there before --- CHANGELOG.md | 1 - README.md | 1 - 2 files changed, 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 787a77c..8a2068f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,5 @@ ## ChangeLog #### Version 0.7.0 (not yet released) -- AirPrint support - Android Printing Framework support - [__change__:] Renamed `isServiceAvailable` to `isAvailable` - [enhancement:] New print options like `name`, `landscape` or `duplex` diff --git a/README.md b/README.md index 1589c11..8eb4af7 100644 --- a/README.md +++ b/README.md @@ -94,7 +94,6 @@ cordova plugin rm de.appplant.cordova.plugin.printer ## ChangeLog #### Version 0.7.0 (not yet released) -- AirPrint support - Android Printing Framework support - [__change__:] Renamed `isServiceAvailable` to `isAvailable` - [enhancement:] New print options like `name`, `landscape` or `duplex` From b6f13a695c1299b44e6416ca4fda37047fe6b4fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Katzer?= Date: Fri, 12 Sep 2014 11:03:14 +0200 Subject: [PATCH 20/21] Change name and description in plugin spec --- plugin.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugin.xml b/plugin.xml index 8e2419f..004351d 100644 --- a/plugin.xml +++ b/plugin.xml @@ -5,10 +5,10 @@ id="de.appplant.cordova.plugin.printer" version="0.7.0-dev"> - AirPrint and Android Printing Framework + AirPrint and Android Printing Framework Plugin - Cordova plugin to print HTML documents using AirPrint for iOS + Cordova plugin to print HTML documents using AirPrint and Android Printing Framework. From 51c73a6ba48ca6bc5d2d7d92afadfa1036dadc74 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Katzer?= Date: Fri, 12 Sep 2014 11:28:52 +0200 Subject: [PATCH 21/21] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 8eb4af7..2993221 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ Cordova Print Plugin :bangbang: __Choose the right branch for you!__ :bangbang: -The plugin provides multiple branches to support different printer types and android versions while _AirPrint_ is supported with each one. This is the _master_ branch. +The plugin provides multiple branches to support different printer types and android versions while _AirPrint_ is supported with each one. - [master Branch][master_branch] for iOS and Android >= 4.4 (>= v0.7.x) - [google-cloud-print Branch][google-cloud-print_branch] for Android <= 4.3 (~> v0.6.x)