iOS

[iOS] AVCaptureSession를 이용한 Barcode Scanner

i-moo 2020. 1. 6. 19:14
반응형

 

1. plist에 Camera 권한 추가

<key>NSCameraUsageDescription</key>

<string>test</string>

 

2. Camera 권한 체크

 

2-1. import

#import <AVFoundation/AVFoundation.h>

 

2-2. 권한 얻기

- (void)permissionCamera {

    AVAuthorizationStatus status = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo];

    if(status == AVAuthorizationStatusAuthorized) {

        // 카메라 접근 권한 동의

        [self setupScanningSession];

    }

    else if(status == AVAuthorizationStatusDenied) {

        // 카메라 접근 권한 동의 해제

        dispatch_async(dispatch_get_main_queue(), ^{

            [SSLoader showErrorWithMessage:@"설정 > APP > 카메라 접근 권한을 허용해주세요."];

        });

    }

    else if(status == AVAuthorizationStatusNotDetermined) {

        // 카메라 접근 권한 동의 전

        

        [AVCaptureDevice requestAccessForMediaType:AVMediaTypeVideo completionHandler:^(BOOL granted) {

            if (granted) {

                [self setupScanningSession];

            }

            else {

                dispatch_async(dispatch_get_main_queue(), ^{

                    [SSLoader showErrorWithMessage:@"설정 > APP > 카메라 접근 권한을 허용해주세요."];

                });

                

            }

        }];

    }

    

}

 

3. AVCaptureSession 초기화

 

3-1. session metadata에대한 딜리게이트 추가

@interface BarcodeViewController () <AVCaptureMetadataOutputObjectsDelegate>

 

3-2. AVCaptureSession, AVCaptureDevice, AVCaptureVideoPreviewLayer 초기화

- (void)setupScanningSession {

    // Initalising hte Capture session before doing any video capture/scanning.

    self.captureSession = [[AVCaptureSession alloc] init];

    

    NSError *error;

    // Set camera capture device to default and the media type to video.

    self.captureDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];

    [self.captureDevice lockForConfiguration:nil];

    self.captureDevice.focusMode = AVCaptureFocusModeContinuousAutoFocus;

    [self.captureDevice unlockForConfiguration];

    

    // Set video capture input: If there a problem initialising the camera, it will give am error.

    AVCaptureDeviceInput *input = [AVCaptureDeviceInput deviceInputWithDevice:self.captureDevice error:&error];

    

    if (!input || error) {

        NSLog(@"Error Getting Camera Input : %@", error? error.userInfo:@"");

        return;

    }

    // Adding input souce for capture session. i.e., Camera

    [self.captureSession addInput:input];

    

    AVCaptureMetadataOutput *captureMetadataOutput = [[AVCaptureMetadataOutput alloc] init];

    // Set output to capture session. Initalising an output object we will use later.

    [self.captureSession addOutput:captureMetadataOutput];

    

    // Create a new queue and set delegate for metadata objects scanned.

    dispatch_queue_t dispatchQueue;

    dispatchQueue = dispatch_queue_create("scanQueue", NULL);

    [captureMetadataOutput setMetadataObjectsDelegate:self queue:dispatchQueue];

    // Delegate should implement captureOutput:didOutputMetadataObjects:fromConnection: to get callbacks on detected metadata.

    [captureMetadataOutput setMetadataObjectTypes:[captureMetadataOutput availableMetadataObjectTypes]];

    

    // Layer that will display what the camera is capturing.

    self.captureLayer = [[AVCaptureVideoPreviewLayer alloc] initWithSession:self.captureSession];

    [self.captureLayer setVideoGravity:AVLayerVideoGravityResizeAspectFill];

    [self.captureLayer setFrame:self.barcodeView.layer.bounds];

    // Adding the camera AVCaptureVideoPreviewLayer to our view's layer.

    [self.barcodeView.layer addSublayer:self.captureLayer];

}

 

3-3. 이슈 있었던 부분

viewDidLoad, viewWillAppear 메소드에 3-2부분을 넣어주면 layer가 뷰에 설정해놓은 값으로 들어가게 된다.

즉, 뷰(xib, storyboard)에서 SE 기준으로 XR에 빌드했을 경우! 왼쪽 이미지처럼 나오게 된다.

viewWillAppear는 괜찮을 줄 알았는데 로드하는데 있어 약간 타이밍 문제가 있나보다.

해결 방법은 파란 코드 부분을 viewDidAppear로 분리시켰을 때 오른쪽 이미지처럼 정상작동 했다.

최종 작업해놓은 코드는 viewDidLoad에서 통신하는 부분이 있어 통신이 끝난 후에 3번을 수행하도록 해놓았다.

 

4. 바코드 인식 시작

[self.captureSession startRunning];

 

5. 인식된 데이터 처리

 

https://developer.apple.com/documentation/avfoundation/avcapturemetadataoutputobjectsdelegate?language=objc

 

AVCaptureMetadataOutputObjectsDelegate - AVFoundation | Apple Developer Documentation

