androidUSB通信——打印机

androidUSB通信——打印机

本文主要解决一下几个问题:
- usb的基本通信
- usb的基本通信打印文字
- 使用jar包打印一个订单信息

一、usb基础

Android 支持各种 USB 外围设备,通过两种模式来支持 Android USB 外设 (实现了 Android 外设协议的硬件): USB 外设模式和 USB 主机模式。在 USB 外设模式下,外部 USB 硬件(装有 Android 的设备要连接的外部设备)充当 USB 主机。
关于usb的介绍可以查看:
http://www.cnblogs.com/over140/archive/2011/11/03/2234258.html
我们这里面使用的是 usb host方式,关于usb host的介绍可以查看官网文档,也可以查看:
http://blog.csdn.net/yylooker2008/article/details/24378991

二、创建基本usb通信

主要涉及到以下的文件:
- AndroidManifest.xml 清单文件
- UsbDemoActivity.java
- qwm_usb_xml.xml 这个文件放在 res/xml的下面,用来过滤设备

2.1qwm_usb_xml.xml说明

这个文件放在 res/xml的下面,用来过滤设备,满足的设备将会被过滤出来。

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <usb-device vendor-id="1234" product-id="5678"/>
    <usb-device vendor-id="1155" product-id="22304" />
</resources>

<!--
  参数说明:
   vendor-id  (VID):产商id
   product-id (PID):产品id
   class             :类
   subclass          :子类
   protocol          :协议
-->

2.2AndroidManifest.xml清单文件配置

这里主要用来申明usb的相关信息

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.qwm.qwmprinterdemo">

    <!--声明使用usb-->
    <uses-feature android:name="android.hardware.usb.host"></uses-feature>

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity
            android:name=".MainActivity"
            android:label="@string/app_name"
            android:theme="@style/AppTheme.NoActionBar">
        </activity>
        <activity
            android:name=".UsbDemoActivity"
            android:label="@string/title_activity_usb_demo"
            android:theme="@style/AppTheme.NoActionBar">
            <intent-filter>
                <!--usb设备的动作-->
                <action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" />
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
           <!-- android设备的信息过滤-->
            <meta-data android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED"
                android:resource="@xml/qwm_usb_xml" ></meta-data>
        </activity>
    </application>
</manifest>

2.3UsbDemoActivity.java usb的操作类

这个类用来操作usb,我们主要按一下几个步骤来操作:
- 1.创建UsbManager
- 2.获取满足的设备
- 3.获取满足设备中的“接口”
- 4.获取接口的端点(获取设备endpoint)
- 5.连接设备
- 6.发送数据

package com.qwm.qwmprinterdemo;

import android.content.Context;
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.os.Bundle;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.Snackbar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.util.Log;
import android.view.View;
import android.widget.Switch;
import android.widget.TextView;
import android.widget.Toast;

import java.util.HashMap;
import java.util.Iterator;

/**
 * @author qiwenming
 * @date 2016/2/25 0025 上午 10:37
 * @ClassName: UsbDemoActivity
 * @PackageName: com.qwm.qwmprinterdemo
 * @Description: usb练习
 */
public class UsbDemoActivity extends AppCompatActivity {

