最近的一个项目有一个需求,要求通过pad的蓝牙去连接l蓝牙打印机去打印单据,就是点击一个按钮去触发生成单据>>保存到数据库
>>蓝牙打印。首先想要实现蓝牙连接,然后去调用Gprinter的SDK,在这里我使用的是Gprinter SDK2.1的版本,而SDK2.2与SDK2.1
的API有不同的地方,这里就以SDK2.1为例。
1、首先要导入jar包、添加依赖,如果没有SDK2.1的版本可以去http://download.csdn.net/download/zabio/9382570下载,
我这里用的是Eclipse。
2、添加权限
<!-- 管理蓝牙设备的权限 -->
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<!-- 使用蓝牙设备的权限 -->
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
3、在AndroidManifest.xml文件中注册打印服务
<service
android:name="com.gprinter.service.GpPrintService"
android:label="GpPrintService"
android:process=":remote"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="com.gprinter.aidl.GpPrintService" />
</intent-filter>
</service>
4、 新建包名为com.gprinter.aidl,向包中添加GpService.aidl文件,代码如下:
package com.gprinter.aidl;
interface GpService{
int openPort(int PrinterId,int PortType,String DeviceName,int PortNumber);
void closePort(int PrinterId);
int getPrinterConnectStatus(int PrinterId);
int printeTestPage(int PrinterId);
int queryPrinterStatus(int PrinterId,int Timesout);
int getPrinterCommandType(int PrinterId);
int sendEscCommand(int PrinterId, String b64);
int sendTscCommand(int PrinterId, String b64);
}
5、在onCreate初始化方法里面启动并绑定服务,我这里是Fragment,所以用的Context。
//变量我放这里了,如有错误,自己修改
private int connectState;
private String deviceAddress;//蓝牙mac地址
private BluetoothSocket socket;//蓝牙socket
private ConnectThread mThread;//连接的蓝牙线程
private MyBroadcastReceiver receiver;//蓝牙搜索的广播
private GpService mGpService = null;
private PrinterServiceConnection mConn = null;
private BluetoothAdapter adapter;//蓝牙适配器
private BluetoothDevice mBluetoothDevice; //蓝牙设备
private void startService() {
Intent i = new Intent(mContext, GpPrintService.class);
mContext.startService(i);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public void connection() {
mConn = new PrinterServiceConnection();
Intent intent = new Intent("com.gprinter.aidl.GpPrintService");
intent.setPackage(mContext.getPackageName());
mContext.bindService(intent, mConn, Context.BIND_AUTO_CREATE); // bindService
}
class PrinterServiceConnection implements ServiceConnection {
@Override
public void onServiceDisconnected(ComponentName name) {
Logger.e("ServiceConnection", "onServiceDisconnected() called");
mGpService = null;
}
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
Logger.e("ServiceConnection", "onServiceConnected() called");
mGpService = GpService.Stub.asInterface(service);
}
};
连接蓝牙,由于是第一次使用蓝牙去调用打印,这里只说明我自己的方法,取消配对的对话框不一定成功。
public void searchBlueToothDevice() {
// 检查设备是否支持蓝牙
adapter = BluetoothAdapter.getDefaultAdapter();
if (adapter == null) {
// 设备不支持蓝牙
Toast.makeText(mContext,"Your device doesn't support BlueTooth",0).show();
return;
}
// 如果蓝牙已经关闭就打开蓝牙
if (!adapter.isEnabled()) {
Logger.e(TAG, "device close");
Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
intent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 300);
return;
}
// 获取已配对的蓝牙设备
Set<BluetoothDevice> devices = adapter.getBondedDevices();
// 遍历
int count = 0;
for (BluetoothDevice pairedDevice : devices) {
if (pairedDevice.getName() == null) {
return;
} else if (pairedDevice.getName().startsWith("Gprinter")) {
count++;
deviceAddress = pairedDevice.getAddress();
//赋值为全局变量
mBluetoothDevice = adapter.getRemoteDevice(deviceAddress);
//连接蓝牙
connect(deviceAddress, mBluetoothDevice);
break;
}
}
// count=0,说明没有配对,搜索设备
if (adapter.isEnabled() && count == 0) {
adapter.startDiscovery();
if (receiver != null) {
mContext.unregisterReceiver(receiver);
receiver = null;
}
// 设置广播信息过滤
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(BluetoothDevice.ACTION_FOUND);
intentFilter.addAction(BluetoothAdapter.ACTION_DISCOVERY_STARTED);
intentFilter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
intentFilter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);
intentFilter.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED);
if (receiver == null) {
receiver = new MyBroadcastReceiver();
// 注册广播接收器,接收并处理搜索结果
mContext.registerReceiver(receiver, intentFilter);
}
}
}
public class MyBroadcastReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (BluetoothDevice.ACTION_FOUND.equals(action)) {
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
if (device == null) {
return;
}
if (device.getName() == null) {
return;
}
if (device.getName().startsWith("Gprinter")) {
deviceAddress = device.getAddress();
Logger.e(TAG, device.getName() + "---ACTION_FOUND");
adapter.cancelDiscovery();
mBluetoothDevice = adapter.getRemoteDevice(deviceAddress);
connectState = device.getBondState();
switch (connectState) {
// 未配对
case BluetoothDevice.BOND_NONE:
// 配对
try {
setPin(mBluetoothDevice.getClass(), mBluetoothDevice, "0000");
Method createBondMethod = mBluetoothDevice.getClass().getMethod("createBond");
createBondMethod.invoke(mBluetoothDevice);
cancelPairingUserInput(mBluetoothDevice.getClass(), mBluetoothDevice);
} catch (Exception e) {
e.printStackTrace();
}
break;
// 已配对
case BluetoothDevice.BOND_BONDED:
if (device.getName().startsWith("Gprinter")) {
connect(deviceAddress, mBluetoothDevice);
}
break;
}
}
} else if (BluetoothDevice.ACTION_BOND_STATE_CHANGED.equals(action)) {
// 状态改变的广播
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
if (device.getName() == null) {
return;
}
if (device.getName().startsWith("Gprinter")) {
deviceAddress = device.getAddress();
Logger.e(TAG, device.getName() + "---ACTION_BOND_STATE_CHANGED");
mBluetoothDevice = adapter.getRemoteDevice(deviceAddress);
connectState = device.getBondState();
switch (connectState) {
case BluetoothDevice.BOND_NONE:
break;
case BluetoothDevice.BOND_BONDING:
break;
case BluetoothDevice.BOND_BONDED:
if (device.getName().startsWith("Gprinter")) {
connect(deviceAddress, mBluetoothDevice);
}
break;
}
}
}
}
}
@SuppressWarnings({ "rawtypes", "unchecked" })
public boolean setPin(Class btClass, BluetoothDevice btDevice, String str) throws Exception {
try {
Method removeBondMethod = btClass.getDeclaredMethod("setPin", new Class[] { byte[].class });
Boolean returnValue = (Boolean) removeBondMethod.invoke(btDevice, new Object[] { str.getBytes() });
Log.e("returnValue", "" + returnValue);
} catch (SecurityException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
return true;
}
// 取消用户输入
@SuppressWarnings({ "unchecked", "rawtypes" })
public boolean cancelPairingUserInput(Class btClass, BluetoothDevice device) throws Exception {
Method createBondMethod = btClass.getMethod("cancelPairingUserInput");
// cancelBondProcess()
Boolean returnValue = (Boolean) createBondMethod.invoke(device);
return returnValue.booleanValue();
}
/**
* 启动连接蓝牙的线程方法
*
* @param macAddress
* @param device
*/
public synchronized void connect(String macAddress, BluetoothDevice device) {
if (mThread != null) {
mThread.interrupt();
mThread = null;
}
if (socket != null) {
try {
mGpService.closePort(0);
} catch (Exception e) {
e.printStackTrace();
}
socket = null;
}
mThread = new ConnectThread(macAddress, device);
mThread.start();
}
private class ConnectThread extends Thread {
private BluetoothDevice mmDevice;
private OutputStream mmOutStream;
public ConnectThread(String mac, BluetoothDevice device) {
mmDevice = device;
String SPP_UUID = "00001101-0000-1000-8000-00805f9b34fb";
try {
if (socket == null) {
socket = device.createRfcommSocketToServiceRecord(UUID.fromString(SPP_UUID));
}
} catch (Exception e) {
e.printStackTrace();
}
}
public void run() {
// Cancel discovery because it will slow down the connection
adapter.cancelDiscovery();
try {
// Connect the device through the socket. This will block
// until it succeeds or throws an exception
Logger.e(TAG, "连接socket");
if (socket.isConnected()) {
Logger.e(TAG, "已经连接过了");
} else {
// socket.connect();
if (socket != null) {
try {
Logger.e(TAG, mGpService + "--1--" + mBluetoothDevice);
if (mGpService != null) {
int state = mGpService.getPrinterConnectStatus(0);
switch (state) {
case GpDevice.STATE_CONNECTED:
break;
case GpDevice.STATE_LISTEN:
Logger.e(TAG, "state:STATE_LISTEN");
break;
case GpDevice.STATE_CONNECTING:
Logger.e(TAG, "state:STATE_CONNECTING");
break;
case GpDevice.STATE_NONE:
Logger.e(TAG, "state:STATE_NONE");
registerBroadcast();
mGpService.openPort(0, 4, mBluetoothDevice.getAddress(), 0);
break;
default:
Logger.e(TAG, "state:default");
break;
}
} else {
Logger.e(TAG, "mGpService IS NULL");
}
//
} catch (Exception e) {
e.printStackTrace();
}
// connectToPrinter();
}
}
} catch (Exception connectException) {
// Unable to connect; close the socket and get out
Logger.e(TAG, "Unable to connect");
try {
if (socket != null) {
mGpService.closePort(0);
socket = null;
// CommonUtils.showToast(mContext, "failed to connect");
}
} catch (Exception closeException) {
// failed to close socket
}
return;
}
}
}
public static final String ACTION_CONNECT_STATUS = "action.connect.status";
private void registerBroadcast() {
IntentFilter filter = new IntentFilter();
filter.addAction(ACTION_CONNECT_STATUS);
mContext.registerReceiver(printerStatusBroadcastReceiver, filter);
}
private BroadcastReceiver printerStatusBroadcastReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
if (ACTION_CONNECT_STATUS.equals(intent.getAction())) {
int type = intent.getIntExtra(GpPrintService.CONNECT_STATUS, 0);
int id = intent.getIntExtra(GpPrintService.PRINTER_ID, 0);
if (type == GpDevice.STATE_CONNECTING) {
Logger.e(TAG, "STATE_CONNECTING");
} else if (type == GpDevice.STATE_NONE) {
Logger.e(TAG, "STATE_NONE");
} else if (type == GpDevice.STATE_VALID_PRINTER) {
Logger.e(TAG, "STATE_VALID_PRINTER");
} else if (type == GpDevice.STATE_INVALID_PRINTER) {
Logger.e(TAG, "STATE_INVALID_PRINTER");
} else if (type == GpDevice.STATE_CONNECTED) {
Logger.e(TAG, "STATE_CONNECTED");
mContext.unregisterReceiver(printerStatusBroadcastReceiver);
getPrinterStatusClicked(id);
} else if (type == GpDevice.STATE_LISTEN) {
Logger.e(TAG, "STATE_LISTEN");
}
}
public void getPrinterStatusClicked(int id) {
try {
int status = mGpService.queryPrinterStatus(0, 500);
String str = new String();
if (status == GpCom.STATE_NO_ERR) {
str = "打印机正常";
int state = mGpService.getPrinterCommandType(0);
if (state == GpCom.ESC_COMMAND) {
printData();
} else {
}
} else if ((byte) (status & GpCom.STATE_OFFLINE) > 0) {
str = "The printer is out of service,please try again!";
} else if ((byte) (status & GpCom.STATE_PAPER_ERR) > 0) {
str = "There is no Pager in the Printer!";
} else if ((byte) (status & GpCom.STATE_COVER_OPEN) > 0) {
str = "The cover of the printer is not closed!";
} else if ((byte) (status & GpCom.STATE_ERR_OCCURS) > 0) {
str = "The printer made a mistake!";
}
Toast.makeText(mContext, "打印机:" + '0' + " 状态:" + str, Toast.LENGTH_SHORT).show();
} catch (RemoteException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
7、printData()方法里的内容,参考如下:
8、关键代码是sendEscConmand方法的调用,不过SDK2.1打印条形码的长度有限制,所以可以自己生成我一维码图片让后去打
印: com.google.zxing包的一维码打印,导入jar包:可以网上下载
private Bitmap getCodeBitMap(String str) {
int size = str.length();
for (int i = 0; i < size; i++) {
int c = str.charAt(i);
if ((19968 <= c && c < 40623)) {
// Toast.makeText(CreateCodeActivity.this, "生成条形码的时刻不能是中文", Toast.LENGTH_SHORT).show();
return null;
}
}
Bitmap bmp = null;
try {
if (str != null && !"".equals(str)) {
bmp = CreateOneDCode(str);
}
} catch (WriterException e) {
e.printStackTrace();
}
return bmp;
}
/**
* 用于将给定的内容生成成一维码 注:目前生成内容为中文的话将直接报错,要修改底层jar包的内容
*
* @param content
* 将要生成一维码的内容
*
* @return 返回生成好的一维码bitmap
* @throws WriterException
* WriterException异常
*/
public Bitmap CreateOneDCode(String content) throws WriterException {
// 生成一维条码,编码时指定大小,不要生成了图片以后再进行缩放,这样会模糊导致识别失败
BitMatrix matrix = null;
matrix = new MultiFormatWriter().encode(content,
BarcodeFormat.CODE_128, 260, 90);
int width = matrix.getWidth();
int height = matrix.getHeight();
int[] pixels = new int[width * height];
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
if (matrix.get(x, y)) {
pixels[y * width + x] = mContext.getResources().getColor(R.color.black);
} else {
pixels[y * width + x] = mContext.getResources().getColor(R.color.white); ;
}
}
}
Bitmap bitmap = Bitmap.createBitmap(width, height,
Bitmap.Config.ARGB_8888);
// 通过像素数组生成bitmap,具体参考api
bitmap.setPixels(pixels, 0, width, 0, 0, width, height);
return bitmap;
}9、打印的条形码要传入一个字符串--我这里是实体类里的一个字段
第一次写博客,可能会存在一些问题,望大家见谅·如果有不懂的可以留言。
Android pad 连接蓝牙打印机Gprinter---实现蓝牙打印功能
原文:http://blog.csdn.net/algerhf/article/details/52240212