写在前面:因为哥们 @骑驴追蝴蝶 遇到了打印图片的功能,这个demo 是支持打印图片的,打印图片代码我单独放在文章最后,有需要的哥们可以去试试
之前公司项目里面需要使用到蓝牙打印机这个功能,搞定后特来向兄弟们分享一下经验和坑。
废话不多说,直接上代码
1.需要导入一些库,这些库是当时看的demo上面需要的,因为时间紧,我没有试过是不是每个库都是需要的,还望兄弟们见谅,不过全部加上是没有错的。
注意:payUpDate不需要添加
2.导入PrinterSDK,这个SDK我会随demo一起放出。
3.先检测是否能够自动连接,因为蓝牙打印机直有第一次连接是费时间的,其他时候只需要调用自动连接即可
AppDelegate.m
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
//自动连接上一次使用的打印机
[PrinterWraper autoConnectLastPrinterTimeout:6.0 Completion:^(NSString *uid) {
NSLog(@"自动连接 uid=%@",uid);
if (uid) {
//连接成功后发送通知
[[NSNotificationCenter defaultCenter] postNotificationName:KConnectionSuccess object:nil];
}else{
[SVProgressHUD dismiss];
}
}];
return YES;
}
4.创建一个专门用来管理打印机的类
.h里面基本上面没有什么
#import <Foundation/Foundation.h>
@interface iOS : NSObject
//直接调用该方法,启动打印机(jsonstring是后台传过来的数据)
- (void)print:(NSString *)jsonString;
@end
.m
#import "iOS.h"
#import <CoreBluetooth/CoreBluetooth.h>
@interface iOS()<BluetoothDelegate,UIAlertViewDelegate>
@property (nonatomic, strong) NSTimer *mytimer;
@property (nonatomic, strong) NSArray*deviceList;
@property (nonatomic, copy) NSString *jsonString;
@property (nonatomic, assign) BOOL isAutoConnectionSuccess;
// 通知监听对象
@property (nonatomic, strong) id observer;
@end
@implementation iOS
- (instancetype)init{
if (self = [super init]) {
self.isAutoConnectionSuccess = NO;
__weak iOS * weakSelf = self;
//自动连接后,会到这里来,通知的接收
self.observer = [[NSNotificationCenter defaultCenter] addObserverForName:KConnectionSuccess object:nil queue:nil usingBlock:^(NSNotification * _Nonnull note) {
weakSelf.isAutoConnectionSuccess = YES;
}];
}
return self;
}
#pragma mark bluetooth delegate 检测蓝牙是否打开,这里是会自动调用的
-(void)BlueToothOpen:(BOOL)isopen;{
if (!isopen) {
//因为我这里是在webview里面进行的,可能有线程问题,所以我将弹框操作,全部放在主线程里面完成的
dispatch_async(dispatch_get_main_queue(), ^{
[SVProgressHUD showSuccessWithStatus:@"请打开蓝牙设备"];
});
}
}
//这里会去寻找打印机是否存在
- (void)scanPrinter{
[PrinterWraper SetBlutoothDelegate:self];
[PrinterWraper StartScanTimeout:5];
dispatch_async(dispatch_get_main_queue(), ^{
[SVProgressHUD showWithStatus:@"连接蓝牙打印机中..."];
});
self.mytimer = [NSTimer scheduledTimerWithTimeInterval:6.0 target:self selector:@selector(timeout) userInfo:nil repeats:NO];
}
-(void)stopScan{
[PrinterWraper StopScan];
[self.mytimer invalidate];
self.mytimer=nil;
}
#pragma mark 查找设备时间到,会调用这个方法,devicelist里面不需要赋值,就会有值,这也是我使用这个框架最大的坑
-(void)timeout{
[self stopScan];
BOOL isSuccess = NO;
for (int i = 0; i < self.deviceList.count; i++) {
if (self.deviceList[i]) {
CBPeripheral *device = self.deviceList[i];
//这里是你们蓝牙打印机的名字,你需要看看你们的蓝牙打印机设定的是什么名字
if ([device.name isEqualToString:@"Bluetooth Printer"]) {
//连接打印机
[PrinterWraper connectPrinter:device.identifier.UUIDString shouldreset:NO];
[SVProgressHUD dismiss];
isSuccess = YES;
}
}
}
if (!isSuccess)
{
dispatch_async(dispatch_get_main_queue(), ^{
[SVProgressHUD dismiss];
UIAlertView* alert=[[UIAlertView alloc] initWithTitle:nil message:NSLocalizedString(@"没有扫描到专用打印机",@"") delegate:nil cancelButtonTitle:NSLocalizedString(@"确定", @"") otherButtonTitles:nil, nil];
[alert show];
});
}
}
#pragma mark 注销通知
- (void)dealloc{
[[NSNotificationCenter defaultCenter] removeObserver:self.observer];
}
#pragma mark -打印jsonString
- (void)print:(NSString *)jsonString{
self.jsonString = jsonString;
if (self.isAutoConnectionSuccess) {
[self printJsonWithBluetoothPrinter:self.jsonString];
return;
}
[self scanPrinter];
}
#pragma mark 连接上会自动调用这个方法
-(void)didConnected:(NSString*)deviceUid Result:(BOOL)success;{
if (success){
[self printJsonWithBluetoothPrinter:self.jsonString];
}
}
//这里是设置你打印的内容,我这里保留下来兄弟们参考
- (void)printJsonWithBluetoothPrinter:(NSString *)jsonString{
#warning 请确保本身的navigationController是有效的
#warning 工程的General->Embedded Binaries + PrinterSdk.framework
#warning 请试用真机 否则会有编译错误
//jsonstring 是后台传过来的,这里考虑到兄弟们也应该是从网络上面请求来的数据,估计也需要同样处理,所以没有注释掉
NSData * data = [jsonString dataUsingEncoding:NSUTF8StringEncoding];
NSDictionary *dic = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
//设置格式 大字体 行间距28 局中
[PrinterWraper setPrintFormat:3 LineSpace:28 alinment:1 rotation:0];// 3 大字体 ,28默认行间距,1局中对齐
[PrinterWraper addPrintText:[NSString stringWithFormat:@"%@%@",[self checkString:dic[@"brand_name"]],[self checkString:dic[@"origin"]]]];
[PrinterWraper setPrintFormat:1 LineSpace:28 alinment:0 rotation:0];
[PrinterWraper addPrintText:@"*"];
[PrinterWraper setPrintFormat:3 LineSpace:28 alinment:1 rotation:0];// 3 大字体 ,28默认行间距,1局中对齐
//打印标题
[PrinterWraper addPrintText:[NSString stringWithFormat:@"%@\n",[self checkString:dic[@"serial"]]]];
//设置标题的格式
[PrinterWraper setPrintFormat:1 LineSpace:28 alinment:0 rotation:0];// 1 小字体 ,28默认行间距,0左对齐
//打印副标题
[PrinterWraper addPrintText:@"哈哈哈哈 客服电话: 4000-000-000\n"];//打印文字
//设置副标题的格式
[PrinterWraper setPrintFormat:1 LineSpace:28 alinment:0 rotation:0];// 1 小字体 ,28默认行间距,0左对齐
//打印副标题
[PrinterWraper addPrintText:@"********************************\n"];//打印文字
NSArray *headers =@[@"菜单",@"单价",@"数量"];
NSArray * goodArr = dic[@"lines"];
NSMutableArray * mutableArr = [NSMutableArray arrayWithCapacity:goodArr.count];
for (NSInteger i = 0; i<goodArr.count; i++) {
NSMutableArray * arr = [NSMutableArray array];
[arr addObject:[self checkString:dic[@"lines"][i][@"product_name"]]];
[arr addObject:[dic[@"lines"][i][@"unit_price_incl_tax"] stringValue]];
[arr addObject:[NSString stringWithFormat:@"X%@",[self checkString:dic[@"lines"][i][@"quantity"]]]];
[mutableArr addObject:arr];
}
NSMutableArray * body = [NSMutableArray array];
[body addObject:headers];
for (NSInteger i = 0; i < mutableArr.count; i++) {
[body addObject:mutableArr[i]];
}
//打印商品列表,会自动排版,要求数组长度一致,空白地方用@""
[PrinterWraper addItemLines:body];
//设置格式 大字体 行间距28 局中
[PrinterWraper setPrintFormat:3 LineSpace:28 alinment:1 rotation:0];// 3 大字体 ,28默认行间距,1局中对齐
NSString * product_total_price = @"";
if (!dic[@"product_total_price"]) {
product_total_price = @"0";
}else{
product_total_price = [dic[@"product_total_price"] stringValue];
}
NSString *str = [NSString stringWithFormat:@"\n合计: %@(元)\n",product_total_price];
[PrinterWraper addPrintText:str];//打印文字
//设置副标题的格式
[PrinterWraper setPrintFormat:1 LineSpace:28 alinment:0 rotation:0];// 1 小字体 ,28默认行间距,0左对齐
//打印副标题
[PrinterWraper addPrintText:@"********************************\n"];//打印文字
NSArray *values0_1 =@[@"订单类型:",[self checkString:dic[@"order_type"]]];
NSArray *values1_1 =@[@"订单渠道:",[self checkString:dic[@"origin"]]];
NSArray *values2_1 =@[@"服务品牌:",[self checkString:dic[@"brand_name"]]];
NSArray *values3_1 =@[@"服务门店:",[self checkString:dic[@"partner_name"]]];
NSArray *values4_1 =@[@"门店电话:",[self checkString:dic[@"service_phone"]]];
NSArray *values5_1 =@[@"下单时间:",[self checkString:dic[@"date_placed"]]];
NSArray *values6_1 =@[@"送餐时间:", [NSString stringWithFormat:@"%@ 【%@】",[self checkString:dic[@"shipping_method"]],[self checkString:dic[@"delivery_time"]]]];
NSArray *values7_1 =@[@"支付方式:",[self checkString:dic[@"payment_method"]]];
NSArray* body_1 =@[values0_1,values1_1,values2_1,values3_1,values4_1,values5_1,values6_1,values7_1];
//打印商品列表,会自动排版,要求数组长度一致,空白地方用@""
[PrinterWraper addItemLines:body_1];
//设置副标题的格式
[PrinterWraper setPrintFormat:1 LineSpace:28 alinment:0 rotation:0];// 1 小字体 ,28默认行间距,0左对齐
//打印副标题
[PrinterWraper addPrintText:@"********************************\n"];//打印文字
[PrinterWraper addPrintText:[self checkString:dic[@"customer_name"]]];
NSString * genderStr;
if ([[self checkString:dic[@"customer_gender"]] isEqualToString:@"男"]) {
genderStr = @" 先生\n";
}else if([[self checkString:dic[@"customer_gender"]] isEqualToString:@"女"]){
genderStr = @" 女士\n";
}else{
genderStr = @" \n";
}
[PrinterWraper addPrintText:genderStr];
[PrinterWraper addPrintText: [NSString stringWithFormat:@"%@\n",[self checkString:dic[@"customer_phone"]]]];
[PrinterWraper addPrintText: [NSString stringWithFormat:@"%@\n",[self checkString:dic[@"delivery_address"]]]];
//打印副标题
[PrinterWraper addPrintText:@"********************************\n"];//打印文字
//打印副标题
[PrinterWraper addPrintText:@"骑士签名:"];
[PrinterWraper addPrintText:@"\n\n\n\n\n\n"];//打印文字
// 开始启动打印
// [PrinterWraper startPrint:self.navigationController];
BOOL res= [PrinterWraper startPrint:nil];
}
- (NSString *)checkString:(id)str{
if (str) {
return (NSString *)str;
}else{
return @"";
}
}
@end
5.对上面的代码做一些解释
- 首先在appdelegate里面进行自动连接上一次使用过的打印机
2.如果能够自动连接,会更改管理类里面的isAutoConnectionSuccess 的值
3.直接调用管理类的,这个方法会根据isAutoConnectionSuccess判断是否自动连接上了
- (void)print:(NSString *)jsonString
4.自动连接上了直接跳鞋打印内容,然后进行打印即可
5.没有自动连接就需要调用下面方法来完成打印机的搜索
[self scanPrinter];
6.搜索的时候deviceList里面会自动进行赋值(这也是这个框架最坑的地方,不调试,根本无法进行)
7.根据deviceList里面设备进行判断,哪个是蓝牙打印机
for (int i = 0; i < self.deviceList.count; i++) {
if (self.deviceList[i]) {
CBPeripheral *device = self.deviceList[i];
if ([device.name isEqualToString:@"Bluetooth Printer"]) {
//连接打印机
[PrinterWraper connectPrinter:device.identifier.UUIDString shouldreset:NO];
[SVProgressHUD dismiss];
isSuccess = YES;
}
}
}
8.连接上了打印机后,会调用这个方法
-(void)didConnected:(NSString*)deviceUid Result:(BOOL)success;{
if (success){
[self printJsonWithBluetoothPrinter:self.jsonString];
}
}
9.然后填写打印内容即可,至于格式,我想兄弟们看看我的代码基本上也知道什么回事了
6.打印效果
注:下面的代码时打印图片的,
- (void)print:(NSString *)jsonString{
[PrinterWraper addPrintImage:[UIImage imageWithContentsOfFile:photopath]];
//打印标题
[PrinterWraper addPrintText:@"掌上科技有限公司"];//打印文字
// 设置主体内容 小字体
[PrinterWraper setPrintFormat:1 LineSpace:28 alinment:0 rotation:0];// 1 小字体 ,28默认行间距,0左对齐
[PrinterWraper addPrintText:@"掌上开单打印机高质量稳定速度快\n联系QQ40255986 手机15988879319\n"];//打印文字
//打印商品列表,会自动排版,要求数组长度一致,空白地方用@""
[PrinterWraper addItemLines:body];
//打印二维码
[PrinterWraper addPrintBarcode:@"http://www.baidu.com" isTwoDimensionalCode:1];//二维码
// 打印一维码 必须是12-13位数字
[PrinterWraper addPrintBarcode:@"123456789012" isTwoDimensionalCode:0];//1维码
[PrinterWraper addPrintBarcode:@"123456789013" isTwoDimensionalCode:0];//1维码
[PrinterWraper addPrintText:@"\n\n"];//打印文字
// 开始启动打印
// [PrinterWraper startPrint:self.navigationController];
}
附上demo地址,demo是直接拿的第三方提供的,但是里面有很多东西可能用不上,兄弟们按照我上面写的基本就ok了,因为我的代码是公司的,所以不敢使用,还望见谅!
https://github.com/knightSaber/PrinterDemoDev
https://github.com/newOcean/printer
文/小小流浪的汉子(简书作者)
原文链接:http://www.jianshu.com/p/4fa9eb1def6e
原文链接:http://www.jianshu.com/p/4fa9eb1def6e