当前位置: 移动技术网 > IT编程>移动开发>Android > Android手机通过蓝牙连接佳博打印机的实例代码

Android手机通过蓝牙连接佳博打印机的实例代码

2019年07月24日  | 移动技术网IT编程  | 我要评论

热血高校主题曲歌词,爱上霸道校董,lgp970论坛

所使用的打印机为佳博打印机,支持蓝牙、wifi、usb我所使用的是通过蓝牙来连接。

在网上找到一个佳博官方针对安卓开发的app源码,但是各种的跳转,没有看太懂,所以又去问度娘,找到了一个不错的文章

android对于蓝牙开发从2.0版本的sdk才开始支持,而且模拟器不支持,测试至少需要两部手机,所以制约了很多技术人员的开发。

1. 首先,要操作蓝牙,先要在androidmanifest.xml里加入权限

// 管理蓝牙设备的权限 
<uses-permissionandroid:name="android.permission.bluetooth_admin" />
// 使用蓝牙设备的权限 
<uses-permissionandroid:name="android.permission.bluetooth" />

2.打开蓝牙

获得蓝牙适配器(android.bluetooth.bluetoothadapter),检查该设备是否支持蓝牙,如果支持,就打开蓝牙。

// 检查设备是否支持蓝牙 
adapter = bluetoothadapter.getdefaultadapter(); 
if (adapter == null) 
{ 
// 设备不支持蓝牙 
} 
// 打开蓝牙 
if (!adapter.isenabled()) 
{ 
intent intent = new intent(bluetoothadapter.action_request_enable); 
// 设置蓝牙可见性,最多300秒 
intent.putextra(bluetoothadapter.extra_discoverable_duration,300);
context.startactivity(intent); 
}

3.获取已配对的蓝牙设备(android.bluetooth.bluetoothdevice)

首次连接某蓝牙设备需要先配对,一旦配对成功,该设备的信息会被保存,以后连接时无需再配对,所以已配对的设备不一定是能连接的。

bluetoothadapter adapter = bluetoothadapter.getdefaultadapter(); 
set<bluetoothdevice> devices = adapter.getbondeddevices(); 
for(int i=0; i<devices.size(); i++) 
{ 
bluetoothdevice device =
bluetoothdevice)devices.iterator().next(); 
system.out.println(device.getname()); 
} 

4.搜索周围的蓝牙设备

适配器搜索蓝牙设备后将结果以广播形式传出去,所以需要自定义一个继承广播的类,在onreceive方法中获得并处理蓝牙设备的搜索结果。

// 设置广播信息过滤 
intentfilter intentfilter = new intentfilter(); 
intentfilter.addaction(bluetoothdevice.action_found); 
intentfilter.addaction(bluetoothdevice.action_bond_state_changed); 
intentfilter.addaction(bluetoothadapter.action_scan_mode_changed); 
intentfilter.addaction(bluetoothadapter.action_state_changed); 
// 注册广播接收器,接收并处理搜索结果 
context.registerreceiver(receiver, intentfilter); 
// 寻找蓝牙设备,android会将查找到的设备以广播形式发出去 
adapter.startdiscovery(); 
自定义广播类
private broadcastreceiver receiver = new 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); 
system.out.println(device.getname()); 
} 
} 
}

5.蓝牙设备的配对和状态监视

