Android 蓝牙打印

2,142 阅读4分钟
原文链接: mp.weixin.qq.com

公司项目需要使用蓝牙打印,然而除了一个蓝牙打印机,啥都没有,在网上找了一堆文档,最后二维码打印还是折腾不好,最后在网上找到了个开源库,特别好用,在这里记录一下,也算是做一些推荐。项目地址,支持标准ESC-POS命令打印,固定IP或蓝牙打印,支持黑白图片打印。

集成

  1. dependencies {

  2.    implementation 'am.util:printer:2.1.0'

  3. }

在 AndroidManifest.xml中添加权限

                            
  1. <uses-permission android:name= "android.permission.INTERNET" />

  2. <uses-permission android:name= "android.permission.BLUETOOTH" />

实现PrintDataMaker

  1. public class BPrintDataMaker implements PrintDataMaker {

  2.  private Context context;

  3.  private ContentBean bean;

  4.  private int width;

  5.  private int height;

  6.  public BPrintDataMaker(Context context, ContentBean qr, int width, int height) {

  7.    this.context = context;

  8.    this.bean = qr;

  9.    this.width = width;

  10.    this.height = height;

  11.  }

  12.  @Override public List<byte[]> getPrintData(int type) {

  13.    ArrayList<byte[]> data = new ArrayList<>();

  14.    try {

  15.      PrinterWriter printer;

  16.      printer = new PrinterWriter58mm(height, width);

  17.      printer.printLineFeed();

  18.      printer.setAlignCenter();

  19.      printer.setEmphasizedOn();

  20.      printer.setFontSize(1);

  21.      printer.print("NO");

  22.      printer.printLineFeed();

  23.      printer.print(bean.getJobNo());

  24.      printer.printLineFeed();

  25.      printer.setFontSize(0);

  26.      printer.print(TextUtils.splitText(bean.getJobTime()));

  27.      printer.printLineFeed();

  28.      printer.print(TextUtils.splitTextTime(bean.getJobTime()));

  29.      printer.printLineFeed();

  30.      printer.setAlignCenter();

  31.      data.add(printer.getDataAndReset());

  32.      String qr = bean.getJobNo() + " " + bean.getVarietyCode();

  33.      Timber.d(qr);

  34.      String bitmapPath = FileUtils.getExternalFilesDir(context, "Temp") + "tmp_qr.jpg";

  35.      Timber.d(bitmapPath);

  36.      if (QRCodeUtil.createQRImage(qr, 380, 380, null, bitmapPath)) {

  37.        ArrayList<byte[]> image2 = printer.getImageByte(bitmapPath);

  38.        data.addAll(image2);

  39.      }

  40.      printer.printLineFeed();

  41.      printer.print("扫一扫,查看详情");

  42.      printer.printLineFeed();

  43.      printer.printLineFeed();

  44.      printer.printLineFeed();

  45.      printer.printLineFeed();

  46.      printer.printLineFeed();

  47.      printer.feedPaperCutPartial();

  48.      data.add(printer.getDataAndClose());

  49.      return data;

  50.    } catch (Exception e) {

  51.      return new ArrayList<>();

  52.    }

  53.  }

  54. }

PrintDataMaker的作用是构建打印数据,并不包含蓝牙设备列表与蓝牙连接。下面提供蓝牙连接功能。

蓝牙连接打印

  1. private void bluetoothPrint() {

  2.    PrintExecutor executor = null;

  3.    BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();

  4.    //得到BluetoothAdapter的Class对象

  5.    Class<BluetoothAdapter> bluetoothAdapterClass = BluetoothAdapter.class;

  6.    try {

  7.      //得到连接状态的方法

  8.      Method method = bluetoothAdapterClass.getDeclaredMethod("getConnectionState", (Class[]) null);

  9.      //打开权限

  10.      method.setAccessible(true);

  11.      int state = (int) method.invoke(adapter, (Object[]) null);

  12.      Timber.i("BLUETOOTH: BluetoothAdapter.STATE_CONNECTED");

  13.      Set<BluetoothDevice> devices = adapter.getBondedDevices();

  14.      Timber.i("BLUETOOTH devices:" + devices.size());

  15.      for (BluetoothDevice device : devices) {

  16.        int isConnected =device.getBondState();

  17.        Timber.d(isConnected+"连接");

  18.        if (isConnected>0) {

  19.          device.getAddress();

  20.          if (executor == null) {

  21.            executor = new PrintExecutor(device, PrinterWriter58mm.TYPE_58);

  22.            executor.setOnStateChangedListener(state1 -> {

  23.              switch (state1) {

  24.                case PrintSocketHolder.STATE_0:

  25.                  Timber.d(">生成页面数据");

  26.                  break;

  27.                case PrintSocketHolder.STATE_1:

  28.                  Timber.d(">生成数据成功,开始创建Socket连接");

  29.                  break;

  30.                case PrintSocketHolder.STATE_2:

  31.                  Timber.d("创建Socket成功,开始发送测试数据");

  32.                  break;

  33.                case PrintSocketHolder.STATE_3:

  34.                  Timber.d("获取输出流成功,开始写入测试页面数据");

  35.                  break;

  36.                case PrintSocketHolder.STATE_4:

  37.                  Timber.d("写入测试页面数据成功,正在完成测试");

  38.                  break;

  39.              }

  40.            });

  41.            executor.setOnPrintResultListener(errorCode -> {

  42.              switch (errorCode) {

  43.                case PrintSocketHolder.ERROR_0:

  44.                  Timber.d("测试成功完成!");

  45.                  break;

  46.                case PrintSocketHolder.ERROR_1:

  47.                  Timber.d("生成测试页面数据失败!");

  48.                  break;

  49.                case PrintSocketHolder.ERROR_2:

  50.                  Timber.d("创建Socket失败!");

  51.                  break;

  52.                case PrintSocketHolder.ERROR_3:

  53.                  Timber.d("获取输出流失败!");

  54.                  break;

  55.                case PrintSocketHolder.ERROR_4:

  56.                  Timber.d("写入测试页面数据失败!");

  57.                  break;

  58.                case PrintSocketHolder.ERROR_5:

  59.                  Timber.d("必要的参数不能为空!");

  60.                  break;

  61.                case PrintSocketHolder.ERROR_6:

  62.                  Timber.d("关闭Socket出错!");

  63.                  break;

  64.                case PrintSocketHolder.ERROR_100:

  65.                  Timber.d("打印失败!");

  66.                  break;

  67.              }

  68.            });

  69.          }

  70.          executor.setDevice(device);

  71.          executor.doPrinterRequestAsync(new BPrintDataMaker(mContext, mBean, 300, 255));

  72.        }

  73.      }

  74.    } catch (Exception e) {

  75.      e.printStackTrace();

  76.      SimpleHUD.showInfoMessage(mContext, "请先连接你的蓝牙设备...");

  77.    }

  78.  }

BluetoothAdapter是全局单例蓝牙适配器。通过  adapter获取到  BluetoothDevicePrintExecutor是打印执行类,通过  BluetoothDevice和  Type初始化工具类。然后设置执行者的状态和结果监听。设置设备,最后异步打印即可。

结语

本篇文章只介绍了printer的蓝牙打印功能,printer还拥有固定IP打印功能,不过项目并不适用,有需要的可以自行学习。


欢迎长按下图 -> 识别图中二维码或者微信扫一扫关注我的公众号