Android作为一个面向手机和平板的操作系统,主要擅长娱乐和通信方面的应用,由于接口方面的限制,对于其它外部设备的支持不是很强,而且多数外设生产厂商也不支持Android系统。
所幸的是,几乎所有智能手机都带有蓝牙功能,只要遵循特定的通信协议,我们可以通过蓝牙功能,调用所有支持蓝牙的外部设备。
打印机是最常见的外部设备,而其中的小票打印机,广泛应用于超市收银、票据、回执打印,是商务应用不可或缺的组成部分。下面就以云腾M02蓝牙热敏小票打印机为例,说明C++ Builder XE10如何调用它进行打印。
云腾M02蓝牙打印机自带锂电池,体积较小,便于携带,同时提供有USB原生接口,即可用手机蓝牙无线打印,也可以在Windows下用USB连接打印,打印速度较快,是市面上较为典型的移动小票打印设备。
一、与打印机进行配对
与任何蓝牙设备进行通讯之前,必须与其进行配对。打开云腾M02打印机电源,在Android系统中点“设置->蓝牙”,可以搜索到该设备的名称ID231 Printer,选择,输入配对密码,默认为“1234”,具体可参看说明书。
二、获取系统中已经配对的蓝牙设备
1. 打开C++ Builder XE10,新建一个Android工程,添加头文件以支持蓝牙功能
#include <System.Bluetooth.hpp>
2. 设置程序的蓝牙权限
点击菜单Project->Options,左边点Uses Permissions,右边勾选蓝牙相关的权限,如图:
一、与打印机进行配对
与任何蓝牙设备进行通讯之前,必须与其进行配对。打开云腾M02打印机电源,在Android系统中点“设置->蓝牙”,可以搜索到该设备的名称ID231 Printer,选择,输入配对密码,默认为“1234”,具体可参看说明书。
二、获取系统中已经配对的蓝牙设备
1. 打开C++ Builder XE10,新建一个Android工程,添加头文件以支持蓝牙功能
#include <System.Bluetooth.hpp>
2. 设置程序的蓝牙权限
点击菜单Project->Options,左边点Uses Permissions,右边勾选蓝牙相关的权限,如图:
3. 通过蓝牙管理器对象,获取本机已配对的蓝牙设备
放置一个组合框ComboBox1和一个按钮Button1,用于填充蓝牙设备名称
void __fastcall TMainForm::Button1Click(TObject *Sender)
{
try
{
FBluetoothManager = TBluetoothManager::Current; //得到本机蓝牙管理器
FAdapter = FBluetoothManager->CurrentAdapter; //得到本机蓝牙设备
if(FBluetoothManager->ConnectionState == TBluetoothConnectionState::Connected) //如果有并且打开了蓝牙设备
{
Memo1->Lines->Add(L"得到本机蓝牙设备: '" + FBluetoothManager->CurrentAdapter->AdapterName + L"'");
ComboBox1->Clear();
FPairedDevices = FBluetoothManager->GetPairedDevices(); //得到已配对设备列表
if(FPairedDevices->Count > 0)
{
for(int i = 0; i < FPairedDevices->Count; i++)
{
ComboBox1->Items->Add(FPairedDevices->Items[i]->DeviceName);
}
if(ComboBox1->Count > 0)
ComboBox1->ItemIndex = 0;
}
else
{
Memo1->Lines->Add(L"无配对设备");
}
}
else //无蓝牙设备或者未打开
{
Memo1->Lines->Add(L"本机没有或未打开蓝牙设备");
}
}
catch (Exception &ex)
{
ShowMessage(ex.Message);
}
}
三、获取设备中提供的服务
每个蓝牙设备都提供有一个或若干个服务,用不同的UUID字符串表示。需要获取该服务,才能与蓝牙设备通讯。
放置第二个组合框ComboBox2和一个按钮Button2,用于填充该设备的服务名称
void __fastcall TMainForm::Button2Click(TObject *Sender)
{
ComboBox2->Clear();
if(ComboBox1->ItemIndex > -1)
{
TBluetoothDevice * LDevice = FPairedDevices->Items[ComboBox1->ItemIndex];
TBluetoothServiceList * LServices = LDevice->GetServices(); //获取该已配对设备提供的服务
for(int i=0; i<LServices->Count; i++)
{
ComboBox2->Items->Add(GUIDToString(LServices->Items[i].UUID));
}
if(ComboBox2->Count > 0)
ComboBox2->ItemIndex = 0;
}
else
{
ShowMessage(L"请在已配对列表中选择一个设备");
}
}
四、连接打印机
void __fastcall TMainForm::Button3Click(TObject *Sender)
{
if(FSocket == NULL) //未连接
{
if(ComboBox1->ItemIndex > -1 && ComboBox2->ItemIndex > -1)
{
UnicodeString strServiceGUID = ComboBox2->Items->Strings[ComboBox2->ItemIndex]; //服务GUID
TBluetoothDevice * LDevice = FPairedDevices->Items[ComboBox1->ItemIndex];
Memo1->Lines->Add(L"准备连接服务:" + strServiceGUID);
Memo1->GoToTextEnd();
FSocket = LDevice->CreateClientSocket(StringToGUID(strServiceGUID), false); //建立与蓝牙设备的Socket通讯
if(FSocket != NULL)
{
try
{
FSocket->Connect(); //连接
BluetoothReadTH = new TBluetoothReadTH(false, FSocket); //创建读数据线程
Memo1->Lines->Add(L"连接Socket成功!");
Memo1->GoToTextEnd();
}
catch(...)
{
delete FSocket;
FSocket = NULL;
Memo1->Lines->Add(L"连接Socket失败!");
Memo1->GoToTextEnd();
}
}
else
{
ShowMessage(L"发送超时(15秒)");
}
}
else
{
ShowMessage(L"请先选择一个配对的设备和该设备的一个服务");
}
}
else //已连接
{
ShowMessage(L"设备已经连接");
}
}
五、发送数据并打印
根据该打印机的通讯协议,发送要打印的内容和控制命令
//发送打印内容
TBytes ToSend = TEncoding::ANSI->GetBytes(AnsiString(Edit1->Text));
FSocket->SendData(ToSend);
Memo1->Lines->Add(L"发送数据:" + Edit1->Text);
Memo1->GoToTextEnd();
//打印并走纸一行命令
TBytes bt;
bt.set_length(1);
bt[0]=0x0D;
FSocket->SendData(bt);
六、关于打印图像
由于热敏打印机只能打印黑白图像,所以要将图像转为黑白模式,代码如下,1表示黑,0表示白:
BYTE b = 0;
if(x < bmp->Width && y < bmp->Height)
{
int pixel = vBitmapData.GetPixel(x, y);
int red = (pixel & 0x00ff0000) >> 16; // 取高两位
int green = (pixel & 0x0000ff00) >> 8; // 取中两位
int blue = pixel & 0x000000ff; // 取低两位
int gray = (int) ((0.29900 * red) + (0.58700 * green) + (0.11400 * blue)); //RGB转灰度
if (gray < 128)
b = 1;
else
b = 0;
}
云腾M02打印机打印图像的数据格式是逐行发送图像,可设置每行纵向有多少个点。假设一个240*240的图片,纵向设置为24点, 则共分10行打印。
每一行,是一个 240*24 的点阵, 每一列有24个点,存储在3个byte里面。
每个byte存储8个像素点信息。因为只有黑白两色,所以对应为1的位是黑色,对应为0的位是白色。
七、总结
打印操作是一个比较耗时的过程,上面代码只是简单示例,在实际应用中,应该将读写蓝牙数据放在线程中进行。具体内容详见示例程序。
示例程序效果如下:
示例程序下载:
http://download.csdn.net/detail/realbay/9724021
打印机网址:
https://item.taobao.com/item.htm?spm=0.0.0.0.9EM5Mj&id=543815038708