Fix missing callback with result on Android

This commit is contained in:
Sebastián Katzer 2019-02-04 11:43:51 +01:00
parent 49ad2187df
commit d74bd6c4b6
9 changed files with 267 additions and 93 deletions

View File

@ -1,26 +1,24 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<!-- <!--
* Copyright (c) 2013-2016 by appPlant GmbH. All rights reserved. Copyright 2013 Sebastián Katzer
*
* @APPPLANT_LICENSE_HEADER_START@ Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* This file contains Original Code and/or Modifications of Original Code distributed with this work for additional information
* as defined in and that are subject to the Apache License regarding copyright ownership. The ASF licenses this file
* Version 2.0 (the 'License'). You may not use this file except in to you under the Apache License, Version 2.0 (the
* compliance with the License. Please obtain a copy of the License at "License"); you may not use this file except in compliance
* http://opensource.org/licenses/Apache-2.0/ and read it before using this with the License. You may obtain a copy of the License at
* file.
* http://www.apache.org/licenses/LICENSE-2.0
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER Unless required by applicable law or agreed to in writing,
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, software distributed under the License is distributed on an
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. KIND, either express or implied. See the License for the
* Please see the License for the specific language governing rights and specific language governing permissions and limitations
* limitations under the License. under the License.
*
* @APPPLANT_LICENSE_HEADER_END@
--> -->
<plugin id="cordova-plugin-printer" <plugin id="cordova-plugin-printer"
@ -115,6 +113,9 @@
<source-file src="src/android/PrintOptions.java" <source-file src="src/android/PrintOptions.java"
target-dir="src/de/appplant/cordova/plugin/printer" /> target-dir="src/de/appplant/cordova/plugin/printer" />
<source-file src="src/android/PrintProxy.java"
target-dir="src/de/appplant/cordova/plugin/printer" />
</platform> </platform>
<!-- windows --> <!-- windows -->

View File

@ -1,4 +1,6 @@
/* /*
Copyright 2013 Sebastián Katzer
Licensed to the Apache Software Foundation (ASF) under one Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file or more contributor license agreements. See the NOTICE file
distributed with this work for additional information distributed with this work for additional information
@ -27,7 +29,6 @@ import android.print.PrintAttributes;
import android.print.PrintDocumentAdapter; import android.print.PrintDocumentAdapter;
import android.print.PrintDocumentInfo; import android.print.PrintDocumentInfo;
import android.support.annotation.NonNull; import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.print.PrintHelper; import android.support.v4.print.PrintHelper;
import java.io.FileOutputStream; import java.io.FileOutputStream;
@ -49,7 +50,7 @@ class PrintAdapter extends PrintDocumentAdapter {
private final @NonNull InputStream input; private final @NonNull InputStream input;
// The callback to inform once the job is done // The callback to inform once the job is done
private final @Nullable PrintHelper.OnPrintFinishCallback callback; private final @NonNull PrintHelper.OnPrintFinishCallback callback;
/** /**
* Constructor * Constructor
@ -59,7 +60,7 @@ class PrintAdapter extends PrintDocumentAdapter {
* @param callback The callback to inform once the job is done. * @param callback The callback to inform once the job is done.
*/ */
PrintAdapter (@NonNull String jobName, @NonNull InputStream input, PrintAdapter (@NonNull String jobName, @NonNull InputStream input,
@Nullable PrintHelper.OnPrintFinishCallback callback) @NonNull PrintHelper.OnPrintFinishCallback callback)
{ {
this.jobName = jobName; this.jobName = jobName;
this.input = input; this.input = input;
@ -109,7 +110,7 @@ class PrintAdapter extends PrintDocumentAdapter {
} }
/** /**
* Close input stream once the printing is done. * Closes the input stream and invokes the callback.
*/ */
@Override @Override
public void onFinish () public void onFinish ()
@ -118,8 +119,6 @@ class PrintAdapter extends PrintDocumentAdapter {
PrintContent.close(input); PrintContent.close(input);
if (callback != null) {
callback.onFinish(); callback.onFinish();
} }
}
} }

View File