    private String TAG = UsbDemoActivity.class.getName();
    private UsbManager usbManager;
    private TextView usbDevicesTv;
    /**
     * 满足的设备
     */
    private UsbDevice myUsbDevice;
    /**
     * usb接口
     */
    private UsbInterface usbInterface;
    /**
     * 块输出端点
     */
    private UsbEndpoint epBulkOut;
    private UsbEndpoint epBulkIn;
    /**
     * 控制端点
     */
    private UsbEndpoint epControl;
    /**
     * 中断端点
     */
    private UsbEndpoint epIntEndpointOut;
    private UsbEndpoint epIntEndpointIn;
    /**
     * 连接
     */
    private UsbDeviceConnection myDeviceConnection;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_usb_demo);
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        usbDevicesTv = (TextView) findViewById(R.id.tv_usb_devices);

        FloatingActionButton connectFab = (FloatingActionButton) findViewById(R.id.fab_connect);
        connectFab.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {//连接usb
                //1)创建usbManager
                usbManager = (UsbManager)getSystemService(Context.USB_SERVICE);
                //2)获取到所有设备 选择出满足的设备
                enumeraterDevices();
                //3)查找设备接口
                getDeviceInterface();
                //4)获取设备endpoint
                assignEndpoint();
                //5)打开conn连接通道
                openDevice();
            }
        });
        FloatingActionButton sendFab = (FloatingActionButton) findViewById(R.id.fab_send);
        sendFab.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {//6.发送数据 String xx = "0D";
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        try{
                            sendMessageToPoint("杞文明\nqiwenming\nqiwenmingshiwo".getBytes("gbk"));
                        }catch (Exception e){
                        }
                    }
                }).start();
            }
        });
    }

    /**
     * 枚举设备
     */
    public void enumeraterDevices(){
        HashMap<String, UsbDevice> deviceList = usbManager.getDeviceList();
        Iterator<UsbDevice> deviceIterator = deviceList.values().iterator();
        StringBuilder sb = new StringBuilder();
        while(deviceIterator.hasNext()){
            UsbDevice device = deviceIterator.next();
            sb.append(devicesString(device));
//                    sb.append(device.toString());
//                    sb.append("\n\n");
            if (device.getVendorId() == 1155 && device.getProductId() == 22304) {
                myUsbDevice = device; // 获取USBDevice
            }
        }
        usbDevicesTv.setText(sb.toString());
    }

    /**
     * usb设备的信息
     * @param device
     * @return
     */
    public String devicesString(UsbDevice device){
        StringBuilder builder = new StringBuilder("UsbDevice\nName=" + device.getDeviceName() +
                "\nVendorId=" + device.getVendorId() + "\nProductId=" + device.getProductId() +
                "\nmClass=" + device.getClass() + "\nmSubclass=" + device.getDeviceSubclass() +
                "\nmProtocol=" + device.getDeviceProtocol() + "\nmManufacturerName=" +"\nmSerialNumber=" +
                "\n\n");
        return builder.toString();
    }

    /**
     * 获取设备的接口
     */
    private void getDeviceInterface() {
        if(myUsbDevice!=null){
            Log.i(TAG,"interfaceCounts : "+myUsbDevice.getInterfaceCount());
            usbInterface = myUsbDevice.getInterface(0);
            System.out.println("成功获得设备接口:" + usbInterface.getId());
        }
    }

    /**
     * 分配端点,IN | OUT,即输入输出;可以通过判断
     */
    private void assignEndpoint() {
        if(usbInterface!=null){
            for (int i = 0; i < usbInterface.getEndpointCount(); i++) {
                UsbEndpoint ep = usbInterface.getEndpoint(i);
                switch (ep.getType()){
                    case UsbConstants.USB_ENDPOINT_XFER_BULK://块
                        if(UsbConstants.USB_DIR_OUT==ep.getDirection()){//输出
                            epBulkOut = ep;
                            System.out.println("Find the BulkEndpointOut," + "index:" + i + "," + "使用端点号:"+ epBulkOut.getEndpointNumber());
                        }else{
                            epBulkIn = ep;
                            System.out .println("Find the BulkEndpointIn:" + "index:" + i+ "," + "使用端点号:"+ epBulkIn.getEndpointNumber());
                        }
                        break;
                    case UsbConstants.USB_ENDPOINT_XFER_CONTROL://控制
                        epControl = ep;
                        System.out.println("find the ControlEndPoint:" + "index:" + i+ "," + epControl.getEndpointNumber());
                        break;
                    case UsbConstants.USB_ENDPOINT_XFER_INT://中断
                        if (ep.getDirection() == UsbConstants.USB_DIR_OUT) {//输出
                            epIntEndpointOut = ep;
                            System.out.println("find the InterruptEndpointOut:" + "index:" + i + ","  + epIntEndpointOut.getEndpointNumber());
                        }
                        if (ep.getDirection() == UsbConstants.USB_DIR_IN) {
                            epIntEndpointIn = ep;
                            System.out.println("find the InterruptEndpointIn:" + "index:" + i + ","+ epIntEndpointIn.getEndpointNumber());
                        }
                        break;
                    default:
                        break;
                }
            }
        }
    }

    /**
     * 连接设备
     */
    public void openDevice() {
        if(usbInterface!=null){//接口是否为null
            // 在open前判断是否有连接权限;对于连接权限可以静态分配,也可以动态分配权限
            UsbDeviceConnection conn = null;
            if(usbManager.hasPermission(myUsbDevice)){
                //有权限,那么打开
                conn = usbManager.openDevice(myUsbDevice);
            }
            if(null==conn){
                Toast.makeText(this,"不能连接到设备",Toast.LENGTH_SHORT).show();
                return;
            }
            //打开设备
            if(conn.claimInterface(usbInterface,true)){
                myDeviceConnection = conn;
                if (myDeviceConnection != null)// 到此你的android设备已经连上zigbee设备
                    System.out.println("open设备成功!");
                final String mySerial = myDeviceConnection.getSerial();
                System.out.println("设备serial number:" + mySerial);
            } else {
                System.out.println("无法打开连接通道。");
                Toast.makeText(this,"无法打开连接通道。",Toast.LENGTH_SHORT).show();
                conn.close();
            }
        }
    }

    /**
     * 发送数据
     * @param buffer
     */
    public void sendMessageToPoint(byte[] buffer) {
        if(myDeviceConnection.bulkTransfer(epBulkOut,buffer,buffer.length,0) >= 0){
            //0 或者正数表示成功
            Toast.makeText(this,"发送成功",Toast.LENGTH_SHORT).show();
        }else{
            Toast.makeText(this,"发送失败的",Toast.LENGTH_SHORT).show();
        }
    }
}