private broadcastreceiver receiver = new 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); 
system.out.println(device.getname()); 
// 如果查找到的设备符合要连接的设备,处理 
if (device.getname().equalsignorecase(name)) { 
// 搜索蓝牙设备的过程占用资源比较多,一旦找到需要连接的设备后需要及时关闭搜索 
adapter.canceldiscovery(); 
// 获取蓝牙设备的连接状态 
connectstate = device.getbondstate(); 
switch (connectstate) { 
// 未配对 
case bluetoothdevice.bond_none: 
// 配对 
try { 
method createbondmethod = bluetoothdevice.class.getmethod("createbond"); 
createbondmethod.invoke(device); 
} catch (exception e) { 
e.printstacktrace(); 
} 
break; 
// 已配对 
case bluetoothdevice.bond_bonded: 
try { 
// 连接 
connect(device); 
} catch (ioexception e) { 
e.printstacktrace(); 
} 
break; 
} 
} 
} else if(bluetoothdevice.action_bond_state_changed.equals(action)) { 
// 状态改变的广播 
bluetoothdevice device = intent.getparcelableextra(bluetoothdevice.extra_device); 
if (device.getname().equalsignorecase(name)) { 
connectstate = device.getbondstate(); 
switch (connectstate) { 
case bluetoothdevice.bond_none: 
break; 
case bluetoothdevice.bond_bonding: 
break; 
case bluetoothdevice.bond_bonded: 
try { 
// 连接 
connect(device); 
} catch (ioexception e) { 
e.printstacktrace(); 
} 
break; 
} 
} 
} 
} 
}

6.蓝牙设备的连接

private void connect(bluetoothdevice device) throws ioexception { 
// 固定的uuid 
final string spp_uuid = "00001101-0000-1000-8000-00805f9b34fb"; 
uuid uuid = uuid.fromstring(spp_uuid); 
bluetoothsocket socket = device.createrfcommsockettoservicerecord(uuid); 
socket.connect(); 
} 
private void connect(bluetoothdevice device) throws ioexception { 
// 固定的uuid 
final string spp_uuid = "00001101-0000-1000-8000-00805f9b34fb"; 
uuid uuid = uuid.fromstring(spp_uuid); 
bluetoothsocket socket = device.createrfcommsockettoservicerecord(uuid); 
socket.connect(); 
}

1.bluetoothadapter 顾名思义,蓝牙适配器,直到我们建立bluetoothsocket连接之前,都要不断操作它

bluetoothadapter里的方法很多,常用的有以下几个:

canceldiscovery() 根据字面意思,是取消发现,也就是说当我们正在搜索设备的时候调用这个方法将不再继续搜索

disable()关闭蓝牙

enable()打开蓝牙,这个方法打开蓝牙不会弹出提示,更多的时候我们需要问下用户是否打开,一下这两行代码同样是打开蓝牙,不过会提示用户:

intemtenabler=new intent(bluetoothadapter.action_request_enable);

startactivityforresult(enabler,recode);//同startactivity(enabler);

getaddress()获取本地蓝牙地址

getdefaultadapter()获取默认bluetoothadapter,实际上,也只有这一种方法获取bluetoothadapter

getname()获取本地蓝牙名称

getremotedevice(string address)根据蓝牙地址获取远程蓝牙设备

getstate()获取本地蓝牙适配器当前状态(感觉可能调试的时候更需要)

isdiscovering()判断当前是否正在查找设备,是返回true

isenabled()判断蓝牙是否打开,已打开返回true,否则,返回false

listenusingrfcommwithservicerecord(string name,uuid uuid)根据名称,uuid创建并返回bluetoothserversocket,这是创建bluetoothsocket服务器端的第一步

startdiscovery()开始搜索,这是搜索的第一步

2.bluetoothdevice看名字就知道,这个类描述了一个蓝牙设备

createrfcommsockettoservicerecord(uuiduuid)根据uuid创建并返回一个bluetoothsocket

这个方法也是我们获取bluetoothdevice的目的——创建bluetoothsocket

这个类其他的方法,如getaddress(),getname(),同bluetoothadapter

3.bluetoothserversocket如果去除了bluetooth相信大家一定再熟悉不过了,既然是socket,方法就应该都差不多,

这个类一种只有三个方法

两个重载的accept(),accept(inttimeout)两者的区别在于后面的方法指定了过时时间,需要注意的是,执行这两个方法的时候,直到接收到了客户端的请求(或是过期之后),都会阻塞线程,应该放在新线程里运行!

