442 lines
12 KiB
Java
442 lines
12 KiB
Java
/*
|
|
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;
|
|
import java.net.URLConnection;
|
|
|
|
class PrintContent {
|
|
|
|
// List of supported content types
|
|
enum ContentType { PLAIN, HTML, IMAGE, PDF, UNSUPPORTED }
|
|
|
|
// Application context
|
|
private final @NonNull Context context;
|
|
|
|
/**
|
|
* Initializes the asset utils.
|
|
*
|
|
* @param ctx The application context.
|
|
*/
|
|
private PrintContent (@NonNull Context ctx) {
|
|
context = ctx;
|
|
}
|
|
|
|
/**
|
|
* Returns the content type for the file referenced by its uri.
|
|
*
|
|
* @param path The path to check.
|
|
*
|
|
* @return The content type even the file does not exist.
|
|
*/
|
|
@NonNull
|
|
static ContentType getContentType (@Nullable String path,
|
|
@NonNull Context context)
|
|
{
|
|
return new PrintContent(context).getContentType(path);
|
|
}
|
|
|
|
/**
|
|
* Returns the content type for the file referenced by its uri.
|
|
*
|
|
* @param path The path to check.
|
|
*
|
|
* @return The content type even the file does not exist.
|
|
*/
|
|
@NonNull
|
|
private ContentType getContentType (@Nullable String path)
|
|
{
|
|
ContentType type = ContentType.PLAIN;
|
|
|
|
if (path == null || path.isEmpty() || path.charAt(0) == '<')
|
|
{
|
|
type = ContentType.HTML;
|
|
}
|
|
else if (path.matches("^[a-z0-9]+://.+"))
|
|
{
|
|
String mime;
|
|
|
|
if (path.startsWith("base64:")) {
|
|
try {
|
|
mime = URLConnection.guessContentTypeFromStream(openBase64(path));
|
|
} catch (IOException e) {
|
|
return ContentType.UNSUPPORTED;
|
|
}
|
|
} else {
|
|
mime = URLConnection.guessContentTypeFromName(path);
|
|
}
|
|
|
|
switch (mime)
|
|
{
|
|
case "image/bmp":
|
|
case "image/png":
|
|
case "image/jpeg":
|
|
case "image/jpeg2000":
|
|
case "image/jp2":
|
|
case "image/gif":
|
|
case "image/x-icon":
|
|
case "image/vnd.microsoft.icon":
|
|
case "image/heif":
|
|
return ContentType.IMAGE;
|
|
case "application/pdf":
|
|
return ContentType.PDF;
|
|
default:
|
|
return ContentType.UNSUPPORTED;
|
|
}
|
|
}
|
|
|
|
return type;
|
|
}
|
|
|
|
/**
|
|
* Opens a file://, res:// or base64:// Uri as a stream.
|
|
*
|
|
* @param path The file path to decode.
|
|
* @param context The application context.
|
|
*
|
|
* @return An open IO stream or null if the file does not exist.
|
|
*/
|
|
@Nullable
|
|
static InputStream open (@NonNull String path, @NonNull Context context)
|
|
{
|
|
return new PrintContent(context).open(path);
|
|
}
|
|
|
|
/**
|
|
* Opens a file://, res:// or base64:// Uri as a stream.
|
|
*
|
|
* @param path The file path to decode.
|
|
*
|
|
* @return An open IO stream or null if the file does not exist.
|
|
*/
|
|
@Nullable
|
|
private InputStream open (@NonNull String path)
|
|
{
|
|
InputStream stream = null;
|
|
|
|
if (path.startsWith("res:"))
|
|
{
|
|
stream = openResource(path);
|
|
}
|
|
else if (path.startsWith("file:///"))
|
|
{
|
|
stream = openFile(path);
|
|
}
|
|
else if (path.startsWith("file://"))
|
|
{
|
|
stream = openAsset(path);
|
|
}
|
|
else if (path.startsWith("base64:"))
|
|
{
|
|
stream = openBase64(path);
|
|
}
|
|
|
|
return stream;
|
|
}
|
|
|
|
/**
|
|
* Decodes a file://, res:// or base64:// Uri to bitmap.
|
|
*
|
|
* @param path The file path to decode.
|
|
* @param context The application context.
|
|
*
|
|
* @return A bitmap or null if the path is not valid
|
|
*/
|
|
@Nullable
|
|
static Bitmap decode (@NonNull String path, @NonNull Context context)
|
|
{
|
|
return new PrintContent(context).decode(path);
|
|
}
|
|
|
|
/**
|
|
* Decodes a file://, res:// or base64:// Uri to bitmap.
|
|
*
|
|
* @param path The file path to decode.
|
|
*
|
|
* @return A bitmap or null if the path is not valid
|
|
*/
|
|
@Nullable
|
|
private Bitmap decode (@NonNull String path)
|
|
{
|
|
Bitmap bitmap;
|
|
|
|
if (path.startsWith("res:"))
|
|
{
|
|
bitmap = decodeResource(path);
|
|
}
|
|
else if (path.startsWith("file:///"))
|
|
{
|
|
bitmap = decodeFile(path);
|
|
}
|
|
else if (path.startsWith("file://"))
|
|
{
|
|
bitmap = decodeAsset(path);
|
|
}
|
|
else if (path.startsWith("base64:"))
|
|
{
|
|
bitmap = decodeBase64(path);
|
|
}
|
|
else {
|
|
bitmap = BitmapFactory.decodeFile(path);
|
|
}
|
|
|
|
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();
|
|
}
|
|
}
|