三、使用jar包打印

jar就是把上面打印的指令进行了封装。但是我们使用的是usb通信,所以上面的usb配置步骤还是需要的。
主要涉及以下几个文件:
- AndroidManifest.xml 清单文件配置
- MainActivity.java 打印操作界面
- PrintTerUtils.java 打印工具类
- regoPrintLibV3.0.05.jar 打印的jar包

3.1 regoPrintLibV3.0.05.jar包中 regoPrinter 类的主要方法说明

regoPrinter打印机操作类主要方法如下:

方法说明
CON_PageStart开启页模式
ASCII_PrintString打印字符
ASCII_CtrlPrintCRLF换行
DRAW_SetFillMode画图填充方式
DRAW_SetLineWidth画图线的宽度
DRAW_PrintRectangle画矩形
ASCII_CtrlReset重置
ASCII_CtrlCutPaper切纸
CON_PageEnd结束页模式

切纸的方法调用:

  //切纸功能
  printer.CON_PageStart(myState, false, 0, 0);
  printer.ASCII_CtrlCutPaper(myState, 30, 0);

3.1AndroidManifest.xml配置说明

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.qwm.qwmprinterdemo">

    <!--声明使用usb-->
    <uses-feature android:name="android.hardware.usb.host"></uses-feature>

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity
            android:name=".MainActivity"
            android:label="@string/app_name"
            android:theme="@style/AppTheme.NoActionBar">
            <intent-filter>
                <!--usb设备的动作-->
                <action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" />
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
            <!-- android设备的信息过滤-->
            <meta-data android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED"
                android:resource="@xml/qwm_usb_xml" ></meta-data>
        </activity>
        <activity
            android:name=".UsbDemoActivity"
            android:label="@string/title_activity_usb_demo"
            android:theme="@style/AppTheme.NoActionBar">
        </activity>
    </application>
</manifest>

3.2 PrintTerUtils.java 打印工具类

package com.qwm.qwmprinterdemo.utils;

import android.widget.Toast;

import com.qwm.qwmprinterdemo.MainActivity;

import rego.printlib.export.regoPrinter;


/**
 * @author qiwenming
 * @date 2016/2/29 0029 下午 4:20
 * @ClassName: PrintTerUtils
 * @PackageName: com.qwm.qwmprinterdemo.utils
 * @Description:  打印类
 */