还有一点需要注意的是,这两个方法都返回一个bluetoothsocket,最后的连接也是服务器端与客户端的两个bluetoothsocket的连接

close()这个就不用说了吧,翻译一下——关闭!

4.bluetoothsocket,跟bluetoothserversocket相对,是客户端

一共5个方法,不出意外,都会用到

close(),关闭

connect()连接

getinptustream()获取输入流

getoutputstream()获取输出流

getremotedevice()获取远程设备,这里指的是获取bluetoothsocket指定连接的那个远程蓝牙设备

根据这篇文章只是更改了最后的蓝牙连接部分(因为佳博打印机有自己的sdk,sdk中有自己的连接方法)将下载的demo中的gprintersdkv22.jar和xutils-2.6.14.jar两个包导入,之后的连接方法如下:

/**
*连接
*/
private voidconnect() {
intrel =0;
try{//使用端口1,4代表模式为蓝牙模式,蓝牙地址,最后默认为0
rel = mgpservice.openport(1,4,adressdata.get(loction),0);
}catch(remoteexception e) {
e.printstacktrace();
}
gpcom.error_code r = gpcom.error_code.values()[rel];
if(r != gpcom.error_code.success) {
if(r == gpcom.error_code.device_already_open) {
//开启成功
}else{
uiutils.showmessage(gpcom.geterrortext(r));
}
}else{
progressdialogutil.dismiss(buletoothactivity.this);
uiutils.showmessage("失败");
}
}

不要忘记的就是mgpservice是佳博sdk的一个自己的服务,要先获取,并与activity进行绑定;

protected voidoncreate(bundle savedinstancestate) {
super.oncreate(savedinstancestate);
setcontentview(r.layout.activity_buletooth);
connection();
}
private voidconnection() {
conn=newprinterserviceconnection();
intent intent =newintent(this, gpprintservice.class);
this.bindservice(intent,conn, context.bind_auto_create);// bindservice
}
classprinterserviceconnectionimplementsserviceconnection {
@override
public void onservicedisconnected(componentname name) {
mgpservice=null;
}
@override
public void onserviceconnected(componentname name, ibinder service) {
mgpservice= gpservice.stub.asinterface(service);
}
}

还要在清单文件中去配置服务

<service
android:name="com.gprinter.service.gpprintservice"
android:enabled="true"
android:exported="true"
android:label="gpprintservice">
<intent-filter>
<actionandroid:name="com.gprinter.aidl.gpprintservice"/>
</intent-filter>
</service>
<serviceandroid:name="com.gprinter.service.allservice">
</service>

做完这些之后就大功告成,可以连接到打印机了,不过还是不能打印,还要进行一些打印的配置,由于我的项目的原因,连接和打印并没有在同一个界面,所以继续去研究佳博源码,发现如果前面链接已经成功的话,在另一个界面只需就行一个配置就可一直接打印打印也代码如下:

