原文:http://blog.csdn.net/johnwcheung/article/details/71576833

Android下的设备调试,如果设备提供了驱动,按照厂家的驱动调试即可;设备未提供驱动,只能按照通用的方法进行调试。

对于智能POS、收银机以及其他打印设备,如果厂商不提供打印相关sdk,那么打印功能怎么实现呢?其实我们可以基于USB通信机制,自己去实现打印驱动。

整个实现流程如下

  1. 初始化打印机:首先要获取USB管理器;其次要注册监听USB设备插拔变化和请求权限的广播;最后列出所有的USB设备,并且都请求获取USB权限;

  2. 实现这个广播接收器:当接收到请求权限的广播时,获取USB设备的引用,android系统会询问你是否允许设备访问,默认为false;当允许了访问之后,会判断USB的引用是否为null, 如果不为空,说明该设备可以连接,否则提示设备拒绝访问;如果接收到已连接的打印设备移除的广播,则要关闭本次连接。

  3. 对于获得权限可使用的USB,我们将获取设备的功能集(UsbInterface)和通信通道(UsbEndpoint),然后创建host与device的连接用来传输数据。

  4. 最后,我们在需要打印的地方调用上面封装好的打印方法,就可以发送指令来控制已经建立连接的打印机了。

USB打印机实现

/**
* USB打印机
* Created by john on 17-5-10.
*/ public class USBPrinter { private static final String ACTION_USB_PERMISSION = "com.usb.printer.USB_PERMISSION"; private static USBPrinter mInstance; private Context mContext;
private UsbDevice mUsbDevice;
private PendingIntent mPermissionIntent;
private UsbManager mUsbManager;
private UsbDeviceConnection mUsbDeviceConnection; private final BroadcastReceiver mUsbDeviceReceiver = new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (ACTION_USB_PERMISSION.equals(action)) {
synchronized (this) {
UsbDevice usbDevice = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) {
mUsbDevice = usbDevice;
} else {
Toast.makeText(context, "Permission denied for device " + usbDevice, Toast.LENGTH_SHORT).show();
}
}
} else if (UsbManager.ACTION_USB_DEVICE_DETACHED.equals(action)) {
if (mUsbDevice != null) {
Toast.makeText(context, "Device closed", Toast.LENGTH_SHORT).show();
if (mUsbDeviceConnection != null) {
mUsbDeviceConnection.close();
}
}
}
}
}; private USBPrinter() { } public static USBPrinter getInstance() {
if (mInstance == null) {
mInstance = new USBPrinter();
}
return mInstance;
} /**
* 初始化打印机,需要与destroy对应
*
* @param context 上下文
*/
public static void initPrinter(Context context) {
getInstance().init(context);
} /**
* 销毁打印机持有的对象
*/
public static void destroyPrinter() {
getInstance().destroy();
} private void init(Context context) {
mContext = context;
mUsbManager = (UsbManager) mContext.getSystemService(Context.USB_SERVICE);
mPermissionIntent = PendingIntent.getBroadcast(mContext, 0, new Intent(ACTION_USB_PERMISSION), 0);
IntentFilter filter = new IntentFilter(ACTION_USB_PERMISSION);
filter.addAction(UsbManager.ACTION_USB_DEVICE_DETACHED);
mContext.registerReceiver(mUsbDeviceReceiver, filter); // 列出所有的USB设备,并且都请求获取USB权限
HashMap<String, UsbDevice> deviceList = mUsbManager.getDeviceList(); for (UsbDevice device : deviceList.values()) {
mUsbManager.requestPermission(device, mPermissionIntent);
}
} private void destroy() {
mContext.unregisterReceiver(mUsbDeviceReceiver); if (mUsbDeviceConnection != null) {
mUsbDeviceConnection.close();
mUsbDeviceConnection = null;
} mContext = null;
mUsbManager = null;
} /**
* 打印方法
* @param msg
*/
public void print(String msg) {
final String printData = msg;
if (mUsbDevice != null) {
UsbInterface usbInterface = mUsbDevice.getInterface(0);
for (int i = 0; i < usbInterface.getEndpointCount(); i++) {
final UsbEndpoint ep = usbInterface.getEndpoint(i);
if (ep.getType() == UsbConstants.USB_ENDPOINT_XFER_BULK) {
if (ep.getDirection() == UsbConstants.USB_DIR_OUT) {
mUsbDeviceConnection = mUsbManager.openDevice(mUsbDevice);
if (mUsbDeviceConnection != null) {
Toast.makeText(mContext, "Device connected", Toast.LENGTH_SHORT).show();
mUsbDeviceConnection.claimInterface(usbInterface, true);
new Thread(new Runnable() {
@Override
public void run() {
byte[] bytes = printData.getBytes();
int b = mUsbDeviceConnection.bulkTransfer(ep, bytes, bytes.length, 100000);
Log.i("Return Status", "b-->" + b);
}
}).start(); mUsbDeviceConnection.releaseInterface(usbInterface);
break;
}
}
}
}
} else {
Toast.makeText(mContext, "No available USB print device", Toast.LENGTH_SHORT).show();
}
}
}

最新文章

  1. js中的replace全局替换
  2. python实现指定目录下JAVA文件单词计数的多进程版本
  3. SQL参数化查询--最有效可预防SQL注入攻击的防御方式
  4. ACE的 日志
  5. ANDROID_MARS学习笔记_S04_008_用Listview、自定义adapter显示返回的微博数据
  6. 限定checkbox最多选中数量
  7. hdu 5625 Clarke and chemistry
  8. GitHub上搭建Hexo化的博客
  9. Oracle 树操作
  10. AngularJS and Asp.net MVC
  11. gulp自动化压缩合并、加版本号解决方案
  12. api_response.go
  13. C++ 对象实例化(转)
  14. 066、Weave如何与外网通信?(2019-04-09 周二)
  15. Intellij Idea乱码解决方案
  16. 干货分享 9款精挑细选的HTML5应用
  17. 回调函数之基本的Promise
  18. Spark Core 资源调度与任务调度(standalone client 流程描述)
  19. Codeforces Round #348 (VK Cup 2016 Round 2, Div. 1 Edition) C. Little Artem and Random Variable 数学
  20. js前端数据加密插件

热门文章

  1. 使用log4net将日志文件输出为csv格式
  2. python编码问题FAQ
  3. 微信小程序传值
  4. Linux下调整根目录的空间大小
  5. Nginx高级应用之Location Url 配置
  6. webservice 采用SSL实现加密传输
  7. 前端PHP入门-008-自定义函数
  8. shell多进程的实现
  9. Jquery 操作 Select 详解
  10. NOIP模拟赛9