public class PrintTerUtils {
    public regoPrinter printer;
    private static PrintTerUtils printTerUtils;
    public int myState = 0;
    private String printName="RG-MTP58B";
    private MainActivity mainActivity;
    public boolean mBconnect = false;
    private final int wordSize = 20;
    /**
     * 打印的行数
     */
    private int pintCol = 0;
    /**
     * 小票的高度
     */
    private int pintHeight = 540;

    private PrintTerUtils(MainActivity mainActivity){
        this.mainActivity = mainActivity;
        connectDevices(mainActivity);
    }

    public static PrintTerUtils getPrintTerUtils(MainActivity mainActivity){
        if (printTerUtils==null){
            printTerUtils = new PrintTerUtils(mainActivity);
        }
        return printTerUtils;
    }

    /**
     * 连接设备
    */
    private void connectDevices(MainActivity mainActivity){
        this.mainActivity = mainActivity;
        if(printer==null){
            printer = new regoPrinter(mainActivity);//创建设备
        }
        //1.判读设备是否连着
        if(!mBconnect){//没有连接,那么我们连接 (连接设备)
            myState = printer.CON_ConnectDevices(printName, "usb", 200);//连接
            if (myState > 0) {
                Toast.makeText(mainActivity, "打印机连接成功",
                        Toast.LENGTH_SHORT).show();
                mBconnect = true;
            }else{
                mBconnect = false;
                return;
            }
        }
    }

    /**
     * 打印购物网当
     */
    public void toPrintOrder() {
        //TODO 设置我们的 订单
        printer.CON_PageStart(myState,false,0,0);
        printer.ASCII_CtrlAlignType(myState, preDefiniation.AlignType.AT_CENTER.getValue());
        printer.ASCII_PrintString(myState, 0, 1, 0, 0, 0, "欢迎光临  ", "gb2312");
        printer.ASCII_CtrlPrintCRLF(myState, 1);
        printer.ASCII_PrintString(myState, 0, 0, 0, 0, 0, "店铺名称  ", "gb2312");
        printer.ASCII_CtrlPrintCRLF(myState, 1);
        printer.ASCII_CtrlAlignType(myState, preDefiniation.AlignType.AT_LEFT.getValue());
        printer.ASCII_PrintString(myState, 0, 0, 0, 0, 0, "收银员:收银员名称", "gb2312");
        printer.ASCII_CtrlPrintCRLF(myState, 1);
        printer.ASCII_PrintString(myState, 0, 0, 0, 0, 0, "时间:2015-01-01", "gb2312");
        printer.ASCII_CtrlPrintCRLF(myState, 1);
        printer.ASCII_PrintString(myState, 0, 0, 0, 0, 0, "----------------------------", "gb2312");
        printer.ASCII_CtrlPrintCRLF(myState, 1);
        printer.ASCII_PrintString(myState, 0, 0, 1, 0, 0, "商品名称        单价      数量      金额", "gb2312");
        printer.ASCII_CtrlPrintCRLF(myState, 1);
        printer.ASCII_PrintString(myState, 0, 0, 0, 0, 0, "花生           2.00      1      2.00", "gb2312");
        printer.ASCII_CtrlPrintCRLF(myState, 1);
        printer.ASCII_PrintString(myState, 0, 0, 0, 0, 0, "----------------------------", "gb2312");
        printer.ASCII_CtrlPrintCRLF(myState, 1);
        printer.ASCII_PrintString(myState, 0, 0, 0, 0, 0, "合计:¥100元", "gb2312");
        printer.ASCII_CtrlPrintCRLF(myState, 1);
        printer.ASCII_PrintString(myState, 0, 0, 0, 0, 0, "优惠金额:¥90元", "gb2312");
        printer.ASCII_CtrlPrintCRLF(myState, 1);
        printer.ASCII_PrintString(myState, 0, 0, 0, 0, 0, "电话:00000000", "gb2312");
        printer.ASCII_CtrlPrintCRLF(myState, 1);
        printer.ASCII_PrintString(myState, 0, 0, 0, 0, 0, "地址:汉武大帝大厦", "gb2312");
        printer.ASCII_CtrlPrintCRLF(myState, 1);
        printer.ASCII_PrintString(myState, 0, 0, 0, 0, 0, "谢谢惠顾,欢迎下次光临!", "gb2312");
        printer.ASCII_CtrlPrintCRLF(myState, 1);
        printer.ASCII_CtrlReset(myState);
        printer.ASCII_CtrlCutPaper(myState, 66, 0);//切纸
        printer.CON_PageEnd(myState,0);
    }


