您的位置:首页 > 移动开发 > Android开发

androidUSB通信——打印机

2016-03-11 11:33 453 查看
androidUSB通信打印机
一usb基础

二创建基本usb通信
1qwm_usb_xmlxml说明

2AndroidManifestxml清单文件配置

3UsbDemoActivityjava usb的操作类

三使用jar包打印
1 regoPrintLibV3005jar包中 regoPrinter 类的主要方法说明

1AndroidManifestxml配置说明

2 PrintTerUtilsjava 打印工具类

3 MainActivityjava

四打印的图片

五项目下载地址

六其他参考项目
1 串口通信打印

2 usb等打印

androidUSB通信——打印机

本文主要解决一下几个问题:

- usb的基本通信

- usb的基本通信打印文字

- 使用jar包打印一个订单信息

一、usb基础

Android 支持各种 USB 外围设备,通过两种模式来支持 Android USB 外设 (实现了 Android 外设协议的硬件): USB 外设模式和 USB 主机模式。在 USB 外设模式下,外部 USB 硬件(装有 Android 的设备要连接的外部设备)充当 USB 主机。

关于usb的介绍可以查看:

/article/4602759.html

我们这里面使用的是 usb host方式,关于usb host的介绍可以查看官网文档,也可以查看:

/article/10016151.html

二、创建基本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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: