Add KitKat support - requires Android SDK 19 or higher

This commit is contained in:
Sebastián Katzer 2013-12-15 11:09:02 +01:00
parent 51625b6d4b
commit b74d9f1825
5 changed files with 52 additions and 425 deletions

View File

@ -9,11 +9,7 @@ by Sebastián Katzer ([github.com/katzer](https://github.com/katzer))
- **iOS** *(Print from iOS devices to AirPrint compatible printers)*<br>
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<br>
@ -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

View File

@ -9,7 +9,7 @@
<description>A bunch of printig plugins for Cordova 3.x.x</description>
<repo>https://github.com/katzer/cordova-plugin-printer.git</repo>
<keywords>print, printer, ios, android</keywords>
<keywords>print, printer, ios, android, kitkat</keywords>
<license>Apache 2.0</license>
<author>Sebastián Katzer</author>
@ -51,7 +51,6 @@
</config-file>
<source-file src="src/android/Printer.java" target-dir="src/de/appplant/cordova/plugin/printer" />
<source-file src="src/android/KitKatPrinter.java" target-dir="src/de/appplant/cordova/plugin/printer" />
</platform>
</plugin>

View File

@ -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, "<html></html>");
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());
}
});
}
}

View File

@ -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);
if (appId == null) {
self.ctx.success(4);
return;
};
String content = args.optString(0, "<html></html>");
Intent controller = self.getPrintController(appId);
WebView controller = self.getPrintController();
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);
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;
}
} catch (PackageManager.NameNotFoundException e) {}
private void startPrinterApp (WebView webview) {
webview.setWebViewClient (new WebViewClient() {
public boolean shouldOverrideUrlLoading (WebView view, String url) {
return false;
}
/**
* Die IDs aller verfügbaren Drucker-Apps.
*/
private JSONArray getInstalledAppIds () {
JSONArray appIds = new JSONArray();
public void onPageFinished (WebView webview, String url) {
// Get a PrintManager instance
PrintManager printManager = (PrintManager) cordova.getActivity()
.getSystemService(Context.PRINT_SERVICE);
for (int i = 0; i < printAppIds.length; i++) {
String appId = printAppIds[i];
Boolean isInstalled = this.isAppInstalled(appId);
// Get a print adapter instance
PrintDocumentAdapter printAdapter = webView.createPrintDocumentAdapter();
if (isInstalled){
appIds.put(appId);
}
}
// Get a print builder instance
PrintAttributes.Builder builder = new PrintAttributes.Builder();
return appIds;
}
builder.setMinMargins(PrintAttributes.Margins.NO_MARGINS);
/**
* 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;
// Create a print job with name and adapter instance
printManager.print("Print Document", printAdapter, builder.build());
}
});
}
}

View File

@ -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', []);
};
},
/**
@ -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]);
};
}
};