Protocol AVCaptureMetadataOutputObjectsDelegate Methods for receiving metadata produced by a metadata capture output. Declaration@protocol AVCaptureMetadataOutputObjectsDelegate OverviewThe AVCaptureMetadataOutputObjectsDelegate protocol must be adopted by

developer.apple.com

 

#pragma mark - AVCaptureMetadataOutputObjectsDelegate

- (void)captureOutput:(AVCaptureOutput *)output didOutputMetadataObjects:(NSArray<__kindof AVMetadataObject *> *)metadataObjects fromConnection:(AVCaptureConnection *)connection {

    // Do your action on barcode capture here:

    NSString *capturedBarcode = nil;

    

    // Specify the barcodes you want to read here:

    NSArray *supportedBarcodeTypes = @[AVMetadataObjectTypeUPCECode,

                                       AVMetadataObjectTypeCode39Code,

                                       AVMetadataObjectTypeCode39Mod43Code,

                                       AVMetadataObjectTypeEAN13Code,

                                       AVMetadataObjectTypeEAN8Code,

                                       AVMetadataObjectTypeCode93Code,

                                       AVMetadataObjectTypeCode128Code,

                                       AVMetadataObjectTypePDF417Code,

                                       AVMetadataObjectTypeQRCode,

                                       AVMetadataObjectTypeAztecCode];

    

    // In all scanned values..

    for (AVMetadataObject *barcodeMetadata in metadataObjects) {

        // ..check if it is a suported barcode

        for (NSString *supportedBarcode in supportedBarcodeTypes) {

            

            if ([supportedBarcode isEqualToString:barcodeMetadata.type]) {

                // This is a supported barcode

                // Note barcodeMetadata is of type AVMetadataObject

                // AND barcodeObject is of type AVMetadataMachineReadableCodeObject

                AVMetadataMachineReadableCodeObject *barcodeObject = (AVMetadataMachineReadableCodeObject *)[self.captureLayer transformedMetadataObjectForMetadataObject:barcodeMetadata];

                

                capturedBarcode = [barcodeObject stringValue];

                NSLog(@"capturedBarcode = %@", capturedBarcode);

                

                break;

            }

        }

    }

}

 

6. 바코드 인식 멈춤

[self.captureSession stopRunning];

 

- 플래시 기능 추가

flash와 torch의 차이 : https://developer.apple.com/library/archive/documentation/AudioVideo/Conceptual/AVFoundationPG/Articles/04_MediaCapture.html

 

Still and Video Media Capture

Still and Video Media Capture To manage the capture from a device such as a camera or microphone, you assemble objects to represent inputs and outputs, and use an instance of AVCaptureSession to coordinate the data flow between them. Minimally you need: An

developer.apple.com

 

flash :  이미지를 밝게 촬영하는데 사용.

torch : 비디오를 지속적으로 밝게 비추는데 사용.

기존 카메라에서도 확인해보면 사진 촬영할 때 플래시를 키면 찍는 순간 플래시가 켜지고, 비디오 촬영할 때 플래시를 키면 플래시가 계속 켜져있는 것을 확인 할 수 있다.

 

if (self.captureDevice && self.captureDevice.hasTorch) {

        if (self.captureDevice.torchMode == AVCaptureTorchModeOff) {

            if ([self.captureDevice isTorchModeSupported:AVCaptureTorchModeOn]) {

                [self.captureDevice lockForConfiguration:nil];

                [self.captureDevice setTorchMode:AVCaptureTorchModeOn];

                [self.captureDevice unlockForConfiguration];

            }

        }

        else {

            if ([self.captureDevice isTorchModeSupported:AVCaptureTorchModeOff]) {

                [self.captureDevice lockForConfiguration:nil];

                [self.captureDevice setTorchMode:AVCaptureTorchModeOff];

                [self.captureDevice unlockForConfiguration];

            }

        }

}

 

 

 

참고한 URL :

https://ayeohyes.wordpress.com/2015/05/09/barcode-scanning-in-ios-using-avfoundation/

 

Barcode scanning in iOS using AVFoundation

Barcode scanning in iOS using AVFoundation.

ayeohyes.wordpress.com

 

https://www.infragistics.com/community/blogs/b/torrey-betts/posts/scanning-barcodes-with-ios-7-objective-c

 

Scanning Barcodes with iOS 7 (Objective-C) | Infragistics Blog

Introduction With the release of iOS 7, Apple included the ability to detect barcodes through its AV Foundation framework. The supported types are: ...

www.infragistics.com

 

 

반응형

'iOS' 카테고리의 다른 글

[iOS] Firebase 호스팅 설정  (0) 2020.09.23
[Xcode] git ignore 설정  (0) 2020.07.02
[iOS] iOS 13.0 DarkMode Check (Widget 포함)  (0) 2019.08.30
[iOS] WKWebView setCookie not working!!! 해결  (6) 2019.08.08
[iOS] 푸시 인증서_서버 전달  (0) 2019.07.31