Печать специальных символов на принтере Bluetooth - PullRequest
0 голосов
/ 06 января 2020

У меня есть приложение, в котором я могу печатать на bluetooth-принтере Zebra ZQ320, но у меня есть некоторые проблемы с указанием c символов, единственная вещь в проекте, связанная с настройкой принтера, это класс, называемый " UtileriaImpresion ", в которой добавлена ​​конфигурация для зебры IMZ320 - ранее использовавшаяся модель, которая представляла ту же проблему.

enter image description here

Класс UtileriaImpresion

package com.hdi.ajustadormovil.utilidades;
import android.bluetooth.BluetoothAdapter;
import android.content.Context;
import android.content.SharedPreferences;
import android.os.Looper;
import android.util.Log;
import android.widget.Toast;
import com.hdi.ajustadormovil.R;
import com.hdi.ajustadormovil.actividades.ImpresoraNoEncontradaException;
import com.hdi.ajustadormovil.unicos.PersistenciaUnico;
import com.zebra.sdk.comm.BluetoothConnection;
import com.zebra.sdk.comm.Connection;
import com.zebra.sdk.comm.ConnectionException;
import org.riversun.finbin.BigBinarySearcher;
import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;


public class UtileriaImpresion {

/**
 * Tag para el debug de Android.
 */
private static final String tag = UtileriaImpresion.class.getName();

/**
 * Ejecuta un hilo secundario donde se intenta imprimir el vale indicado.
 *
 * @param context    Contexto actual de la aplicación.
 * @param parametros Mapa con los parámetros a reemplazar en el ticket.
 * @param archivo    Indica el nombre del archivo en los Assets.
 * @param mac        Dirección mac de la impresora a la que se debe conectar.
 */
public static void imprimir(final Context context, final Map<String, String> parametros, final String archivo, final String mac) {

    Log.v(tag, "imprimir");


    BluetoothAdapter ba = BluetoothAdapter.getDefaultAdapter();

    if (ba == null) {

        Toast.makeText(context, R.string.encienda_bluetooth, Toast.LENGTH_SHORT).show();
        return;

    }

    if (!ba.isEnabled()) {

        Toast.makeText(context, R.string.encienda_bluetooth, Toast.LENGTH_SHORT).show();
        return;

    }

    new Thread(new Runnable() {

        @Override
        public void run() {

            Looper.prepare();
            Connection cnn = null;

            try {

                byte[] bytes = UtileriaImpresion.obtenerBytesTemplateImpresion(context, archivo, parametros);
                cnn = new BluetoothConnection(mac);
                cnn.open();
                cnn.write(bytes);
                Toast.makeText(context, R.string.impresion_terminada, Toast.LENGTH_LONG).show();
                Log.i(tag, "Impresión terminada");

            } catch (ConnectionException cex) {

                Log.e(tag, "imprimir", cex);
                PersistenciaUnico.obtenerInstancia().guardarLog(tag, PersistenciaUnico.nivel.error, "", cex.getMessage() != null ? cex.getMessage() : "No se generó mensaje descriptivo para la excepción");
                Toast.makeText(context, R.string.impresora_no_conectada, Toast.LENGTH_LONG).show();

            } catch (Exception ex) {

                Log.e(tag, "imprimir", ex);
                PersistenciaUnico.obtenerInstancia().guardarLog(tag, PersistenciaUnico.nivel.error, "", ex.getMessage() != null ? ex.getMessage() : "No se generó mensaje descriptivo para la excepción", "Ninguno");
                Toast.makeText(context, R.string.error_impresion, Toast.LENGTH_LONG).show();

            } finally {

                if (cnn != null && cnn.isConnected()) {

                    try {

                        cnn.close();

                    } catch (ConnectionException cex) {

                        Log.e(tag, "imprimir", cex);
                        PersistenciaUnico.obtenerInstancia().guardarLog(tag, PersistenciaUnico.nivel.error, "", cex.getMessage() != null ? cex.getMessage() : "No se generó mensaje descriptivo para la excepción", "Ninguno");

                    }

                }

                Looper.loop();
                Looper looper;
                looper = Looper.myLooper();

                if (looper != null) {

                    looper.quit();

                }

            }

        }

    }).start();

}

/**
 * Lee el archivo especificado de los assets de la aplicación, reemplaza los
 * parámetros indicados y genera el arreglo de bytes resultate listo para
 * mandar a la impresora.
 *
 * @param context       Contexto actual de la aplicación.
 * @param nombreArchivo Nombre de archivo (con extención) en assets de la aplicación.
 * @param parametros    Mapa con los parámetros a sustituir en el archivo.
 * @return Arreglo de bytes que contiene el archivo leído y los parámetros
 * indicados.
 * @throws IOException Si no se pudo abrir el archivo por alguna razón.
 */
public static byte[] obtenerBytesTemplateImpresion(Context context, String nombreArchivo, Map<String, String> parametros) throws IOException {

    InputStream in = context.getAssets().open(nombreArchivo);
    byte[] bytes = new byte[in.available()];
    in.read(bytes);
    in.close();

    BigBinarySearcher searcher = new BigBinarySearcher();

    for (Map.Entry<String, String> parametro : parametros.entrySet()) {

        byte[] bytesKey = parametro.getKey().getBytes();
        int indice = searcher.indexOf(bytes, bytesKey);

        if (indice >= 0) {

            byte[] respaldoIzquierda = Arrays.copyOfRange(bytes, 0, indice);
            byte[] respaldoDerecha = Arrays.copyOfRange(bytes, indice + bytesKey.length + 1, bytes.length);
            byte[] bytesValue = parametro.getValue().getBytes();
            ByteBuffer buffer = ByteBuffer.allocate(respaldoIzquierda.length + bytesValue.length + respaldoDerecha.length);
            // Se agregan los bytes de la izquierda.
            buffer.put(respaldoIzquierda);
            // Se agregan los bytes de medio.
            buffer.put(bytesValue);
            // Se agregan los bytes del final.
            buffer.put(respaldoDerecha);
            // Se reemplaza el array orignal.
            bytes = buffer.array();

        }

    }

    return bytes;

}

/**
 * Obtiene la impresora que se configuró como predeterminada en las
 * preferencias del sistema.
 *
 * @param context Contexto actual de la aplicación.
 * @return Cadena de texto que contiene la dirección mac, si la cadena esta
 * vacía o es nula se puede considerar que no se ha configurado la
 * impresora.
 * @throws ImpresoraNoEncontradaException Si no se ha encontrado la configuración de la impresora
 *                                        predeterminada.
 */
public static String obtenerDireccionMacImpresora(Context context) throws ImpresoraNoEncontradaException {

    SharedPreferences sp = context.getSharedPreferences(context.getPackageName(), Context.MODE_PRIVATE);
    String mac = sp.getString(Constantes.SHARED_PREFERENCES_IMPRESORA, "");

    if (mac.length() == 0) {

        throw new ImpresoraNoEncontradaException("No se ha encontrado la impresora predeterminada, por favor configure alguna");

    }

    return mac;

}

/**
 * Establece un centrado relativo del texto indicado de acuerdo a la letra
 * que se utiliza por defecto en la impresora zebra IMZ320 (Zebra Times 5.0
 * de 8.5 Pt) para imprimir los campos.
 * </p>
 * El centrado se hace llenando con espacios en blanco el lado izquierdo del
 * texto, teniendo en cuenta que por renglón y en dicha fuente, la impresora
 * puede pintar 48 caracteres.
 *
 * @param texto Texto a centrar.
 * @return Nueva cadena de texto que contiene el centrado relativo.
 */
public static String centrarTexto(String texto) {

    // Variable que indica el límite de caracteres que caben en una línea.
    int limite = 48;

    if (StringUtilities.isEmptyOrNull(texto)) {

        return texto;

    }

    if (!texto.matches("[0-9]+")) {

        if (StringUtilities.isAllUpper(texto) || StringUtilities.cantidadMayusculasContinuas(texto, 5)) {

            limite = 35;

        }

    }

    if (texto.length() == limite) {

        return texto;

    }

    int espacios;
    espacios = (limite - texto.length()) / 2;
    espacios = Double.valueOf(espacios * 1.8).intValue();
    return StringUtilities.padLeft(texto, espacios + texto.length());

}

/**
 * Descompone el texto indicado en diferentes renglones teniendo en cuenta
 * que cada renglón puede tener un máximo de 48 caractéres en minúscula y 30
 * en mayúscula.
 *
 * @param texto Cadena de texto.
 * @return Lista de cadenas de texto.
 * @throws NullPointerException Si el parámetro texto es nulo.
 */
public static List<String> obtenerRenglones(String texto) throws NullPointerException {

    // Variable que indica el límite de caracteres que caben en una línea.
    int limite = 48;

    if (texto == null) {

        throw new NullPointerException("El parámetro texto no debe ser nulo");

    }

    if (StringUtilities.isAllUpper(texto) || StringUtilities.cantidadMayusculasContinuas(texto, 5)) {

        limite = 35;

    }

    if (texto.trim().length() <= limite) {

        List<String> lst = new ArrayList<>();
        lst.add(texto);
        return lst;

    }

    texto += " |";
    String[] partes = texto.split(" ");
    List<String> resultado = new ArrayList<>();
    StringBuilder renglon = new StringBuilder();

    for (int i = 0; i < partes.length - 1; i++) {

        renglon.append(partes[i]);

        if (renglon.length() + 1 + partes[i + 1].length() > limite) {

            resultado.add(renglon.toString().trim());
            renglon = new StringBuilder();

        } else {

            renglon.append(" ");

        }

    }

    resultado.add(renglon.toString().trim());
    return resultado;
  }
}

1 Ответ

1 голос
/ 06 января 2020

Без дополнительной информации или без какого-либо кода, который выглядит как UTF-8, напечатанный как ISO-8859-1. В ZPL необходимо настроить принтер на использование UTF-8 через ^CI28.

...