一、前言
在硬件系列(五)-------------Android小票打印机连接 (已封装好,可直接使用)博文中,介绍了利用小票打印sdk进行小票打印,这个也是很久前写的了,也有很多同行的朋友需要sdk进行打印,只是碍于写那篇博文的时候是抽离出来的,很多同行要demo就没有,现在正好有台小票打印机在身边,就顺便做了一下总结,写了一些相关硬件的demo,都是打印机系列,这次demo会分享出来,保证可行,小票打印机可以支持很多品牌的打印,只要能获取到打印设备的pid和vid,就能进行小票打印了。不多说,开撸。
二、USB管理类
import android.annotation.SuppressLint;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.hardware.usb.UsbConstants;
import android.hardware.usb.UsbDevice;
import android.hardware.usb.UsbDeviceConnection;
import android.hardware.usb.UsbEndpoint;
import android.hardware.usb.UsbInterface;
import android.hardware.usb.UsbManager;
import android.util.Log;
import java.util.HashMap;
import java.util.Iterator;
/**
* usb端口测试
*
* @author Freak
* @date 2019/8/13.
*/
public class UsbAdmin {
private static final String TAG = "UsbAdmin";
private UsbManager mUsbManager;
private UsbDevice mDevice;
private UsbDeviceConnection mConnection;
private UsbEndpoint mEndpointIntr;
private PendingIntent mPermissionIntent = null;
private static final String ACTION_USB_PERMISSION = "com.android.example.USB_PERMISSION";
@SuppressLint("NewApi")
private void setDevice(UsbDevice device) {
if (device != null) {
UsbInterface intf = null;
UsbEndpoint ep = null;
int interfaceCount = device.getInterfaceCount();
Log.i(TAG, "InterfaceCount:" + interfaceCount);
int j;
mDevice = device;
for (j = 0; j < interfaceCount; j++) {
int i;
intf = device.getInterface(j);
Log.i(TAG, "接口是:" + j + "类是:" + intf.getInterfaceClass());
if (intf.getInterfaceClass() == 7) {
int usbEndpointCount = intf.getEndpointCount();
for (i = 0; i < usbEndpointCount; i++) {
ep = intf.getEndpoint(i);
Log.i(TAG, "端点是:" + i + "方向是:" + ep.getDirection() + "类型是:" + ep.getType());
if (ep.getDirection() == 0 && ep.getType() == UsbConstants.USB_ENDPOINT_XFER_BULK) {
Log.i(TAG, "接口是:" + j + "端点是:" + i);
break;
}
}
if (i != usbEndpointCount) {
break;
}
}
}
if (j == interfaceCount) {
Log.i(TAG, "没有打印机接口");
return;
}
mEndpointIntr = ep;
UsbDeviceConnection connection = mUsbManager.openDevice(device);
if (connection != null && connection.claimInterface(intf, true)) {
Log.i(TAG, "打开成功! ");
Log.i(TAG, "connection " + connection);
mConnection = connection;
} else {
Log.i(TAG, "打开失败! ");
mConnection = null;
}
}
}
/**
* 这是测试打开usb
*/
@SuppressLint("NewApi")
public void openUsb() {
Log.i(TAG, "执行到这里1 ");
if (mDevice != null) {
Log.i(TAG, "执行到这里2 ");
Log.i(TAG, "mDevice: " + mDevice.getDeviceId());
setDevice(mDevice);
if (mConnection == null) {
HashMap<String, UsbDevice> deviceList = mUsbManager.getDeviceList();
Iterator<UsbDevice> deviceIterator = deviceList.values().iterator();
while (deviceIterator.hasNext()) {
UsbDevice device = deviceIterator.next();
mUsbManager.requestPermission(device, mPermissionIntent);
}
}
} else {
Log.i(TAG, "执行到这里3");
HashMap<String, UsbDevice> deviceList = mUsbManager.getDeviceList();
Iterator<UsbDevice> deviceIterator = deviceList.values().iterator();
while (deviceIterator.hasNext()) {
UsbDevice device = deviceIterator.next();
Log.i(TAG, "执行到这里4" + device.getDeviceId());
mUsbManager.requestPermission(device, mPermissionIntent);
}
}
}
@SuppressLint("NewApi")
public void closeUsb() {
if (mConnection != null) {
mConnection.close();
mConnection = null;
}
}
public String getUsbStatus(boolean language) {
if (mDevice == null) {
if (language) {
return "没有Usb设备!";
} else {
return "No Usb Device!";
}
}
if (mConnection == null) {
if (language) {
return "Usb设备不是打印机!";
} else {
return "Usb device is not a printer!";
}
}
if (language) {
return "Usb打印机打开成功!";
}
return "Usb Printer Open success!";
}
/**
* 打印连接的测试回馈
*
* @return
*/
public boolean getUsbStatus() {
if (mConnection == null) {
return false;
}
return true;
}
/**
* 发送信息 一是打印消息,切纸,打开钱箱等
*
* @param content
* @return
*/
@SuppressLint("NewApi")
public boolean sendCommand(byte[] content) {
boolean result;
synchronized (this) {
int len = -1;
if (mConnection != null) {
len = mConnection.bulkTransfer(mEndpointIntr, content, content.length, 10000);
}
if (len < 0) {
result = false;
Log.i(TAG, "发送失败! " + len);
} else {
result = true;
Log.i(TAG, "发送" + len + "字节数据");
}
}
return result;
}
private final BroadcastReceiver mUsbReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (ACTION_USB_PERMISSION.equals(action)) {
synchronized (this) {
UsbDevice device = (UsbDevice) intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) {
if (device != null) {
//现在排除了标签打印机
Log.d(TAG, "其他设备的id " + device.getProductId());
// if (device.getProductId() != 22304) {
// setDevice(device);
// }
if (device.getProductId() != 1 && device.getProductId() != 46880 && device.getProductId() != 22304) {
setDevice(device);
}
} else {
closeUsb();
mDevice = device;
}
} else {
Log.d(TAG, "permission denied for device " + device);
}
}
}
}
};
private static UsbAdmin usbAdmin;
public static UsbAdmin getInstance(Context context) {
if (usbAdmin != null) {
return usbAdmin;
} else {
usbAdmin = new UsbAdmin(context);
return usbAdmin;
}
}
public UsbAdmin(Context context) {
mUsbManager = (UsbManager) context.getSystemService(Context.USB_SERVICE);
mPermissionIntent = PendingIntent.getBroadcast(context, 0, new Intent(ACTION_USB_PERMISSION), 0);
IntentFilter filter = new IntentFilter(ACTION_USB_PERMISSION);
context.registerReceiver(mUsbReceiver, filter);
}
}
三、打印工具类
/**
* 调用硬件工具类
*
* @author Freak
* @date 2019/8/13.
*/
public class HardwareUtil {
public static final byte[] PRINTF_CUT = {0x0a, 0x0a, 0x1d, 0x56, 0x01};
public static final byte[] PUSH_CASH = {0x1b, 0x70, 0x00, 0x1e, (byte) 0xff, 0x00};
public static final int TYPE_COLLECTION = 0;
public static final int TYPE_WEB_ORDER = 1;
public static final int TYPE_VIP_CARD = 2;
public static final int TYPE_TRANSFER = 3;
/**
* 设备是否连接
*/
public static boolean isConnected(UsbAdmin mUsbAdmin) {
mUsbAdmin.openUsb();
if (!mUsbAdmin.getUsbStatus()) {
return false;
} else {
return true;
}
}
/**
* 是否能打印
*/
public static boolean isPrintfData(String content, UsbAdmin mUsbAdmin) {
boolean print = (boolean) ACache.get(App.getInstance().getApplicationContext()).getAsObject(Constants.WHETHER_PRINT);
Log.d("HardwareUtil", "是否打印" + print);
if (!print) {
return false;
}
byte[] data = new byte[1024];
try {
String cmd = testFormat();
data = cmd.getBytes("GBK");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
if (mUsbAdmin.sendCommand(data) && mUsbAdmin.sendCommand(PRINTF_CUT)) {
return true;
} else {
return false;
}
}
/**
* 打开钱箱
*
* @param mUsbAdmin
* @return
*/
public static boolean pushCash(UsbAdmin mUsbAdmin) {
boolean canPush = false;
mUsbAdmin.openUsb();
mUsbAdmin.getUsbStatus();
if (mUsbAdmin.sendCommand(PUSH_CASH)) {
canPush = true;
} else {
canPush = false;
}
return canPush;
}
/**
* 测试格式
*/
public static String testFormat() {
String data = null;
String time = DateUtil.getTime();
data = "测试单据" +
cmdEnter() +
"------------------------------\n" +
cmdEnter() +
"收银员:1001\n" +
"测试时间: " + time + "\n" +
"------------------------------\n" +
cmdEnter();
return data;
}
/**
* 换行
*
* @return
*/
public static String cmdEnter() {
return new StringBuffer().append((char) 10).toString();
}
}
四、调用方法
4.1、初始化
private UsbAdmin mUsbAdmin;
mUsbAdmin = UsbAdmin.getInstance(getActivity());
4.2、连接打印机
HardwareUtil.isConnected(mUsbAdmin);
//连接可能需要1秒时间,设置延时任务,更新连接状态
mHandler.postDelayed(new Runnable() {
@Override
public void run() {
mHandler.sendEmptyMessage(0);
}
}, 2000);
handle是为了延迟一下更新连接状态,因为连接的时候需要一点时间。
4.3、断开打印机
mUsbAdmin.closeUsb();
mHandler.postDelayed(new Runnable() {
@Override
public void run() {
mHandler.sendEmptyMessage(1);
}
}, 2000);
4.4、打印测试
HardwareUtil.isPrintfData("", mUsbAdmin);
五、分析
这个小票打印使用的是UsbManager进行usb设备的获取,需要一个USB权限com.android.example.USB_PERMISSION,无关设备没有这个权限就无法使用usb打印设备打印,也就找不到这个打印设备。
再初始化的时候,是创建了一个UsbAdmin对象,我们来看一下构造方法:
public UsbAdmin(Context context) {
mUsbManager = (UsbManager) context.getSystemService(Context.USB_SERVICE);
mPermissionIntent = PendingIntent.getBroadcast(context, 0, new Intent(ACTION_USB_PERMISSION), 0);
IntentFilter filter = new IntentFilter(ACTION_USB_PERMISSION);
context.registerReceiver(mUsbReceiver, filter);
}
private final BroadcastReceiver mUsbReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (ACTION_USB_PERMISSION.equals(action)) {
synchronized (this) {
UsbDevice device = (UsbDevice) intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) {
if (device != null) {
//现在排除了标签打印机
Log.d(TAG, "其他设备的id " + device.getProductId());
// if (device.getProductId() != 22304) {
// setDevice(device);
// }
if (device.getProductId() != 1 && device.getProductId() != 46880 && device.getProductId() != 22304) {
setDevice(device);
}
} else {
closeUsb();
mDevice = device;
}
} else {
Log.d(TAG, "permission denied for device " + device);
}
}
}
}
};
在openUsb方法中,每一个设备都进行了权限的请求:
mUsbManager.requestPermission(device, mPermissionIntent);
然后根据获取的设备去打印,打印效果如图所示: