Move io methods from PrintContent to PrintIO class and fix mark/reset not supported [fixes #204]

This commit is contained in:
Sebastián Katzer 2019-03-01 11:46:50 +01:00
parent 4bba693cd5
commit 3cf978a0ff
8 changed files with 338 additions and 267 deletions

View File

@ -107,6 +107,9 @@
<source-file src="src/android/Printer.java" <source-file src="src/android/Printer.java"
target-dir="src/de/appplant/cordova/plugin/printer" /> target-dir="src/de/appplant/cordova/plugin/printer" />
<source-file src="src/android/PrintIO.java"
target-dir="src/de/appplant/cordova/plugin/printer" />
<source-file src="src/android/PrintManager.java" <source-file src="src/android/PrintManager.java"
target-dir="src/de/appplant/cordova/plugin/printer" /> target-dir="src/de/appplant/cordova/plugin/printer" />

View File

@ -41,8 +41,8 @@ import static android.print.PrintDocumentInfo.CONTENT_TYPE_DOCUMENT;
/** /**
* Document adapter to render and print PDF files. * Document adapter to render and print PDF files.
*/ */
class PrintAdapter extends PrintDocumentAdapter { class PrintAdapter extends PrintDocumentAdapter
{
// The name of the print job // The name of the print job
private final @NonNull String jobName; private final @NonNull String jobName;
@ -107,7 +107,7 @@ class PrintAdapter extends PrintDocumentAdapter {
OutputStream output = new FileOutputStream(dest.getFileDescriptor()); OutputStream output = new FileOutputStream(dest.getFileDescriptor());
try { try {
PrintContent.copy(input, output); PrintIO.copy(input, output);
} catch (IOException e) { } catch (IOException e) {
callback.onWriteFailed(e.getMessage()); callback.onWriteFailed(e.getMessage());
return; return;
@ -124,7 +124,7 @@ class PrintAdapter extends PrintDocumentAdapter {
{ {
super.onFinish(); super.onFinish();
PrintContent.close(input); PrintIO.close(input);
callback.onFinish(); callback.onFinish();
} }

View File

@ -22,30 +22,26 @@
package de.appplant.cordova.plugin.printer; package de.appplant.cordova.plugin.printer;
import android.content.Context; import android.content.Context;
import android.content.res.AssetManager;
import android.content.res.Resources;
import android.graphics.Bitmap; import android.graphics.Bitmap;
import android.graphics.BitmapFactory; import android.graphics.BitmapFactory;
import android.support.annotation.NonNull; import android.support.annotation.NonNull;
import android.support.annotation.Nullable; import android.support.annotation.Nullable;
import android.util.Base64;
import java.io.ByteArrayInputStream; import java.io.BufferedInputStream;
import java.io.Closeable;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.OutputStream;
import java.net.URLConnection; import java.net.URLConnection;
class PrintContent { /**
* Knows how to convert a resource URL into an io stream.
*/
class PrintContent
{
// List of supported content types // List of supported content types
enum ContentType { PLAIN, HTML, IMAGE, PDF, UNSUPPORTED } enum ContentType { PLAIN, HTML, IMAGE, PDF, UNSUPPORTED }
// Application context // Helper class to deal with io operations
private final @NonNull Context context; private final @NonNull PrintIO io;
/** /**
* Initializes the asset utils. * Initializes the asset utils.
@ -53,7 +49,7 @@ class PrintContent {
* @param ctx The application context. * @param ctx The application context.
*/ */
private PrintContent (@NonNull Context ctx) { private PrintContent (@NonNull Context ctx) {
context = ctx; io = new PrintIO(ctx);
} }
/** /**
@ -90,13 +86,19 @@ class PrintContent {
{ {
String mime; String mime;
if (path.startsWith("base64:")) { if (path.startsWith("base64:"))
try { {
mime = URLConnection.guessContentTypeFromStream(openBase64(path)); try
} catch (IOException e) { {
mime = URLConnection.guessContentTypeFromStream(io.openBase64(path));
}
catch (IOException e)
{
return ContentType.UNSUPPORTED; return ContentType.UNSUPPORTED;
} }
} else { }
else
{
mime = URLConnection.guessContentTypeFromName(path); mime = URLConnection.guessContentTypeFromName(path);
} }
@ -131,7 +133,8 @@ class PrintContent {
* @return An open IO stream or null if the file does not exist. * @return An open IO stream or null if the file does not exist.
*/ */
@Nullable @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); 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. * @return An open IO stream or null if the file does not exist.
*/ */
@Nullable @Nullable
private InputStream open (@NonNull String path) private BufferedInputStream open (@NonNull String path)
{ {
InputStream stream = null; InputStream stream = null;
if (path.startsWith("res:")) if (path.startsWith("res:"))
{ {
stream = openResource(path); stream = io.openResource(path);
} }
else if (path.startsWith("file:///")) else if (path.startsWith("file:///"))
{ {
stream = openFile(path); stream = io.openFile(path);
} }
else if (path.startsWith("file://")) else if (path.startsWith("file://"))
{ {
stream = openAsset(path); stream = io.openAsset(path);
} }
else if (path.startsWith("base64:")) 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:")) if (path.startsWith("res:"))
{ {
bitmap = decodeResource(path); bitmap = io.decodeResource(path);
} }
else if (path.startsWith("file:///")) else if (path.startsWith("file:///"))
{ {
bitmap = decodeFile(path); bitmap = io.decodeFile(path);
} }
else if (path.startsWith("file://")) else if (path.startsWith("file://"))
{ {
bitmap = decodeAsset(path); bitmap = io.decodeAsset(path);
} }
else if (path.startsWith("base64:")) else if (path.startsWith("base64:"))
{ {
bitmap = decodeBase64(path); bitmap = io.decodeBase64(path);
} }
else { else {
bitmap = BitmapFactory.decodeFile(path); bitmap = BitmapFactory.decodeFile(path);
@ -216,226 +219,4 @@ class PrintContent {
return bitmap; 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();
}
} }

283
src/android/PrintIO.java Normal file
View File

@ -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();
}
}

View File

@ -45,12 +45,11 @@ import static android.os.Build.VERSION.SDK_INT;
import static android.print.PrintJobInfo.STATE_COMPLETED; 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 { /**
* Provides high level methods for printing.
interface OnPrintFinishCallback { */
void onFinish (boolean completed); class PrintManager
} {
// The application context // The application context
private final @NonNull Context context; private final @NonNull Context context;
@ -363,4 +362,9 @@ class PrintManager {
{ {
return (android.print.PrintManager) context.getSystemService(PRINT_SERVICE); return (android.print.PrintManager) context.getSystemService(PRINT_SERVICE);
} }
interface OnPrintFinishCallback
{
void onFinish (boolean completed);
}
} }

View File

@ -43,8 +43,8 @@ import static android.support.v4.print.PrintHelper.SCALE_MODE_FIT;
/** /**
* Wrapper for the print job settings. * Wrapper for the print job settings.
*/ */
class PrintOptions { class PrintOptions
{
// The print job settings // The print job settings
private final @NonNull JSONObject spec; private final @NonNull JSONObject spec;

View File

@ -33,8 +33,8 @@ import android.support.v4.print.PrintHelper;
/** /**
* Simple delegate class to have access to the onFinish method. * Simple delegate class to have access to the onFinish method.
*/ */
class PrintProxy extends PrintDocumentAdapter { class PrintProxy extends PrintDocumentAdapter
{
// Holds the delegate object // Holds the delegate object
private final @NonNull PrintDocumentAdapter delegate; private final @NonNull PrintDocumentAdapter delegate;

View File

@ -37,8 +37,8 @@ import org.json.JSONObject;
* that loads the markup data. Once the page has been fully rendered it takes * 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. * 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. * Executes the request.
* *