From 3cf978a0ffeed2c8338b558c6fc255bbc085ed39 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Katzer?= Date: Fri, 1 Mar 2019 11:46:50 +0100 Subject: [PATCH] Move io methods from PrintContent to PrintIO class and fix mark/reset not supported [fixes #204] --- plugin.xml | 3 + src/android/PrintAdapter.java | 8 +- src/android/PrintContent.java | 283 ++++------------------------------ src/android/PrintIO.java | 283 ++++++++++++++++++++++++++++++++++ src/android/PrintManager.java | 16 +- src/android/PrintOptions.java | 4 +- src/android/PrintProxy.java | 4 +- src/android/Printer.java | 4 +- 8 files changed, 338 insertions(+), 267 deletions(-) create mode 100644 src/android/PrintIO.java diff --git a/plugin.xml b/plugin.xml index 5146917..a267ea6 100644 --- a/plugin.xml +++ b/plugin.xml @@ -107,6 +107,9 @@ + + diff --git a/src/android/PrintAdapter.java b/src/android/PrintAdapter.java index 187f1ff..4c46df9 100644 --- a/src/android/PrintAdapter.java +++ b/src/android/PrintAdapter.java @@ -41,8 +41,8 @@ import static android.print.PrintDocumentInfo.CONTENT_TYPE_DOCUMENT; /** * Document adapter to render and print PDF files. */ -class PrintAdapter extends PrintDocumentAdapter { - +class PrintAdapter extends PrintDocumentAdapter +{ // The name of the print job private final @NonNull String jobName; @@ -107,7 +107,7 @@ class PrintAdapter extends PrintDocumentAdapter { OutputStream output = new FileOutputStream(dest.getFileDescriptor()); try { - PrintContent.copy(input, output); + PrintIO.copy(input, output); } catch (IOException e) { callback.onWriteFailed(e.getMessage()); return; @@ -124,7 +124,7 @@ class PrintAdapter extends PrintDocumentAdapter { { super.onFinish(); - PrintContent.close(input); + PrintIO.close(input); callback.onFinish(); } diff --git a/src/android/PrintContent.java b/src/android/PrintContent.java index 41ab594..ccf0ec4 100644 --- a/src/android/PrintContent.java +++ b/src/android/PrintContent.java @@ -22,30 +22,26 @@ package de.appplant.cordova.plugin.printer; import android.content.Context; -import android.content.res.AssetManager; -import android.content.res.Resources; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.support.annotation.NonNull; import android.support.annotation.Nullable; -import android.util.Base64; -import java.io.ByteArrayInputStream; -import java.io.Closeable; -import java.io.FileInputStream; -import java.io.FileNotFoundException; +import java.io.BufferedInputStream; import java.io.IOException; import java.io.InputStream; -import java.io.OutputStream; import java.net.URLConnection; -class PrintContent { - +/** + * Knows how to convert a resource URL into an io stream. + */ +class PrintContent +{ // List of supported content types enum ContentType { PLAIN, HTML, IMAGE, PDF, UNSUPPORTED } - // Application context - private final @NonNull Context context; + // Helper class to deal with io operations + private final @NonNull PrintIO io; /** * Initializes the asset utils. @@ -53,7 +49,7 @@ class PrintContent { * @param ctx The application context. */ private PrintContent (@NonNull Context ctx) { - context = ctx; + io = new PrintIO(ctx); } /** @@ -90,13 +86,19 @@ class PrintContent { { String mime; - if (path.startsWith("base64:")) { - try { - mime = URLConnection.guessContentTypeFromStream(openBase64(path)); - } catch (IOException e) { + if (path.startsWith("base64:")) + { + try + { + mime = URLConnection.guessContentTypeFromStream(io.openBase64(path)); + } + catch (IOException e) + { return ContentType.UNSUPPORTED; } - } else { + } + else + { mime = URLConnection.guessContentTypeFromName(path); } @@ -131,7 +133,8 @@ class PrintContent { * @return An open IO stream or null if the file does not exist. */ @Nullable - static InputStream open (@NonNull String path, @NonNull Context context) + static BufferedInputStream open (@NonNull String path, + @NonNull Context context) { return new PrintContent(context).open(path); } @@ -144,28 +147,28 @@ class PrintContent { * @return An open IO stream or null if the file does not exist. */ @Nullable - private InputStream open (@NonNull String path) + private BufferedInputStream open (@NonNull String path) { InputStream stream = null; if (path.startsWith("res:")) { - stream = openResource(path); + stream = io.openResource(path); } else if (path.startsWith("file:///")) { - stream = openFile(path); + stream = io.openFile(path); } else if (path.startsWith("file://")) { - stream = openAsset(path); + stream = io.openAsset(path); } else if (path.startsWith("base64:")) { - stream = openBase64(path); + stream = io.openBase64(path); } - return stream; + return stream != null ? new BufferedInputStream(stream) : null; } /** @@ -196,19 +199,19 @@ class PrintContent { if (path.startsWith("res:")) { - bitmap = decodeResource(path); + bitmap = io.decodeResource(path); } else if (path.startsWith("file:///")) { - bitmap = decodeFile(path); + bitmap = io.decodeFile(path); } else if (path.startsWith("file://")) { - bitmap = decodeAsset(path); + bitmap = io.decodeAsset(path); } else if (path.startsWith("base64:")) { - bitmap = decodeBase64(path); + bitmap = io.decodeBase64(path); } else { bitmap = BitmapFactory.decodeFile(path); @@ -216,226 +219,4 @@ class PrintContent { return bitmap; } - - /** - * Copies content of input stream to output stream. - * - * @param input The readable input stream. - * @param output The writable output stream. - * - * @throws IOException If the input stream is not readable, - * or the output stream is not writable. - */ - static void copy (@NonNull InputStream input, - @NonNull OutputStream output) throws IOException - { - byte[] buf = new byte[1024]; - int bytesRead; - - while ((bytesRead = input.read(buf)) > 0) { - output.write(buf, 0, bytesRead); - } - - input.reset(); - close(output); - } - - /** - * Closes the stream. - * - * @param stream The stream to close. - */ - static void close (@NonNull Closeable stream) - { - try { - stream.close(); - } catch (IOException e) { - // ignore - } - } - - /** - * Opens an file given as a file:/// path. - * - * @param path The path to the file. - * - * @return An open IO stream or null if the file does not exist. - */ - @Nullable - private InputStream openFile (@NonNull String path) - { - String absPath = path.substring(7); - - try { - return new FileInputStream(absPath); - } catch (FileNotFoundException e) { - return null; - } - } - - /** - * Decodes an file given as a file:/// path to a bitmap. - * - * @param path The path to the file. - * - * @return A bitmap or null if the path is not valid - */ - @Nullable - private Bitmap decodeFile (@NonNull String path) - { - String absPath = path.substring(7); - - return BitmapFactory.decodeFile(absPath); - } - - /** - * Opens an asset file given as a file:// path. - * - * @param path The path to the asset. - * - * @return An open IO stream or null if the file does not exist. - */ - @Nullable - private InputStream openAsset (@NonNull String path) - { - String resPath = path.replaceFirst("file:/", "www"); - - try { - return getAssets().open(resPath); - } catch (Exception e) { - return null; - } - } - - /** - * Decodes an asset file given as a file:// path to a bitmap. - * - * @param path The path to the asset. - * - * @return A bitmap or null if the path is not valid - */ - @Nullable - private Bitmap decodeAsset (@NonNull String path) - { - InputStream stream = openAsset(path); - Bitmap bitmap; - - if (stream == null) - return null; - - bitmap = BitmapFactory.decodeStream(stream); - - close(stream); - - return bitmap; - } - - /** - * Opens a resource file given as a res:// path. - * - * @param path The path to the resource. - * - * @return An open IO stream or null if the file does not exist. - */ - @NonNull - private InputStream openResource (@NonNull String path) - { - String resPath = path.substring(6); - int resId = getResId(resPath); - - return getResources().openRawResource(resId); - } - - /** - * Decodes a resource given as a res:// path to a bitmap. - * - * @param path The path to the resource. - * - * @return A bitmap or null if the path is not valid - */ - @Nullable - private Bitmap decodeResource (@NonNull String path) - { - String data = path.substring(9); - byte[] bytes = Base64.decode(data, 0); - - return BitmapFactory.decodeByteArray(bytes, 0, bytes.length); - } - - /** - * Opens a resource file given as a res:// path. - * - * @param path The path to the resource. - * - * @return An open IO stream or null if the file does not exist. - */ - @NonNull - private InputStream openBase64 (@NonNull String path) - { - String data = path.substring(9); - byte[] bytes = Base64.decode(data, 0); - - return new ByteArrayInputStream(bytes); - } - - /** - * Decodes a resource given as a base64:// string to a bitmap. - * - * @param path The given relative path. - * - * @return A bitmap or null if the path is not valid - */ - @Nullable - private Bitmap decodeBase64 (@NonNull String path) - { - String data = path.substring(9); - byte[] bytes = Base64.decode(data, 0); - - return BitmapFactory.decodeByteArray(bytes, 0, bytes.length); - } - - /** - * Returns the resource ID for the given resource path. - * - * @return The resource ID for the given resource. - */ - private int getResId (@NonNull String resPath) - { - Resources res = getResources(); - String pkgName = context.getPackageName(); - String dirName = "drawable"; - String fileName = resPath; - - if (resPath.contains("/")) { - dirName = resPath.substring(0, resPath.lastIndexOf('/')); - fileName = resPath.substring(resPath.lastIndexOf('/') + 1); - } - - String resName = fileName.substring(0, fileName.lastIndexOf('.')); - int resId = res.getIdentifier(resName, dirName, pkgName); - - if (resId == 0) { - resId = res.getIdentifier(resName, "mipmap", pkgName); - } - - if (resId == 0) { - resId = res.getIdentifier(resName, "drawable", pkgName); - } - - return resId; - } - - /** - * Returns the asset manager for the app. - */ - private AssetManager getAssets() { - return context.getAssets(); - } - - /** - * Returns the resource bundle for the app. - */ - private Resources getResources() { - return context.getResources(); - } } diff --git a/src/android/PrintIO.java b/src/android/PrintIO.java new file mode 100644 index 0000000..7c2fa25 --- /dev/null +++ b/src/android/PrintIO.java @@ -0,0 +1,283 @@ +/* + 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.content.Context; +import android.content.res.AssetManager; +import android.content.res.Resources; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.util.Base64; + +import java.io.ByteArrayInputStream; +import java.io.Closeable; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; + +/** + * Provides IO utility functions to deal with the resources. + */ +class PrintIO +{ + // Application context + private final @NonNull Context context; + + /** + * Initializes the asset utils. + * + * @param ctx The application context. + */ + PrintIO (@NonNull Context ctx) + { + context = ctx; + } + + /** + * Copies content of input stream to output stream. + * + * @param input The readable input stream. + * @param output The writable output stream. + * + * @throws IOException If the input stream is not readable, + * or the output stream is not writable. + */ + static void copy (@NonNull InputStream input, + @NonNull OutputStream output) throws IOException + { + byte[] buf = new byte[input.available()]; + int bytesRead; + + input.mark(Integer.MAX_VALUE); + + while ((bytesRead = input.read(buf)) > 0) + { + output.write(buf, 0, bytesRead); + } + + input.reset(); + close(output); + } + + /** + * Closes the stream. + * + * @param stream The stream to close. + */ + static void close (@NonNull Closeable stream) + { + try { + stream.close(); + } catch (IOException e) { + // ignore + } + } + + /** + * Opens an file given as a file:/// path. + * + * @param path The path to the file. + * + * @return An open IO stream or null if the file does not exist. + */ + @Nullable + InputStream openFile (@NonNull String path) + { + String absPath = path.substring(7); + + try { + return new FileInputStream(absPath); + } catch (FileNotFoundException e) { + return null; + } + } + + /** + * Decodes an file given as a file:/// path to a bitmap. + * + * @param path The path to the file. + * + * @return A bitmap or null if the path is not valid + */ + @Nullable + Bitmap decodeFile (@NonNull String path) + { + String absPath = path.substring(7); + + return BitmapFactory.decodeFile(absPath); + } + + /** + * Opens an asset file given as a file:// path. + * + * @param path The path to the asset. + * + * @return An open IO stream or null if the file does not exist. + */ + @Nullable + InputStream openAsset (@NonNull String path) + { + String resPath = path.replaceFirst("file:/", "www"); + + try { + return getAssets().open(resPath); + } catch (Exception e) { + return null; + } + } + + /** + * Decodes an asset file given as a file:// path to a bitmap. + * + * @param path The path to the asset. + * + * @return A bitmap or null if the path is not valid + */ + @Nullable + Bitmap decodeAsset (@NonNull String path) + { + InputStream stream = openAsset(path); + Bitmap bitmap; + + if (stream == null) + return null; + + bitmap = BitmapFactory.decodeStream(stream); + + close(stream); + + return bitmap; + } + + /** + * Opens a resource file given as a res:// path. + * + * @param path The path to the resource. + * + * @return An open IO stream or null if the file does not exist. + */ + @NonNull + InputStream openResource (@NonNull String path) + { + String resPath = path.substring(6); + int resId = getResId(resPath); + + return getResources().openRawResource(resId); + } + + /** + * Decodes a resource given as a res:// path to a bitmap. + * + * @param path The path to the resource. + * + * @return A bitmap or null if the path is not valid + */ + @Nullable + Bitmap decodeResource (@NonNull String path) + { + String data = path.substring(9); + byte[] bytes = Base64.decode(data, 0); + + return BitmapFactory.decodeByteArray(bytes, 0, bytes.length); + } + + /** + * Opens a resource file given as a res:// path. + * + * @param path The path to the resource. + * + * @return An open IO stream or null if the file does not exist. + */ + @NonNull + InputStream openBase64 (@NonNull String path) + { + String data = path.substring(9); + byte[] bytes = Base64.decode(data, 0); + + return new ByteArrayInputStream(bytes); + } + + /** + * Decodes a resource given as a base64:// string to a bitmap. + * + * @param path The given relative path. + * + * @return A bitmap or null if the path is not valid + */ + @Nullable + Bitmap decodeBase64 (@NonNull String path) + { + String data = path.substring(9); + byte[] bytes = Base64.decode(data, 0); + + return BitmapFactory.decodeByteArray(bytes, 0, bytes.length); + } + + /** + * Returns the resource ID for the given resource path. + * + * @return The resource ID for the given resource. + */ + private int getResId (@NonNull String resPath) + { + Resources res = getResources(); + String pkgName = context.getPackageName(); + String dirName = "drawable"; + String fileName = resPath; + + if (resPath.contains("/")) { + dirName = resPath.substring(0, resPath.lastIndexOf('/')); + fileName = resPath.substring(resPath.lastIndexOf('/') + 1); + } + + String resName = fileName.substring(0, fileName.lastIndexOf('.')); + int resId = res.getIdentifier(resName, dirName, pkgName); + + if (resId == 0) { + resId = res.getIdentifier(resName, "mipmap", pkgName); + } + + if (resId == 0) { + resId = res.getIdentifier(resName, "drawable", pkgName); + } + + return resId; + } + + /** + * Returns the asset manager for the app. + */ + private AssetManager getAssets() { + return context.getAssets(); + } + + /** + * Returns the resource bundle for the app. + */ + private Resources getResources() { + return context.getResources(); + } +} diff --git a/src/android/PrintManager.java b/src/android/PrintManager.java index 4e090a2..e0f7838 100644 --- a/src/android/PrintManager.java +++ b/src/android/PrintManager.java @@ -45,12 +45,11 @@ 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; -class PrintManager { - - interface OnPrintFinishCallback { - void onFinish (boolean completed); - } - +/** + * Provides high level methods for printing. + */ +class PrintManager +{ // The application context private final @NonNull Context context; @@ -363,4 +362,9 @@ class PrintManager { { return (android.print.PrintManager) context.getSystemService(PRINT_SERVICE); } + + interface OnPrintFinishCallback + { + void onFinish (boolean completed); + } } diff --git a/src/android/PrintOptions.java b/src/android/PrintOptions.java index e752e41..e5e19db 100644 --- a/src/android/PrintOptions.java +++ b/src/android/PrintOptions.java @@ -43,8 +43,8 @@ import static android.support.v4.print.PrintHelper.SCALE_MODE_FIT; /** * Wrapper for the print job settings. */ -class PrintOptions { - +class PrintOptions +{ // The print job settings private final @NonNull JSONObject spec; diff --git a/src/android/PrintProxy.java b/src/android/PrintProxy.java index b217622..f258c51 100644 --- a/src/android/PrintProxy.java +++ b/src/android/PrintProxy.java @@ -33,8 +33,8 @@ import android.support.v4.print.PrintHelper; /** * Simple delegate class to have access to the onFinish method. */ -class PrintProxy extends PrintDocumentAdapter { - +class PrintProxy extends PrintDocumentAdapter +{ // Holds the delegate object private final @NonNull PrintDocumentAdapter delegate; diff --git a/src/android/Printer.java b/src/android/Printer.java index afdf666..afb49bb 100644 --- a/src/android/Printer.java +++ b/src/android/Printer.java @@ -37,8 +37,8 @@ import org.json.JSONObject; * that loads the markup data. Once the page has been fully rendered it takes * the print adapter of that web view and initializes a print job. */ -public class Printer extends CordovaPlugin { - +public final class Printer extends CordovaPlugin +{ /** * Executes the request. *