IOS几种常见的实现扫描、生成二维码的方式(一、使用ZBar SDK)

        最近项目中使用到扫描二维码的功能,要求还蛮多的,包括界面的定制,扫描灵敏度,使用的稳定性等等。于是,研究总结了一下IOS中几种扫描二维码的实现方式。

        基本上我们的实现方法有三大途径:ZBar、ZXing、AVFoundation。在 iOS7 以前,在iOS中实现二维码和条形码扫描,我们知道的有两大开源组件ZBar与ZXing,而iOS7后苹果也提供AVFoundation支持二维码的扫描。

        ZBar在扫描的灵敏度上和内存的使用上相对于ZXing上都是较优的,但是对于 “圆角二维码” 的扫描确很困难。ZXing 是 Google Code上的一个开源的条形码扫描库,是用java设计的,连Google Glass 都在使用的。但有人为了追求更高效率以及可移植性,出现了c++ port. Github上的Objectivc-C port,其实就是用OC代码封装了一下而已,而且已经停止维护。ios7以上AVFoundation提供原生api扫描二维码,无论在扫描灵敏度和性能上来说都是最优的,所以毫无疑问我们应该切换到AVFoundation,但是如果需要兼容iOS 6或之前的版本就要使用ZBar或ZXing代替。

       由于我们的项目还要支持iOS6的用户,所以选择了ZBar。那我们就先从ZBar说起吧。官网介绍 http://zbar.sourceforge.net  SDK下载 http://sourceforge.net/projects/zbar/files/iPhoneSDK/ZBarSDK-1.2.dmg/download 。首先声明一下,官方下载的ZBar SDK竟然是不支持64位的,而苹果早就已经开始对上传到 iTunes 上的应用强制要求支持64位。所以需要的可以从这里下载,链接:http://download.csdn.net/detail/he_jiabin/9043381 已经支持64位的ZBarSDK静态库,同时解决中文乱码的问题。使用可以参考官方的帮助文档:http://zbar.sourceforge.net/iphone/sdkdoc/install.html 。基本的步骤就是导入需要的framework,如下图


        在使用的扫码的控制器中引入#import "ZBarSDK.h"头文件,就可以使用了。值得一提的是,通过提供的SDK我们可以看到,ZBar SDK提供了两种使用方式:1)直接调用 ZBarReaderViewController 打开一个扫描界面;2)ZBar SDK提供的可以嵌入其他视图的ZBarReaderView(建议使用该方式,我们可以自定义扫描界面,我们后面定制扫描的页面就是通过这种方式)。


        第一种方式是常规的方式,通过ZBarReaderViewController直接打开一个扫描界面进行扫描。首先引用头文件 #import"ZBarSDK.h",实现代理<ZBarReaderDelegate

初始化扫描二维码控制器

- (void)normalScanQRCodeView{
    //初始化扫描二维码控制器
    ZBarReaderViewController *reader = [ZBarReaderViewController new];
    //设置代理
    reader.readerDelegate = self;
    //基本适配
    reader.supportedOrientationsMask = ZBarOrientationMaskAll;
    //二维码/条形码识别设置
    ZBarImageScanner *scanner = reader.scanner;
    [scanner setSymbology: ZBAR_I25
                   config: ZBAR_CFG_ENABLE
                       to: 0];
    //弹出系统照相机,全屏拍摄
    [self presentViewController:reader animated:YES completion:^{
        
    }];
}


扫描二维码成功、读取二维码内容

#pragma mark -
#pragma mark ZBarReaderDelegate
//扫描二维码的时候,识别成功会进入此方法,读取二维码内容
-(void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
    id<NSFastEnumeration> results = [info objectForKey:ZBarReaderControllerResults];
    ZBarSymbol * symbol;
    for(symbol in results)
        break;
    
    [picker dismissViewControllerAnimated:YES completion:nil];
    
    NSString *result = symbol.data;
    
    NSLog(@"%@",result);
    
    //二维码扫描成功,弹窗提示
    UIAlertController *alertVC = [UIAlertController alertControllerWithTitle:@"扫描成功" message:[NSString stringWithFormat:@"二维码内容:\n%@",result] preferredStyle:UIAlertControllerStyleAlert];
    UIAlertAction *action = [UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleCancel handler:^(UIAlertAction *action) {
    }];
    [alertVC addAction:action];
    [self presentViewController:alertVC animated:YES completion:^{
    }];
}