public classprintactivityextendsbaseactivityimplementsview.onclicklistener{
@bind(r.id.print_print)
buttonprint;
privategpservicemgpservice=null;
privateprinterserviceconnectionconn=null;
private static final int main_query_printer_status=0xfe;
private static final int request_print_label=0xfd;
private static final int request_print_receipt=0xfc;
private int mtotalcopies=0;
@override
protected void inithandler() {
handler=newhandler() {
@override
public void handlemessage(message msg) {
super.handlemessage(msg);
}
};
}
privatebroadcastreceivermbroadcastreceiver=newbroadcastreceiver() {
@override
public void onreceive(context context, intent intent) {
string action = intent.getaction();
log.d("tag", action);
// gpcom.action_device_real_status 为广播的intentfilter
if(action.equals(gpcom.action_device_real_status)) {
//业务逻辑的请求码,对应哪里查询做什么操作
intrequestcode = intent.getintextra(gpcom.extra_printer_request_code, -1);
//判断请求码,是则进行业务操作
if(requestcode ==main_query_printer_status) {
intstatus = intent.getintextra(gpcom.extra_printer_real_status,16);
string str;
if(status == gpcom.state_no_err) {
str ="打印机正常";
}else{
str ="打印机 ";
if((byte) (status & gpcom.state_offline) > 0) {
str +="脱机";
}
if((byte) (status & gpcom.state_paper_err) > 0) {
str +="缺纸";
}
if((byte) (status & gpcom.state_cover_open) > 0) {
str +="打印机开盖";
}
if((byte) (status & gpcom.state_err_occurs) > 0) {
str +="打印机出错";
}
if((byte) (status & gpcom.state_times_out) > 0) {
str +="查询超时";
}
}
toast.maketext(getapplicationcontext(),"打印机:"+1+"状态:"+ str, toast.length_short)
.show();
}else if(requestcode ==request_print_receipt) {
intstatus = intent.getintextra(gpcom.extra_printer_real_status,16);
if(status == gpcom.state_no_err) {
sendreceipt();
}else{
toast.maketext(printactivity.this,"query printer status error", toast.length_short).show();
}
}
}
}
};
@override
protected void inittitle() {
mtitletextmiddle.settext("打印");
}
private void connection() {
conn=newprinterserviceconnection();
intent intent =newintent(this, gpprintservice.class);
this.bindservice(intent,conn, context.bind_auto_create);// bindservice
}
classprinterserviceconnectionimplementsserviceconnection {
@override
public void onservicedisconnected(componentname name) {
log.i("serviceconnection","onservicedisconnected() called");
mgpservice=null;
}
@override
public void onserviceconnected(componentname name, ibinder service) {
mgpservice= gpservice.stub.asinterface(service);
}
}
@override
protected void oncreate(bundle savedinstancestate) {
super.oncreate(savedinstancestate);
setcontentview(r.layout.activity_print);
connection();
//注册实时状态查询广播
registerreceiver(mbroadcastreceiver,newintentfilter(gpcom.action_device_real_status));
/**
*票据模式下,可注册该广播,在需要打印内容的最后加入addqueryprinterstatus(),在打印完成后会接收到
* action为gpcom.action_device_status的广播,特别用于连续打印,
*可参照该sample中的sendreceiptwithresponse方法与广播中的处理
**/
registerreceiver(mbroadcastreceiver,newintentfilter(gpcom.action_receipt_response));
/**
*标签模式下,可注册该广播,在需要打印内容的最后加入addqueryprinterstatus(response_mode mode)
*,在打印完成后会接收到,action为gpcom.action_label_response的广播,特别用于连续打印,
*可参照该sample中的sendlabelwithresponse方法与广播中的处理
**/
registerreceiver(mbroadcastreceiver,newintentfilter(gpcom.action_label_response));
}
@override
protected void initview() {
print.setonclicklistener(this);
}
@override
public void onclick(view v) {
switch(v.getid()) {
caser.id.print_print:
if(mgpservice==null) {
uiutils.showmessage("服务正在开启");
}else{
try{
inttype =mgpservice.getprintercommandtype(1);
if(type == gpcom.esc_command) {
mgpservice.queryprinterstatus(1,1000,request_print_receipt);
}else{
toast.maketext(this,"printer is not receipt mode", toast.length_short).show();
}
}catch(remoteexception e1) {
e1.printstacktrace();
}
}
break;
}
}
private void sendreceipt() {
esccommand esc =newesccommand();
esc.addinitializeprinter();
esc.addprintandfeedlines((byte)3);
esc.addselectjustification(esccommand.justification.center);//设置打印居中
esc.addselectprintmodes(esccommand.font.fonta, esccommand.enable.off, esccommand.enable.on, esccommand.enable.on, esccommand.enable.off);//设置为倍高倍宽
esc.addtext("asdfkldsjgfsdl\n");//打印文字
esc.addprintandlinefeed();
/*打印文字 */
esc.addselectprintmodes(esccommand.font.fonta, esccommand.enable.off, esccommand.enable.off, esccommand.enable.off, esccommand.enable.off);//取消倍高倍宽
esc.addselectjustification(esccommand.justification.left);//设置打印左对齐
esc.addtext("dfkdsgklfds\n");//打印文字
// esc.addtext("welcome to use smarnet printer!\n"); //打印文字
// /*打印繁体中文需要打印机支持繁体字库 */
// string message = "佳博智匯票據打印機\n";
// // esc.addtext(message,"big5");
// esc.addtext(message, "gb2312");
esc.addprintandlinefeed();
/*绝对位置具体详细信息请查看gp58编程手册 */
esc.addtext("商品名称");
esc.addsethorandvermotionunits((byte)7, (byte)0);
esc.addsetabsoluteprintposition((short)6);
esc.addtext("订单号");
esc.addsetabsoluteprintposition((short)10);
esc.addtext("状态");
esc.addprintandlinefeed();
esc.addtext("苹果");
esc.addsethorandvermotionunits((byte)7, (byte)0);
esc.addsetabsoluteprintposition((short)6);
esc.addtext("12345");
esc.addsetabsoluteprintposition((short)10);
esc.addtext("正常");
esc.addprintandlinefeed();
esc.addtext("果粒橙300ml");
esc.addsethorandvermotionunits((byte)7, (byte)0);
esc.addsetabsoluteprintposition((short)6);
esc.addtext("3545456");
esc.addsetabsoluteprintposition((short)10);
esc.addtext("正常");
esc.addprintandlinefeed();
// /*打印图片 */
// esc.addtext("print bitmap!\n"); //打印文字
// bitmap b = bitmapfactory.decoderesource(getresources(), r.drawable.gprinter);
// esc.addrastbitimage(b, 384, 0); //打印图片
// /*打印一维条码 */
// esc.addtext("print code128\n"); //打印文字
// esc.addselectprintingpositionforhricharacters(esccommand.hri_position.below);//
// //设置条码可识别字符位置在条码下方
// esc.addsetbarcodeheight((byte) 60); //设置条码高度为60点
// esc.addsetbarcodewidth((byte) 1); //设置条码单元宽度为1
// esc.addcode128(esc.gencodeb("smarnet")); //打印code128码
// esc.addprintandlinefeed();
/*
* qrcode命令打印此命令只在支持qrcode命令打印的机型才能使用。在不支持二维码指令打印的机型上,则需要发送二维条码图片
*/
esc.addtext("商家二维码\n");//打印文字
esc.addselecterrorcorrectionlevelforqrcode((byte)0x31);//设置纠错等级
esc.addselectsizeofmoduleforqrcode((byte)6);//设置qrcode模块大小
esc.addstoreqrcodedata("dfgdgs");//设置qrcode内容
esc.addprintqrcode();//打印qrcode
esc.addprintandlinefeed();
/*打印文字 */esc.addselectjustification(esccommand.justification.center);//设置打印左对齐
esc.addtext("completed!\r\n");//打印结束
//开钱箱
esc.addgenerateplus(labelcommand.foot.f5, (byte)255, (byte)255);
esc.addprintandfeedlines((byte)8);
vector<byte> datas = esc.getcommand();//发送数据
byte[] bytes = gputils.byteto_byte(datas);
string sss = base64.encodetostring(bytes, base64.default);
intrs;
try{
rs =mgpservice.sendesccommand(1, sss);
gpcom.error_code r = gpcom.error_code.values()[rs];
if(r != gpcom.error_code.success) {
toast.maketext(getapplicationcontext(), gpcom.geterrortext(r), toast.length_short).show();
}
}catch(remoteexception e) {
//todo auto-generated catch block
e.printstacktrace();
}
}
}

至此大功告成,打印出东西之后感觉好爽

以上所述是小编给大家介绍的android手机通过蓝牙连接佳博打印机的实例代码,希望对大家有所帮助

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网