| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226 |
- //
- // GRCodeManager.m
- // GreenRoad
- //
- // Created by Vecige on 16/11/17.
- // Copyright © 2016年 jetsum. All rights reserved.
- //
- #import "GRScanManager.h"
- #import <AVFoundation/AVFoundation.h>
- #import <AudioToolbox/AudioToolbox.h>
- @interface GRScanManager()<AVCaptureMetadataOutputObjectsDelegate>
- @property (copy, nonatomic) void (^completionBlock) (NSString *);
- @property (nonatomic, strong) AVCaptureSession *session;
- @property (nonatomic, strong) dispatch_queue_t sessionQueue;
- @end
- @implementation GRScanManager
- - (instancetype)init {
- self = [super init];
- if (self) {
- _supportQRCode = YES;
- _supportBarCode = YES;
- [self createQueue];
- }
- return self;
- }
- /**
- * 创建一个队列,防止阻塞主线程
- */
- - (void)createQueue{
- dispatch_queue_t sessionQueue = dispatch_queue_create("com.Colexiu.KulexiuForStudent.sesson", DISPATCH_QUEUE_SERIAL);
- self.sessionQueue = sessionQueue;
- }
- #pragma mark - 扫描二维码
- #pragma mark 开始扫描
- - (void)startScanningQRCodeWithInView:(UIView *)inView scanView:(UIView *)scanView resultCallback:(void(^)(NSString *result))callback {
-
- if ([self.session isRunning]) {
- [self.session stopRunning];
- self.session = nil;
- }
-
- // 0.保存block
- self.completionBlock = callback;
-
- // 1.创建输入
- // 1.1.定义错误
- NSError *error = nil;
-
- // 1.2.获取摄像头
- AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
-
- if ([device respondsToSelector:@selector(setVideoZoomFactor:)]) {
- if ([ device lockForConfiguration:nil]) {
- // float zoomFactor = device.activeFormat.videoZoomFactorUpscaleThreshold;
- float zoomFactor = 2.0;
- [device setVideoZoomFactor:zoomFactor];
- [device unlockForConfiguration];
- }
- }
-
- // 1.3.创建输入
- AVCaptureDeviceInput *input = [AVCaptureDeviceInput deviceInputWithDevice:device error:&error];
- if (error != nil) {
- return;
- }
-
- // 2.创建输出
- AVCaptureMetadataOutput *output = [[AVCaptureMetadataOutput alloc] init];
- [output setMetadataObjectsDelegate:self queue:dispatch_get_main_queue()];
-
- // 3.创建捕捉会话
- AVCaptureSession *session = [[AVCaptureSession alloc] init];
- [session addInput:input];
- [session addOutput:output];
-
- self.session = session;
-
- // 4.设置输入的内容类型
- // [output setMetadataObjectTypes:@[AVMetadataObjectTypeQRCode]];
- // [output setMetadataObjectTypes:@[AVMetadataObjectTypeQRCode, AVMetadataObjectTypeEAN13Code, AVMetadataObjectTypeEAN8Code, AVMetadataObjectTypeCode128Code]];
- NSMutableArray *types = [NSMutableArray array];
- if (self.supportQRCode) {
- [types addObject:AVMetadataObjectTypeQRCode];
- }
- if (self.supportBarCode) {
- [types addObjectsFromArray:@[AVMetadataObjectTypeEAN13Code, AVMetadataObjectTypeEAN8Code, AVMetadataObjectTypeCode128Code]];
- }
- [output setMetadataObjectTypes:[types copy]];
- // 5.添加预览图层(让用户看到扫描的界面)
- // 5.1.创建图层
- AVCaptureVideoPreviewLayer *previewLayer = [[AVCaptureVideoPreviewLayer alloc] initWithSession:session];
- previewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill;
- // 5.2.设置的layer的frame
- previewLayer.frame = inView.bounds;
- inView.clipsToBounds = YES;
- inView.layer.masksToBounds = YES;
- scanView.clipsToBounds = YES;
- scanView.layer.masksToBounds = YES;
- // 5.3.将图层添加到其它图层中
- [inView.layer insertSublayer:previewLayer below:scanView.layer];
- [previewLayer setAffineTransform:CGAffineTransformMakeScale(2.0, 2.0)];
- // 6.设置扫描区域
- CGSize screenSize = [UIScreen mainScreen].bounds.size;
- CGFloat x = scanView.frame.origin.y / screenSize.height;
- CGFloat y = scanView.frame.origin.x / screenSize.width;
- CGFloat w = scanView.frame.size.height / screenSize.height;
- CGFloat h = scanView.frame.size.width / screenSize.width;
- output.rectOfInterest = CGRectMake(x, y, w, h);
-
- // 7.开始扫描
- [self sessionStartRunning];
- }
- - (void)sessionStartRunning {
-
- @weakObj(self);
- dispatch_async(self.sessionQueue, ^{
- @strongObj(self);
- if (!self.session.running) {
- [self.session startRunning];
- }
- });
- }
- -(void)sessionStopRunning{
-
- @weakObj(self);
- dispatch_async(self.sessionQueue, ^{
- @strongObj(self);
- if (self.session.running) {
- [self.session stopRunning];
- }
- });
- }
- #pragma mark - 实现AVCaptureMetadataOutput代理方法
- - (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputMetadataObjects:(NSArray *)metadataObjects fromConnection:(AVCaptureConnection *)connection {
- // 1.遍历结果
-
- for (AVMetadataMachineReadableCodeObject *result in metadataObjects) {
- NSString *scannedResult = [(AVMetadataMachineReadableCodeObject *) result stringValue];
- [self addwarningtone];
- BLOCK_EXEC(_completionBlock,scannedResult);
- // [self stopScanning];
- break;
- }
- }
- #pragma mark 给扫描结果添加提示音
- -(void)addwarningtone{
- SystemSoundID soundID = 1000;
- AudioServicesPlaySystemSound(soundID);
- AudioServicesPlayAlertSound(soundID);
- }
- + (BOOL)isAvailable
- {
- @autoreleasepool {
- AVCaptureDevice *captureDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
-
- if (!captureDevice) {
- return NO;
- }
-
- NSError *error;
- AVCaptureDeviceInput *deviceInput = [AVCaptureDeviceInput deviceInputWithDevice:captureDevice error:&error];
-
- if (!deviceInput || error) {
- return NO;
- }
-
- return YES;
- }
- }
- + (BOOL)supportsMetadataObjectTypes:(NSArray *)metadataObjectTypes
- {
- if (![self isAvailable]) {
- return NO;
- }
-
- @autoreleasepool {
- // Setup components
- AVCaptureDevice *captureDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
- AVCaptureDeviceInput *deviceInput = [AVCaptureDeviceInput deviceInputWithDevice:captureDevice error:nil];
- AVCaptureMetadataOutput *output = [[AVCaptureMetadataOutput alloc] init];
- AVCaptureSession *session = [[AVCaptureSession alloc] init];
-
- [session addInput:deviceInput];
- [session addOutput:output];
-
- if (metadataObjectTypes == nil || metadataObjectTypes.count == 0) {
- // Check the QRCode metadata object type by default
- metadataObjectTypes = @[AVMetadataObjectTypeQRCode];
- }
-
- for (NSString *metadataObjectType in metadataObjectTypes) {
- if (![output.availableMetadataObjectTypes containsObject:metadataObjectType]) {
- return NO;
- }
- }
-
- return YES;
- }
- }
- - (void)stopScanning {
- [self sessionStopRunning];
- }
- @end
|