常规的扫描效果




        第二种方式是我们着重要讲的自定义扫描界面的方式。即通过自定义ZBarReaderView的界面达到自定义的效果。首先引用头文件 #import"ZBarSDK.h",实现代理<ZBarReaderViewDelegate>

初始化扫描二维码对象ZBarReaderView

/**
 *初始化扫描二维码对象ZBarReaderView
 *@param 设置扫描二维码视图的窗口布局、参数
 */
-(void)configuredZBarReader{
    //初始化照相机窗口
    _readview = [[ZBarReaderView alloc] init];
    //设置扫描代理
    _readview.readerDelegate = self;
    //关闭闪光灯
    _readview.torchMode = 0;
    //显示帧率
    _readview.showsFPS = NO;
    //将其照相机拍摄视图添加到要显示的视图上
    [self.view addSubview:_readview];
    //二维码/条形码识别设置
    ZBarImageScanner *scanner = _readview.scanner;
    [scanner setSymbology: ZBAR_I25
                   config: ZBAR_CFG_ENABLE
                       to: 0];
    //Layout ZBarReaderView
    __weak __typeof(self) weakSelf = self;
    [_readview mas_makeConstraints:^(MASConstraintMaker *make) {
        make.top.equalTo(weakSelf.view).with.offset(0);
        make.left.equalTo(weakSelf.view).with.offset(0);
        make.right.equalTo(weakSelf.view).with.offset(0);
        make.bottom.equalTo(weakSelf.view).with.offset(0);
    }];
    
    //初始化扫描二维码视图的子控件
    [self configuredZBarReaderMaskView];
    
    //启动,必须启动后,手机摄影头拍摄的即时图像菜可以显示在readview上
    [_readview start];
    [_qrRectView startScan];
}


自定义扫描二维码视图样式

/**
 *自定义扫描二维码视图样式
 *@param 初始化扫描二维码视图的子控件
 */