@ -1,4 +1,6 @@
/* /*
Copyright 2013 Sebastián Katzer
Licensed to the Apache Software Foundation (ASF) under one Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file or more contributor license agreements. See the NOTICE file
distributed with this work for additional information distributed with this work for additional information

View File

@ -1,5 +1,5 @@
/* /*
Copyright 2013-2016 appPlant GmbH Copyright 2013 Sebastián Katzer
Licensed to the Apache Software Foundation (ASF) under one Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file or more contributor license agreements. See the NOTICE file
@ -26,6 +26,7 @@ import android.content.Context;
import android.graphics.Bitmap; import android.graphics.Bitmap;
import android.print.PrintAttributes; import android.print.PrintAttributes;
import android.print.PrintDocumentAdapter; import android.print.PrintDocumentAdapter;
import android.print.PrintJob;
import android.support.annotation.NonNull; import android.support.annotation.NonNull;
import android.support.annotation.Nullable; import android.support.annotation.Nullable;
import android.support.v4.print.PrintHelper; import android.support.v4.print.PrintHelper;
@ -41,10 +42,15 @@ import java.io.InputStream;
import static android.content.Context.PRINT_SERVICE; import static android.content.Context.PRINT_SERVICE;
import static android.os.Build.VERSION.SDK_INT; import static android.os.Build.VERSION.SDK_INT;
import static android.print.PrintJobInfo.STATE_COMPLETED;
import static de.appplant.cordova.plugin.printer.PrintContent.ContentType.UNSUPPORTED; import static de.appplant.cordova.plugin.printer.PrintContent.ContentType.UNSUPPORTED;
class PrintManager { class PrintManager {
interface OnPrintFinishCallback {
void onFinish (boolean completed);
}
// The application context // The application context
private final @NonNull Context context; private final @NonNull Context context;
@ -110,8 +116,7 @@ class PrintManager {
*/ */
@SuppressWarnings("ConstantConditions") @SuppressWarnings("ConstantConditions")
void print (@Nullable String content, @NonNull JSONObject settings, void print (@Nullable String content, @NonNull JSONObject settings,
@NonNull WebView view, @NonNull WebView view, @NonNull OnPrintFinishCallback callback)
@Nullable PrintHelper.OnPrintFinishCallback callback)
{ {
switch (PrintContent.getContentType(content, context)) switch (PrintContent.getContentType(content, context))
{ {
@ -123,26 +128,57 @@ class PrintManager {
break; break;
case HTML: case HTML:
if (content == null || content.isEmpty()) { if (content == null || content.isEmpty()) {
printWebView(view, settings); printWebView(view, settings, callback);
} else { } else {
printText(content, "text/html", settings); printHtml(content, settings, callback);
} }
break; break;
case UNSUPPORTED: case UNSUPPORTED:
// TODO unsupported content // TODO unsupported content
case PLAIN: case PLAIN:
printText(content, "text/plain", settings); printText(content, settings, callback);
} }
} }
/**
* Prints the HTML content.
*
* @param content The HTML text to print.
* @param settings Additional settings how to render the content.
* @param callback The function to invoke once the job is done.
*/
private void printHtml (@Nullable String content,
@NonNull JSONObject settings,
@NonNull OnPrintFinishCallback callback)
{
printContent(content, "text/html", settings, callback);
}
/**
* Prints the plain text content.
*
* @param content The plain text to print.
* @param settings Additional settings how to render the content.
* @param callback The function to invoke once the job is done.
*/
private void printText (@Nullable String content,
@NonNull JSONObject settings,
@NonNull OnPrintFinishCallback callback)
{
printContent(content, "text/plain", settings, callback);
}
/** /**
* Prints the markup content. * Prints the markup content.
* *
* @param content The HTML markup to print. * @param content The HTML markup to print.
* @param mimeType The mime type to render.
* @param settings Additional settings how to render the content. * @param settings Additional settings how to render the content.
* @param callback The function to invoke once the job is done.
*/ */
private void printText (@Nullable String content, @NonNull String mimeType, private void printContent (@Nullable String content, @NonNull String mimeType,
@NonNull JSONObject settings) @NonNull JSONObject settings,
@NonNull OnPrintFinishCallback callback)
{ {
((Activity) context).runOnUiThread(() -> { ((Activity) context).runOnUiThread(() -> {
view = this.createWebView(settings); view = this.createWebView(settings);
@ -155,7 +191,7 @@ class PrintManager {
@Override @Override
public void onPageFinished (WebView view, String url) { public void onPageFinished (WebView view, String url) {
printWebView(PrintManager.this.view, settings); printWebView(PrintManager.this.view, settings, callback);
PrintManager.this.view = null; PrintManager.this.view = null;
} }
}); });
@ -169,9 +205,11 @@ class PrintManager {
* *
* @param view The web view instance to print. * @param view The web view instance to print.
* @param settings Additional settings how to render the content. * @param settings Additional settings how to render the content.
* @param callback The function to invoke once the job is done.
*/ */
private void printWebView (@NonNull WebView view, private void printWebView (@NonNull WebView view,
@NonNull JSONObject settings) @NonNull JSONObject settings,
@NonNull OnPrintFinishCallback callback)
{ {
PrintOptions options = new PrintOptions(settings); PrintOptions options = new PrintOptions(settings);
String jobName = options.getJobName(); String jobName = options.getJobName();
@ -185,7 +223,9 @@ class PrintManager {
adapter = view.createPrintDocumentAdapter(); adapter = view.createPrintDocumentAdapter();
} }
printAdapter(adapter, options); PrintProxy proxy = new PrintProxy(adapter, () -> callback.onFinish(isPrintJobCompleted(jobName)));
printAdapter(proxy, options);
}); });
} }
@ -197,7 +237,7 @@ class PrintManager {
* @param callback The function to invoke once the job is done. * @param callback The function to invoke once the job is done.
*/ */
private void printPdf (@NonNull String path, @NonNull JSONObject settings, private void printPdf (@NonNull String path, @NonNull JSONObject settings,
@Nullable PrintHelper.OnPrintFinishCallback callback) @NonNull OnPrintFinishCallback callback)
{ {
InputStream stream = PrintContent.open(path, context); InputStream stream = PrintContent.open(path, context);
@ -205,7 +245,7 @@ class PrintManager {
PrintOptions options = new PrintOptions(settings); PrintOptions options = new PrintOptions(settings);
String jobName = options.getJobName(); String jobName = options.getJobName();
PrintAdapter adapter = new PrintAdapter(jobName, stream, callback); PrintAdapter adapter = new PrintAdapter(jobName, stream, () -> callback.onFinish(isPrintJobCompleted(jobName)));
printAdapter(adapter, options); printAdapter(adapter, options);
} }
@ -233,7 +273,7 @@ class PrintManager {
* @param callback The function to invoke once the job is done. * @param callback The function to invoke once the job is done.
*/ */
private void printImage (@NonNull String path, @NonNull JSONObject settings, private void printImage (@NonNull String path, @NonNull JSONObject settings,
@Nullable PrintHelper.OnPrintFinishCallback callback) @NonNull OnPrintFinishCallback callback)
{ {
Bitmap bitmap = PrintContent.decode(path, context); Bitmap bitmap = PrintContent.decode(path, context);
@ -245,7 +285,7 @@ class PrintManager {
options.decoratePrintHelper(printer); options.decoratePrintHelper(printer);
printer.printBitmap(jobName, bitmap, callback); printer.printBitmap(jobName, bitmap, () -> callback.onFinish(isPrintJobCompleted(jobName)));
} }
/** /**
@ -283,6 +323,37 @@ class PrintManager {
return view; return view;
} }
/**
* Finds the print job by its name.
*
* @param jobName The name of the print job.
*
* @return null if it could not find any job with this label.
*/
@Nullable
private PrintJob findPrintJobByName (@NonNull String jobName)
{
for (PrintJob job : getPrintService().getPrintJobs()) {
if (job.getInfo().getLabel().equals(jobName)) {
return job;
}
}
return null;
}
/**
* Returns if the print job is done.
*
* @param jobName The name of the print job.
*/
private boolean isPrintJobCompleted (@NonNull String jobName)
{
PrintJob job = findPrintJobByName(jobName);
return (job == null || job.getInfo().getState() <= STATE_COMPLETED);
}
/** /**
* Returns the print service of the app. * Returns the print service of the app.
*/ */

View File

@ -1,4 +1,6 @@
/* /*
Copyright 2013 Sebastián Katzer
Licensed to the Apache Software Foundation (ASF) under one Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file or more contributor license agreements. See the NOTICE file
distributed with this work for additional information distributed with this work for additional information

View File

@ -0,0 +1,84 @@
/*
Copyright 2013 Sebastián Katzer
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 android.os.Bundle;
import android.os.CancellationSignal;
import android.os.ParcelFileDescriptor;
import android.print.PageRange;
import android.print.PrintAttributes;
import android.print.PrintDocumentAdapter;
import android.support.annotation.NonNull;
import android.support.v4.print.PrintHelper;
/**
* Simple delegate class to have access to the onFinish method.
*/
class PrintProxy extends PrintDocumentAdapter {
// Holds the delegate object
private final @NonNull PrintDocumentAdapter delegate;
// The callback to inform once the job is done
private final @NonNull PrintHelper.OnPrintFinishCallback callback;
/**
* Constructor
*
* @param adapter The real adapter.
* @param callback The callback to invoke once the printing is done.
*/
PrintProxy (@NonNull PrintDocumentAdapter adapter,
@NonNull PrintHelper.OnPrintFinishCallback callback)
{
this.delegate = adapter;
this.callback = callback;
}
@Override
public void onLayout (PrintAttributes oldAttributes,
PrintAttributes newAttributes,
CancellationSignal cancellationSignal,
LayoutResultCallback callback,
Bundle bundle)
{
delegate.onLayout(oldAttributes, newAttributes, cancellationSignal, callback, bundle);
}
@Override
public void onWrite (PageRange[] range,
ParcelFileDescriptor dest,
CancellationSignal cancellationSignal,
WriteResultCallback callback)
{
delegate.onWrite(range, dest, cancellationSignal, callback);
}
/**
* Invokes the callback.
*/
@Override
public void onFinish () {
super.onFinish();
callback.onFinish();
}
}

View File

@ -1,5 +1,5 @@
/* /*
Copyright 2013-2016 appPlant GmbH Copyright 2013 Sebastián Katzer
Licensed to the Apache Software Foundation (ASF) under one Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file or more contributor license agreements. See the NOTICE file
@ -21,12 +21,14 @@
package de.appplant.cordova.plugin.printer; package de.appplant.cordova.plugin.printer;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable; import android.support.annotation.Nullable;
import android.webkit.WebView; import android.webkit.WebView;
import org.apache.cordova.CallbackContext; import org.apache.cordova.CallbackContext;
import org.apache.cordova.CordovaPlugin; import org.apache.cordova.CordovaPlugin;
import org.apache.cordova.PluginResult; import org.apache.cordova.PluginResult;
import org.apache.cordova.PluginResult.Status;
import org.json.JSONArray; import org.json.JSONArray;
import org.json.JSONObject; import org.json.JSONObject;
@ -90,10 +92,7 @@ public class Printer extends CordovaPlugin {
PrintManager pm = new PrintManager(cordova.getContext()); PrintManager pm = new PrintManager(cordova.getContext());
boolean printable = pm.canPrintItem(item); boolean printable = pm.canPrintItem(item);
PluginResult res = new PluginResult( sendPluginResult(callback, printable);
PluginResult.Status.OK, printable);
callback.sendPluginResult(res);
}); });
} }
@ -108,7 +107,7 @@ public class Printer extends CordovaPlugin {
JSONArray utis = PrintManager.getPrintableUTIs(); JSONArray utis = PrintManager.getPrintableUTIs();
PluginResult res = new PluginResult( PluginResult res = new PluginResult(
PluginResult.Status.OK, utis); Status.OK, utis);
callback.sendPluginResult(res); callback.sendPluginResult(res);
}); });
@ -129,7 +128,21 @@ public class Printer extends CordovaPlugin {
PrintManager pm = new PrintManager(cordova.getContext()); PrintManager pm = new PrintManager(cordova.getContext());
WebView view = (WebView) webView.getView(); WebView view = (WebView) webView.getView();
pm.print(content, settings, view, callback::success); pm.print(content, settings, view, (boolean completed) -> sendPluginResult(callback, completed));
}); });
} }
/**
* Sends the result back to the client.
*
* @param callback The callback to invoke.
* @param value The argument to pass with.
*/
private void sendPluginResult (@NonNull CallbackContext callback,
boolean value)
{
PluginResult result = new PluginResult(Status.OK, value);
callback.sendPluginResult(result);
}
} }

View File

@ -1,7 +1,7 @@
/* globals Windows: true */ /* globals Windows: true */
/* /*
Copyright 2013-2016 appPlant GmbH Copyright 2013 Sebastián Katzer
Licensed to the Apache Software Foundation (ASF) under one Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file or more contributor license agreements. See the NOTICE file
@ -19,7 +19,7 @@
KIND, either express or implied. See the License for the KIND, either express or implied. See the License for the
specific language governing permissions and limitations specific language governing permissions and limitations
under the License. under the License.
*/ */
var Printing = Windows.Graphics.Printing, var Printing = Windows.Graphics.Printing,
PrintManager = Windows.Graphics.Printing.PrintManager; PrintManager = Windows.Graphics.Printing.PrintManager;

View File

@ -1,4 +1,6 @@
/* /*
Copyright 2013 Sebastián Katzer
Licensed to the Apache Software Foundation (ASF) under one Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file or more contributor license agreements. See the NOTICE file
distributed with this work for additional information distributed with this work for additional information