Android下的POS打印機(jī)調(diào)用的簡單實現(xiàn)
本文基于GP58系列,它可以兼容ESC/POS指令集,對EPSON的打印機(jī)通用.
Android下的設(shè)備調(diào)試,如果設(shè)備提供了驅(qū)動,按照廠家的驅(qū)動調(diào)試即可;設(shè)備未提供驅(qū)動,只能按照通用的方法進(jìn)行調(diào)試。這里采用的是調(diào)用USB接口來控制打印機(jī)輸出。
1.首先獲取USB管理器
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);
}
使用一個延遲意圖來接收usb接入時的廣播,當(dāng)廣播接收到時,說明有新的設(shè)備接入。
添加一個boardcast action
private static final String ACTION_USB_PERMISSION = "com.android.example.USB_PERMISSION";
private final BroadcastReceiver mUsbReceiver = new BroadcastReceiver() {
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) {
setDevice(device);
} else {
Closeusb();
// mDevice = device;
}
} else {
Log.d(TAG, "permission denied for device " + device);
}
}
}
}
};
取到usb設(shè)備的引用,android系統(tǒng)會詢問你是否允許設(shè)備訪問,默認(rèn)為false;當(dāng)允許了訪問之后,會判斷USB的引用是否為null,如果不為空則會調(diào)用setDevice來創(chuàng)建一個Connection,否則會關(guān)閉本次連接。
在setDevice中,我們可以獲取設(shè)備的功能集(UsbInterface),也可以獲取通信通道(UsbEndpoint),同時也創(chuàng)建了host與device的連接用來傳輸數(shù)據(jù)。
private void setDevice(UsbDevice device) {
if (device != null) {
UsbInterface intf = null;
UsbEndpoint ep = null;
int InterfaceCount = device.getInterfaceCount();
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, "沒有打印機(jī)接口");
return;
}
mEndpointIntr = ep;
UsbDeviceConnection connection = mUsbManager.openDevice(device);
if (connection != null && connection.claimInterface(intf, true)) {
Log.i(TAG, "打開成功! ");
mConnection = connection;
} else {
Log.i(TAG, "打開失敗! ");
mConnection = null;
}
}
}
2.在相關(guān)的類中新建一個UsbAdmin,調(diào)用openUsb,這里首先是走了上面的setDevice()方法,獲取到了設(shè)備的引用,當(dāng)連接通道建立時列出所有USB設(shè)備,當(dāng)設(shè)備的引用不存在時同樣列出所有的USB設(shè)備,并且都請求獲取USB權(quán)限。
public void openUsb() {
if (mDevice != null) {
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 {
HashMap<String, UsbDevice> deviceList = mUsbManager.getDeviceList();
Iterator<UsbDevice> deviceIterator = deviceList.values().iterator();
while (deviceIterator.hasNext()) {
UsbDevice device = deviceIterator.next();
mUsbManager.requestPermission(device, mPermissionIntent);
}
}
}
3.當(dāng)上面兩部都走完了之后,我們就可以發(fā)送指令來控制已經(jīng)建立連接的打印機(jī)了,這里我們使用的是標(biāo)準(zhǔn)的ESC/POS指令集,為硬件默認(rèn),貼出代碼,這里的指令集采用的是十進(jìn)制表示形式,也可以替換成十六進(jìn)制。
public class printerCmdUtils {
/**
* 這些數(shù)據(jù)源自愛普生指令集,為POS機(jī)硬件默認(rèn)
*/
public static final byte ESC = 27;//換碼
public static final byte FS = 28;//文本分隔符
public static final byte GS = 29;//組分隔符
public static final byte DLE = 16;//數(shù)據(jù)連接換碼
public static final byte EOT = 4;//傳輸結(jié)束
public static final byte ENQ = 5;//詢問字符
public static final byte SP = 32;//空格
public static final byte HT = 9;//橫向列表
public static final byte LF = 10;//打印并換行(水平定位)
public static final byte CR = 13;//歸位鍵
public static final byte FF = 12;//走紙控制(打印并回到標(biāo)準(zhǔn)模式(在頁模式下) )
public static final byte CAN = 24;//作廢(頁模式下取消打印數(shù)據(jù) )
//------------------------打印機(jī)初始化-----------------------------
/**
* 打印機(jī)初始化
* @return
*/
public static byte[] init_printer()
{
byte[] result = new byte[2];
result[0] = ESC;
result[1] = 64;
return result;
}
//------------------------換行-----------------------------
/**
* 換行
* @param lineNum要換幾行
* @return
*/
public static byte[] nextLine(int lineNum)
{
byte[] result = new byte[lineNum];
for(int i=0;i<lineNum;i++)
{
result[i] = LF;
}
return result;
}
//------------------------下劃線-----------------------------
/**
* 繪制下劃線(1點寬)
* @return
*/
public static byte[] underlineWithOneDotWidthOn()
{
byte[] result = new byte[3];
result[0] = ESC;
result[1] = 45;
result[2] = 1;
return result;
}
/**
* 繪制下劃線(2點寬)
* @return
*/
public static byte[] underlineWithTwoDotWidthOn()
{
byte[] result = new byte[3];
result[0] = ESC;
result[1] = 45;
result[2] = 2;
return result;
}
/**
* 取消繪制下劃線
* @return
*/
public static byte[] underlineOff()
{
byte[] result = new byte[3];
result[0] = ESC;
result[1] = 45;
result[2] = 0;
return result;
}
//------------------------加粗-----------------------------
/**
* 選擇加粗模式
* @return
*/
public static byte[] boldOn()
{
byte[] result = new byte[3];
result[0] = ESC;
result[1] = 69;
result[2] = 0xF;
return result;
}
/**
* 取消加粗模式
* @return
*/
public static byte[] boldOff()
{
byte[] result = new byte[3];
result[0] = ESC;
result[1] = 69;
result[2] = 0;
return result;
}
//------------------------對齊-----------------------------
/**
* 左對齊
* @return
*/
public static byte[] alignLeft()
{
byte[] result = new byte[3];
result[0] = ESC;
result[1] = 97;
result[2] = 0;
return result;
}
/**
* 居中對齊
* @return
*/
public static byte[] alignCenter()
{
byte[] result = new byte[3];
result[0] = ESC;
result[1] = 97;
result[2] = 1;
return result;
}
/**
* 右對齊
* @return
*/
public static byte[] alignRight()
{
byte[] result = new byte[3];
result[0] = ESC;
result[1] = 97;
result[2] = 2;
return result;
}
/**
* 水平方向向右移動col列
* @param col
* @return
*/
public static byte[] set_HT_position( byte col )
{
byte[] result = new byte[4];
result[0] = ESC;
result[1] = 68;
result[2] = col;
result[3] = 0;
return result;
}
//------------------------字體變大-----------------------------
/**
* 字體變大為標(biāo)準(zhǔn)的n倍
* @param num
* @return
*/
public static byte[] fontSizeSetBig(int num)
{
byte realSize = 0;
switch (num)
{
case 1:
realSize = 0;break;
case 2:
realSize = 17;break;
case 3:
realSize = 34;break;
case 4:
realSize = 51;break;
case 5:
realSize = 68;break;
case 6:
realSize = 85;break;
case 7:
realSize = 102;break;
case 8:
realSize = 119;break;
}
byte[] result = new byte[3];
result[0] = 29;
result[1] = 33;
result[2] = realSize;
return result;
}
//------------------------字體變小-----------------------------
/**
* 字體取消倍寬倍高
* @param num
* @return
*/
public static byte[] fontSizeSetSmall(int num)
{
byte[] result = new byte[3];
result[0] = ESC;
result[1] = 33;
return result;
}
//------------------------切紙-----------------------------
/**
* 進(jìn)紙并全部切割
* @return
*/
public static byte[] feedPaperCutAll()
{
byte[] result = new byte[4];
result[0] = GS;
result[1] = 86;
result[2] = 65;
result[3] = 0;
return result;
}
/**
* 進(jìn)紙并切割(左邊留一點不切)
* @return
*/
public static byte[] feedPaperCutPartial()
{
byte[] result = new byte[4];
result[0] = GS;
result[1] = 86;
result[2] = 66;
result[3] = 0;
return result;
}
//------------------------切紙-----------------------------
public static byte[] byteMerger(byte[] byte_1, byte[] byte_2){
byte[] byte_3 = new byte[byte_1.length+byte_2.length];
System.arraycopy(byte_1, 0, byte_3, 0, byte_1.length);
System.arraycopy(byte_2, 0, byte_3, byte_1.length, byte_2.length);
return byte_3;
}
public static byte[] byteMerger(byte[][] byteList){
int length = 0;
for(int i=0;i<byteList.length;i++)
{
length += byteList[i].length;
}
byte[] result = new byte[length];
int index = 0;
for(int i=0;i<byteList.length;i++)
{
byte[] nowByte = byteList[i];
for(int k=0;k<byteList[i].length;k++)
{
result[index] = nowByte[k];
index++;
}
}
return result;
}
}
4.在以上都完成之后,就可以把你需要的字符串轉(zhuǎn)換成byte數(shù)組并調(diào)用sendCommand方法來進(jìn)行打印了
@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, "發(fā)送失??! " + len);
} else {
Result = true;
Log.i(TAG, "發(fā)送" + len + "字節(jié)數(shù)據(jù)");
}
}
return Result;
len = mConnection.bulkTransfer(mEndpointIntr, Content, Content.length, 10000);
這一步僅僅加了同步鎖,并未開啟一個新的線程去處理,在本機(jī)上沒有問題,但上面的USB通信機(jī)制的文章有提到要放到異步線程,這里需要注意。
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- Android實現(xiàn)PDF預(yù)覽打印功能
- Android gradle插件打印時間戳的方法詳解
- Android編程實現(xiàn)計算兩個日期之間天數(shù)并打印所有日期的方法
- Android中如何安全地打印日志詳解
- Mac 下 Android Studio 不打印日志的解決辦法
- Android jni調(diào)試打印char陣列的實例詳解
- Android 藍(lán)牙連接 ESC/POS 熱敏打印機(jī)打印實例(ESC/POS指令篇)
- Android 藍(lán)牙連接 ESC/POS 熱敏打印機(jī)打印實例(藍(lán)牙連接篇)
- Android打印機(jī)--小票打印格式及模板設(shè)置實例代碼
- Android進(jìn)階——安卓調(diào)用ESC/POS打印機(jī)打印實例
- Android手機(jī)通過藍(lán)牙連接佳博打印機(jī)的實例代碼
- Android實現(xiàn)系統(tǒng)打印功能
相關(guān)文章
Android中Fragmen首選項使用自定義的ListPreference的方法
Android中Fragmen的首選項可以使用自定義的ListPreference,這樣Fragment的PreferenceFragment就可以更方便地保存配置信息,需要的朋友可以參考下2016-05-05
Android中HttpURLConnection類使用介紹
早些時候其實我們都習(xí)慣性使用HttpClient,但是后來Android6.0之后不再支持HttpClient,需要添加Apache的jar才行,所以,就有很多開發(fā)者放棄使用HttpClient了,HttpURLConnection畢竟是標(biāo)準(zhǔn)Java接口(java.net) ,適配性還是很強(qiáng)的2022-12-12
Android中使用的定時針(刷新頁面請求服務(wù)器)詳解
這篇文章主要介紹了Android中使用的定時針(刷新頁面請求服務(wù)器)詳解的相關(guān)資料,需要的朋友可以參考下2016-12-12
ionic監(jiān)聽android返回鍵實現(xiàn)“再按一次退出”功能
本篇文章主要介紹了ionic監(jiān)聽android返回鍵實現(xiàn)“再按一次退出”功能,非常具有實用價值,需要的朋友可以參考下2018-02-02
Android ProgressBar進(jìn)度條使用詳解
ProgressBar進(jìn)度條,分為旋轉(zhuǎn)進(jìn)度條和水平進(jìn)度條,進(jìn)度條的樣式根據(jù)需要自定義,這篇文章主要介紹了Android ProgressBar進(jìn)度條使用方法,感興趣的小伙伴們可以參考一下2016-02-02
Android學(xué)習(xí)之Broadcast的簡單使用
這篇文章主要為大家詳細(xì)介紹了Android學(xué)習(xí)之Broadcast的簡單使用方法,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-08-08
Android編程之線性布局LinearLayout實例簡析
這篇文章主要介紹了Android編程之線性布局LinearLayout用法,結(jié)合實例形式簡單分析了Android線性布局的使用技巧,需要的朋友可以參考下2016-01-01