- (void)configuredZBarReaderMaskView{
    //扫描的矩形方框视图
    _qrRectView = [[QRView alloc] init];
    _qrRectView.transparentArea = CGSizeMake(220, 220);
    _qrRectView.backgroundColor = [UIColor clearColor];
    [_readview addSubview:_qrRectView];
    [_qrRectView mas_makeConstraints:^(MASConstraintMaker *make) {
        make.top.equalTo(_readview).with.offset(0);
        make.left.equalTo(_readview).with.offset(0);
        make.right.equalTo(_readview).with.offset(0);
        make.bottom.equalTo(_readview).with.offset(0);
    }];
    
    //照明按钮
    _lightingBtn = [UIButton buttonWithType:UIButtonTypeCustom];
    [_lightingBtn setTitle:@"照明" forState:UIControlStateNormal];
    [_lightingBtn.titleLabel setFont:[UIFont systemFontOfSize:14]];
    _lightingBtn.layer.borderColor = [UIColor colorWithHexString:@"#3498db"].CGColor;
    _lightingBtn.layer.borderWidth = 1.0;
    _lightingBtn.layer.cornerRadius = 8.0;
    [_lightingBtn setTitleEdgeInsets:UIEdgeInsetsMake(0, 20, 0, 0)];
    [_lightingBtn setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
    [_lightingBtn setBackgroundColor:[UIColor clearColor]];
    _lightingBtn.tag = LIGHTBUTTONTAG;
    [_lightingBtn addTarget:self action:@selector(buttonClicked:) forControlEvents:UIControlEventTouchUpInside];
    [_qrRectView addSubview:_lightingBtn];
    [_lightingBtn mas_makeConstraints:^(MASConstraintMaker *make) {
        make.bottom.equalTo(_qrRectView).with.offset(-100);
        make.centerX.equalTo(_qrRectView);
        make.size.mas_equalTo(CGSizeMake(88, 28));
    }];
    UIImageView *lightImage = [[UIImageView alloc] init];
    lightImage.image = [UIImage imageNamed:@"bulb"];
    [_lightingBtn addSubview:lightImage];
    [lightImage mas_makeConstraints:^(MASConstraintMaker *make) {
        make.centerY.equalTo(_lightingBtn);
        make.left.equalTo(_lightingBtn).with.offset(17);
        make.width.equalTo(@22);
        make.height.equalTo(@22);
    }];
    
    //导入二维码图片
    _importQRCodeImageBtn = [UIButton buttonWithType:UIButtonTypeCustom];
    [_importQRCodeImageBtn setTitle:@"导入二维码" forState:UIControlStateNormal];
    [_importQRCodeImageBtn.titleLabel setFont:[UIFont systemFontOfSize:12]];
    [_importQRCodeImageBtn setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
    [_importQRCodeImageBtn setBackgroundColor:[UIColor clearColor]];
    _importQRCodeImageBtn.tag = IMPORTBUTTONTAG;
    [_importQRCodeImageBtn addTarget:self action:@selector(buttonClicked:) forControlEvents:UIControlEventTouchUpInside];
    [_qrRectView addSubview:_importQRCodeImageBtn];
    [_importQRCodeImageBtn mas_makeConstraints:^(MASConstraintMaker *make) {
        make.bottom.equalTo(_qrRectView.mas_bottom).with.offset(-32);
        make.right.equalTo(_qrRectView.mas_right).with.offset(-20);
        make.size.mas_equalTo(CGSizeMake(60, 12));
    }];
    
    _importQRCodeImage = [UIButton buttonWithType:UIButtonTypeCustom];
    [_importQRCodeImage setBackgroundImage:[UIImage imageNamed:@"album"] forState:UIControlStateNormal];
    _importQRCodeImage.tag = IMPORTBUTTONTAG;
    [_importQRCodeImage addTarget:self action:@selector(buttonClicked:) forControlEvents:UIControlEventTouchUpInside];
    [_qrRectView addSubview:_importQRCodeImage];
    [_importQRCodeImage mas_makeConstraints:^(MASConstraintMaker *make) {
        make.bottom.equalTo(_qrRectView).with.offset(-48);
        make.centerX.equalTo(_importQRCodeImageBtn);
        make.size.mas_equalTo(CGSizeMake(32, 32));
    }];
}

控件事件处理

- (void)buttonClicked:(UIButton *)sender{
    switch (sender.tag) {
        case LIGHTBUTTONTAG://照明按钮
        {
            if(0 != _readview.torchMode){
                //关闭闪光灯
                _readview.torchMode = 0;
            }else if (0 == _readview.torchMode){
                //打开闪光灯
                _readview.torchMode = 1;
            }
            
        }
            break;
        case IMPORTBUTTONTAG://导入二维码图片
        {
            [self presentImagePickerController];
        }
            break;
    
        default:
            break;
    }
}

/**
 *打开二维码扫描视图ZBarReaderView
 *@param 关闭闪光灯
 */
- (void)setZBarReaderViewStart{
    _readview.torchMode = 0;//关闭闪光灯
    [_readview start];//开始扫描二维码
    [_qrRectView startScan];
    
}

/**
 *关闭二维码扫描视图ZBarReaderView
 *@param 关闭闪光灯
 */
- (void)setZBarReaderViewStop{
    _readview.torchMode = 0;//关闭闪光灯
    [_readview stop];//关闭扫描二维码
    [_qrRectView stopScan];
}

//弹出系统相册、相机
-(void)presentImagePickerController{
    UIImagePickerControllerSourceType sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
    _picker = [[UIImagePickerController alloc] init];
    _picker.sourceType               = sourceType;
    _picker.allowsEditing            = YES;
    //    NSArray *temp_MediaTypes        = [UIImagePickerController availableMediaTypesForSourceType:picker.sourceType];
    //    picker.mediaTypes               = temp_MediaTypes;
    _picker.delegate                 = self;
    
    UIWindow *window = [UIApplication sharedApplication].keyWindow;
    [window addSubview:_picker.view];
    [_picker.view mas_makeConstraints:^(MASConstraintMaker *make) {
        make.center.equalTo(window);
        make.size.equalTo(window);
    }];
}

-(void)imagePickerControllerDidCancel:(UIImagePickerController *)picker{
    //收起相册
    [picker.view removeFromSuperview];
}

最关键的步骤就是扫描二维码获取二维码内容和从相册导入二维码图片获取二维码内容

#pragma mark -
#pragma mark ZBarReaderViewDelegate
//扫描二维码的时候,识别成功会进入此方法,读取二维码内容
- (void) readerView: (ZBarReaderView*) readerView
     didReadSymbols: (ZBarSymbolSet*) symbols
          fromImage: (UIImage*) image{
    //停止扫描
    [self setZBarReaderViewStop];
    
    ZBarSymbol *symbol = nil;
    for (symbol in symbols) {
        break;
    }
    NSString *urlStr = symbol.data;
    
    if(urlStr==nil || urlStr.length<=0){
        //二维码内容解析失败
        UIAlertController *alertVC = [UIAlertController alertControllerWithTitle:@"扫描失败" message:nil preferredStyle:UIAlertControllerStyleAlert];
        __weak __typeof(self) weakSelf = self;
        UIAlertAction *action = [UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleCancel handler:^(UIAlertAction *action) {
            //重新扫描
            [weakSelf setZBarReaderViewStart];
        }];
        [alertVC addAction:action];
        [self presentViewController:alertVC animated:YES completion:^{
        }];
        
        return;
    }
    
    NSLog(@"urlStr: %@",urlStr);
    
    //二维码扫描成功,弹窗提示
    UIAlertController *alertVC = [UIAlertController alertControllerWithTitle:@"扫描成功" message:[NSString stringWithFormat:@"二维码内容:\n%@",urlStr] preferredStyle:UIAlertControllerStyleAlert];
    __weak __typeof(self) weakSelf = self;
    UIAlertAction *action = [UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleCancel handler:^(UIAlertAction *action) {
        //继续扫描
        [weakSelf setZBarReaderViewStart];
    }];
    [alertVC addAction:action];
    [self presentViewController:alertVC animated:YES completion:^{
        
    }];
    
}

#pragma mark -
#pragma mark UIImagePickerControllerDelegate
//导入二维码的时候会进入此方法,处理选中的相片获取二维码内容
-(void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info{
    //停止扫描
    [self setZBarReaderViewStop];
    
    //处理选中的相片,获得二维码里面的内容
    ZBarReaderController *reader = [[ZBarReaderController alloc] init];
    UIImage *image = [info objectForKey:UIImagePickerControllerOriginalImage];
    CGImageRef cgimage = image.CGImage;
    ZBarSymbol *symbol = nil;
    for(symbol in [reader scanImage:cgimage])
        break;
    NSString *urlStr = symbol.data;
    
    [picker.view removeFromSuperview];
    
    if(urlStr==nil || urlStr.length<=0){
        //二维码内容解析失败
        UIAlertController *alertVC = [UIAlertController alertControllerWithTitle:@"扫描失败" message:nil preferredStyle:UIAlertControllerStyleAlert];
        __weak __typeof(self) weakSelf = self;
        UIAlertAction *action = [UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleCancel handler:^(UIAlertAction *action) {
            //重新扫描
            [weakSelf setZBarReaderViewStart];
        }];
        [alertVC addAction:action];
        [self presentViewController:alertVC animated:YES completion:^{
        }];

        return;
    }
    
    NSLog(@"urlStr: %@",urlStr);
    
    //二维码扫描成功,弹窗提示
    UIAlertController *alertVC = [UIAlertController alertControllerWithTitle:@"扫描成功" message:[NSString stringWithFormat:@"二维码内容:\n%@",urlStr] preferredStyle:UIAlertControllerStyleAlert];
    __weak __typeof(self) weakSelf = self;
    UIAlertAction *action = [UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleCancel handler:^(UIAlertAction *action) {
        //继续扫描
        [weakSelf setZBarReaderViewStart];
    }];
    [alertVC addAction:action];
    [self presentViewController:alertVC animated:YES completion:^{
    }];
}


自定义的扫描二维码效果:


       

        这里通过ZBar SDK自定义扫描二维码的步骤基本完成。 

        接下来,我们来讲一下如何生成一张二维码。在生成二维码的库中QREncoder最为常见,但是由于中文字符的特殊性,生成中文的时候会出现一定的错误,所以采用 libqrencode,二维码生成框架libqrencode是一个纯C编写的类库,支持面也更广泛。

       首先下载libqrencode源码,可以到这里下载http://download.csdn.net/detail/he_jiabin/9111589。在工程中导入相关的framework。已经导入的framework无需再导入。



      将libqrencode源码加入工程后,在需要使用生成二维码的控制器中引用头文件 #import"QRCodeGenerator.h" 

      生成二维码图片的方法如下:

testImageView.image = [QRCodeGenerator qrImageForString:testTextField.text imageSize:testImageView.bounds.size.width];

       到这里,看来生成二维码图片的步骤确实很简单。但是在我们将libqrencode源码加入工程后,在相关控制器引用头文件 #import"QRCodeGenerator.h"的时候,编译却报错了。认真一看还是一大片的红色错误。这是因为,在使用libqrencode框架的时候,需要我们对项目做一些必要的配置修改。

       第一步:需要我们去手动修改.pch文件。需要在.pch文件中添加以下内容:

#import <Availability.h>

#ifndef __IPHONE_4_0
#warning "This project uses features only available in iOS SDK 4.0 and later."
#endif

#ifdef __OBJC__
#import <UIKit/UIKit.h>
#import <Foundation/Foundation.h>
#endif

       貌似现在Xcode6+以后,Xcode生成的项目默认都是不带.pch文件的。这个时候需要我们自己生成.pch文件,然后修改里面的内容。生成.pch文件步骤:Xcode-->File-->New-->File-->Other-->PCH File



       第二步:配置好相应的Prefix Header文件路径。

       如果这两步都配置好了之后,我们就可以正确生成二维码了。

       生成二维码效果:



项目Demo已经放在GitHub,也算是做了一个小结。https://github.com/jaybinhe/JB_ZBarSDK_Demo


  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
### 回答1: Android Studio 可以使用 Zbar 库来实现二维码识别。Zbar 是一个开源的条码识别库,可以支持多种类型的条码和二维码,包括 QR 码、Data Matrix 码等。在 Android Studio 中,可以通过添加 Zbar 库的依赖,然后在代码中调用相关 API 来实现二维码扫描和识别。同时,还需要在 AndroidManifest.xml 文件中添加相应的权限声明,例如相机权限等。通过这种方式,就可以在 Android 应用中集成二维码扫描功能了。 ### 回答2: Android Studio 是一款用于开发Android应用程序的集成开发环境(IDE),而Zbar 是一个流行的二维码扫描库,可用于实现二维码的识别。 首先,我们需要在Android Studio中配置Zbar库。可以通过在项目的build.gradle文件中添加Zbar依赖项来完成配置。然后,我们需要在AndroidManifest.xml文件中添加必要的权限,如摄像头权限等。 接下来,在我们想要进行二维码识别的Activity中,我们需要初始化Zbar库并打开相机。我们可以在Activity的onCreate()方法中进行这些操作。 在初始化和打开相机之后,我们需要在相机预览界面中实现一个回调函数,以便在捕捉到图像时进行二维码的识别。我们可以使用Zbar库提供的接口来实现这个回调函数,并在回调函数中调用Zbar二维码识别方法。 一旦识别到二维码,我们可以通过定义一个回调接口来接收识别结果,并在回调接口中处理这些结果。可以根据需要,将识别的二维码信息展示出来,或者执行其他操作。 最后,在Activity的onDestroy()方法中,我们需要释放相机资源和关闭Zbar库。 以上就是使用Android Studio和Zbar实现二维码识别的大致步骤。当然,具体的实现细节还需要根据具体的项目需求进行相应修改和补充。希望以上回答对您有帮助! ### 回答3: 在Android Studio中使用Zbar库来实现二维码识别非常简便。以下是一个简单的步骤指南: 首先,你需要在你的项目的build.gradle文件中添加Zbar库的依赖项。 在dependencies区块中添加以下代码: ```gradle implementation 'me.dm7.barcodescanner:zxing:1.9.13' ``` 下一步是在你的布局文件中添加一个BarcodeScannerView,这将用于显示相机预览和捕获二维码图像。 ```xml <me.dm7.barcodescanner.zxing.ZXingScannerView android:id="@+id/scanner_view" android:layout_width="match_parent" android:layout_height="match_parent" /> ``` 然后,在你的Activity或Fragment的代码中,你需要初始化和控制BarcodeScannerView。 首先,在你的onCreate方法中实例化一个BarcodeScannerView对象: ```java private ZXingScannerView mScannerView; ``` 然后,在onResume方法中初始化BarcodeScannerView,并启动相机预览: ```java @Override public void onResume() { super.onResume(); mScannerView = new ZXingScannerView(this); setContentView(mScannerView); mScannerView.setResultHandler(this); mScannerView.startCamera(); } ``` 接下来,你需要实现回调方法来处理识别到的二维码数据: ```java @Override public void handleResult(Result result) { // 在这里处理识别到的二维码数据 String qrCodeData = result.getText(); // 你可以对数据进行任何你想要的处理 // ... // 完成后,重新启动相机预览 mScannerView.resumeCameraPreview(this); } ``` 最后,在onPause方法中释放BarcodeScannerView资源: ```java @Override public void onPause() { super.onPause(); mScannerView.stopCamera(); } ``` 通过以上步骤,你就可以在Android Studio中使用Zbar实现二维码的识别了。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值