Most of the related answers and google contain pretty old contributions referring to this topic. So Im looking for a way to make my Android-Application print receipts (58 mm in width) via a bluetooth thermal receipt printer. Is it necessary to use a printer with a 3rd party API? I thought about to buy a regular bluetooth printer, that can be connected to my device and use the default Android print manager to make a layout for the receipt. Is that possible? Are there any samples, docs or tutorials? Would appreciate it. Thanks in advance
Asked
Active
Viewed 6,081 times
2 Answers
0
Yes, it's necesary to use a 3rd party SDK. I recommend you Zebra Printers, the have good documentation and code samples, that makes it easy compared to other brands. Download the SDK from here
To make your labels you can use ZebraDesigner that let you visualy create the layout and gives you as output ZPL code that you can send from your app to the Bluetooth printer. Click here to see it.

DanBreakingNews
- 11
- 2
- 6
-
Hi DanBreakingNews I need some hemp how to print my data to zebra printer also can I check for debug to save a temporary file on my sytem. – Rahul Vats May 28 '17 at 14:39
-
Hi you can see the example in my other answer above – DanBreakingNews May 28 '17 at 18:41
-
Hi Thanks for the reply, But actually I am creating android app for my client who has printer. How I can check the out put at my end by save it to a file or something like that for debugging. When its completed I can send apk to client to test on printer. Could you please share your contact email, so I can send you receipt example which I need to print. Please help me I am stuck on this. – Rahul Vats May 28 '17 at 18:55
-
Before sending the zpl you can write it to a file and tell the client to send you that file, then test it on http://labelary.com/viewer.html – DanBreakingNews May 28 '17 at 19:11
-
Thanks a lot. Got your point. I have installed the ZPL Designer and export PM file : its look like as ! 0 200 200 609 1 PW 575 TONE 0 SPEED 3 ON-FEED IGNORE NO-PACE BAR-SENSE T 4 0 174 33 Test Name PRINT Is this the ZPL file and please help how can i send parameters from android to that file as its need dynamic data. – Rahul Vats May 28 '17 at 19:32
-
Hi, file.pm is the one containing the ZPL. For the parameters well what i do is to set a field on ZebraDesigner lets say it's call MY_VAR_VALUE the when generated the ZPL look for that value and replace it with whatever you like. Example: ^FT34,604^A0N,20,19^FH\^FDMY_VAR_VALUE^FS then just replace it ^FT34,604^A0N,20,19^FH\^FDHELLO WORLD^FS – DanBreakingNews May 28 '17 at 19:53
-
Thanks a lot my pm file code like this: ! 0 200 200 609 1 PW 575 TONE 0 SPEED 3 ON-FEED IGNORE NO-PACE BAR-SENSE T 4 0 174 33 Test Name PRINT Is it ok? – Rahul Vats May 29 '17 at 12:27
-
Your output file is not ZPL language, make sure when creating a new label to specify the right printer type and the language to use. – DanBreakingNews May 29 '17 at 13:52
0
Hi here is an example of how to print using zebra from a cordova application
package com.custom.plugin;
import android.os.Build;
import org.apache.cordova.CordovaPlugin;
import org.apache.cordova.CallbackContext;
import org.apache.cordova.CordovaInterface;
import org.apache.cordova.CordovaWebView;
import org.apache.cordova.PluginResult;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import android.app.Activity;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.Context;
import android.support.v4.app.ActivityCompat;
import android.os.Bundle;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothClass;
import android.bluetooth.BluetoothDevice;
import java.util.Set;
import com.zebra.android.discovery.*;
import com.zebra.sdk.comm.*;
import com.zebra.sdk.printer.*;
import com.zebra.sdk.printer.SGD;
/**
* This class echoes a string called from JavaScript.
*/
public class PrinterDanBreakingNews extends CordovaPlugin {
@Override
public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException {
if (action.equals("getListPairedDevices")) {
this.getListPairedDevices(callbackContext);
return true;
}else if(action.equals("print"))
{
this.print(callbackContext,args);
return true;
}
return false;
}
private void getListPairedDevices(CallbackContext callbackContext)
{
try
{
BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
if( !bluetoothAdapter.isEnabled() )
{
callbackContext.error("Favor encienda el bluetooth");
}
Set<BluetoothDevice> pairedDevices = bluetoothAdapter.getBondedDevices();
if (pairedDevices.size() > 0) {
JSONArray lista = new JSONArray();
for (BluetoothDevice device : pairedDevices) {
String bname = device.getName();
String bmac = device.getAddress();
String btype
= getBTMajorDeviceClass(
device.getBluetoothClass().getMajorDeviceClass()
);
JSONObject item = new JSONObject();
item.put("name", bname);
item.put("type", btype);
item.put("mac", bmac);
lista.put(item);
}
callbackContext.success(lista.toString());
}
callbackContext.error("Error. no hay dispositivos registrados");
}
catch( Exception ex )
{
callbackContext.error("Error. " + ex.toString());
}
}
private String getBTMajorDeviceClass(int major){
switch(major){
case BluetoothClass.Device.Major.AUDIO_VIDEO:
return "AUDIO_VIDEO";
case BluetoothClass.Device.Major.COMPUTER:
return "COMPUTER";
case BluetoothClass.Device.Major.HEALTH:
return "HEALTH";
case BluetoothClass.Device.Major.IMAGING:
return "IMAGING";
case BluetoothClass.Device.Major.MISC:
return "MISC";
case BluetoothClass.Device.Major.NETWORKING:
return "NETWORKING";
case BluetoothClass.Device.Major.PERIPHERAL:
return "PERIPHERAL";
case BluetoothClass.Device.Major.PHONE:
return "PHONE";
case BluetoothClass.Device.Major.TOY:
return "TOY";
case BluetoothClass.Device.Major.UNCATEGORIZED:
return "UNCATEGORIZED";
case BluetoothClass.Device.Major.WEARABLE:
return "WEARABLE";
default: return "unknown!";
}
}
public void print(final CallbackContext callbackContext, final JSONArray args){
try
{
new Thread(new Runnable() {
@Override
public void run() {
try {
String mac = "";
String template = "";
String length = "";
if( args.length() > 0 ) {
JSONArray row = args.getJSONArray(0);
JSONObject item = row.getJSONObject(0);
mac = item.getString("mac");
template = item.getString("template");
length = item.getString("length");
}
Connection thePrinterConn = new BluetoothConnectionInsecure(mac);
if (isPrinterReady(thePrinterConn)) {
thePrinterConn.open();
SGD.SET("device.languages", "zpl", thePrinterConn);
SGD.SET("ezpl.media_type", "continuous", thePrinterConn);
SGD.SET("zpl.label_length", length, thePrinterConn);
thePrinterConn.write(template.getBytes());
Thread.sleep(500);
thePrinterConn.close();
callbackContext.success("listo");
} else {
callbackContext.error("Error3, la impresora no esta lista");
}
} catch (Exception ex) {
callbackContext.error("Error2. " + ex.toString());
}
}
}).start();
}
catch(Exception ex)
{
callbackContext.error("Error1. " + ex.toString());
}
}
private Boolean isPrinterReady(Connection connection)
throws Exception {
Boolean isOK = false;
connection.open();
ZebraPrinter printer = ZebraPrinterFactory.getInstance(connection);
PrinterStatus printerStatus = printer.getCurrentStatus();
if (printerStatus.isReadyToPrint) {
isOK = true;
} else if (printerStatus.isPaused) {
//throw new ConnectionException("Cannot print because the printer is paused");
} else if (printerStatus.isHeadOpen) {
//throw new ConnectionException("Cannot print because the printer media door is open");
} else if (printerStatus.isPaperOut) {
//throw new ConnectionException("Cannot print because the paper is out");
} else {
//throw new ConnectionException("Cannot print");
}
//connection.open();
return isOK;
}
}
In the function getListPairedDevices you can get a list of mac addresses to use and then use function print to send your ZLP code.
Here is some ZPL test.
CT~~CD,~CC^~CT~
^XA~TA000~JSN^LT0^MNW^MTD^PON^PMN^LH0,0^JMA^PR4,4~SD0^JUS^LRN^CI0^XZ
^XA
^MMT
^PW575
^LL0799
^LS0
^FT35,720^A0N,20,19^FH\^FDHORA^FS
^FT35,680^A0N,20,19^FH\^FDFECHA^FS
^FT34,644^A0N,20,19^FH\^FDCOURRIER^FS
^FT34,609^A0N,20,19^FH\^FDADR2^FS
^FT34,572^A0N,20,19^FH\^FDADR1^FS
^FT34,533^A0N,20,19^FH\^FDSUCURSAL^FS
^FT34,498^A0N,20,19^FH\^FDDESTINATARIO^FS
^FT34,461^A0N,20,19^FH\^FDREMITENTE^FS
^FT165,720^A0N,20,19^FH\^FD: VHORA^FS
^FT165,680^A0N,20,19^FH\^FD: VFECHA^FS
^FT165,644^A0N,20,19^FH\^FD: VCOURRIER^FS
^FT166,534^A0N,20,19^FH\^FD: VSUCURSAL^FS
^FT166,426^A0N,20,19^FH\^FD: VEMPAQUE^FS
^FT166,461^A0N,20,19^FH\^FD: VREMITENTE^FS
^FT166,497^A0N,20,19^FH\^FD: VDESTINATARIO^FS
^FT34,425^A0N,20,19^FH\^FDEMPAQUE^FS
^FT136,365^A0N,23,24^FH\^FD1138 CHO-CHO-1-1-1-1^FS
^FT185,325^A0N,23,24^FH\^FDGUIA: 11389942705^FS
^FT165,46^A0N,28,28^FH\^FDDIRECTO LOGISTICS^FS
^FT25,214^A0N,138,139^FH\^FD1/2^FS
^FT380,265^BQN,2,8
^FH\^FDLA,101010^FS
^FO20,281^GB536,0,3^FS
^PQ1,0,1,Y^XZ

DanBreakingNews
- 11
- 2
- 6