    /**
     * 回收单子2
     */
    public void toPrint3(){
        printer.CON_PageStart(myState, true, 540, 540);
        printer.DRAW_SetFillMode(false);
        printer.DRAW_SetLineWidth(4);
        //矩形
        printer.DRAW_PrintRectangle(myState, 18, 10, 540, 540);
        printer.DRAW_PrintText(myState, 108, 32, "手机回收凭证", 40);
        printer.DRAW_PrintText(myState, 108, 82, "服务门店:小明大厦店", 20);
        printer.DRAW_SetLineWidth(2);
        printer.DRAW_PrintLine(myState, 38, 107, 500, 107);//线条
        printer.DRAW_PrintText(myState, 38, 127, "订单号:123456789", 25);
        printer.DRAW_PrintText(myState, 38, 167, "时间:2016-01-26 14:50", 25);
        printer.DRAW_PrintText(myState, 38, 207, "姓名:杞文明     联系电话:13000000", 25);
        printer.DRAW_PrintLine(myState, 38, 237, 500, 237);//线条
        printer.DRAW_PrintText(myState, 38, 257, "机型:iPhone 6s", 25);
        printer.DRAW_PrintText(myState, 38, 297, "IMEI:123456789987654123", 25);
        printer.DRAW_PrintText(myState, 38, 337, "设备情况:", 25);
        //下面的高度需要更具字符的个数计算
        printer.DRAW_PrintText(myState, 38, 377, "大陆国行/三网通/过保/xxxxx/小米/嘻嘻嘻一/附件是弟弟福建省的/十分激动手机覅及地上/啦啦啦", 25);
        printer.DRAW_PrintLine(myState, 38, 462, 500, 462);//线条
        printer.DRAW_PrintText(myState, 38, 482, "回收价:1000元RMB", 25);
        printer.CON_PageEnd(myState, 0);
        //切纸功能
        printer.CON_PageStart(myState, false, 0, 0);
        printer.ASCII_CtrlCutPaper(myState, 30, 0);
        printer.CON_PageEnd(myState,0);
    }

}

3.3 MainActivity.java

package com.qwm.qwmprinterdemo;

import android.os.Bundle;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.Snackbar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.View;
import android.view.Menu;
import android.view.MenuItem;

import com.qwm.qwmprinterdemo.utils.PrintTerUtils;

/**
 * @author qiwenming
 * @date 2016/2/29 0029 下午 4:32
 * @ClassName: MainActivity
 * @PackageName: com.qwm.qwmprinterdemo
 * @Description: 打印
 */
public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }

    /**
     * 打印订单
     * @param view
     */
    public void printOrder1(View view){
        PrintTerUtils.getPrintTerUtils(this).toPrintOrder();
    }

    /**
     * 打印回收单
     * @param view
     */
    public void printOrder2(View view){
        PrintTerUtils.getPrintTerUtils(this).toPrint2();
    }

    /**
     * 打印回收单
     * @param view
     */
    public void printOrder3(View view){
        PrintTerUtils.getPrintTerUtils(this).toPrint3();
    }
}

四、打印的图片

这里写图片描述
这里写图片描述

五、项目下载地址

https://github.com/qiwenming/QwmPrinterDemo

六、其他参考项目

6.1 串口通信打印

80mm https://github.com/antwari/print

58mm https://github.com/antwari/printDemo

6.2 usb等打印

https://github.com/CelloscopeRnD/PrintingDemo

<script type="text/javascript"> $(function () { $('pre.prettyprint code').each(function () { var lines = $(this).text().split('\n').length; var $numbering = $('<ul/>').addClass('pre-numbering').hide(); $(this).addClass('has-numbering').parent().append($numbering); for (i = 1; i <= lines; i++) { $numbering.append($('<li/>').text(i)); }; $numbering.fadeIn(1700); }); }); </script>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值