qt for ios掃描二維碼功能實現

來源:互聯網
上載者:User

標籤:

問題:  

公司項目考慮到跨平台一直都是用qt做,由於項目需求,項目上要增加一個二維碼掃描功能,在安卓可以用QVideoProbe實現抓取網路攝影機視訊框架,用QZxing解碼圖片,從而實現二維碼掃描,但是在ios上,QVideProbe並不支援,所以只好選擇其他抓取視訊框架的方法,考慮使用OPencv實現抓取視訊框架,但是在查看ios文檔時,ios7 以上直接支援二維碼掃描功能,所以放棄使用opencv抓取 + zxing解碼的方法.從而採取ios官方提供的二維碼解碼功能.

 

實現:

由於我們項目ui一直是用qml實現,但是要實現掃描二維碼功能,需要調用AVFoundation中的方法,同時要顯示ios中的ui顯示網路攝影機及返回qml 鍵.所以這裡需要結合oc 和 qt編程.

直接上代碼:

pro檔案增加

ios {

  OBJECTIVE_SOURCES += IOSView.mm  \  # object c++ file

       IOSCamera.mm 

  HEADER +=  IOSView.h \

      IOSCamera.h \

      IOSCameraViewProtocol.h 

 

  QMAKE_LFLAGS += -framework AVFoundation  #add AVfoundation framework

 

  QT += gui private

}

重新qmake產生xcode project

IOSView.#include <QQuickItem>

class IOSView : public QQuickItem{    Q_OBJECT    Q_PROPERTY(QString qrcodeText READ qrcodeText WRITE setQrcodeText NOTIFY qrcodeTextChanged)        public:    explicit IOSView(QQuickItem *parent = 0);            QString qrcodeText() {       return m_qrcodeText;    }        void setQrcodeText(QString text){        m_qrcodeText = text;        emit qrcodeTextChanged();    }           QString m_qrcodeText;                public slots:    void startScan();  //for open ios camera scan and ui        private:    void *m_delegate;  //for communication with qt        signals:    void qrcodeTextChanged();      void stopCameraScan();  //show qml};

IOSView..mm

#include <UIKit/UIKit.h>#include <QtQuick>#include <QtGui>#include <QtGui/qpa/qplatformnativeinterface.h>#include "IOSView.h"#include "IOSCamera.h"@interface IOSCameraDelegate : NSObject <IOSCameraProtocol> {    IOSView *m_iosView;}@end@implementation IOSCameraDelegate- (id) initWithIOSCamera:(IOSView *)iosView{    self = [super init];    if (self) {        m_iosView = iosView;    }    return self;}-(void) scanCancel{    emit m_iosView->stopCameraScan();}-(void) scanResult :(NSString *) result{    m_iosView->setQrcodeText(QString::fromNSString(result));}@endIOSView::IOSView(QQuickItem *parent) :    QQuickItem(parent), m_delegate([[IOSCameraDelegate alloc] initWithIOSCamera:this]){}    void IOSView::startScan(){    // Get the UIView that backs our QQuickWindow:    UIView *view = static_cast<UIView *>(QGuiApplication::platformNativeInterface()->nativeResourceForWindow("uiview", window()));    UIViewController *qtController = [[view window] rootViewController];    IOSCamera *iosCamera = [[[IOSCameraView alloc] init ]autorelease];    iosCamera.delegate = (id)m_delegate;    // Tell the imagecontroller to animate on top:    [qtController presentViewController:iosCamera animated:YES completion:nil];    [iosCamera startScan];}

  

IOSCameraViewProtocol.h

#import <Foundation/Foundation.h>@protocol CameraScanViewProtocol <NSObject>@required-(void) scanCancel;-(void) scanResult :(NSString *) result;@end

  

IOSCamera.h

#import <UIKit/UIKit.h>#import <AVFoundation/AVFoundation.h>#import "CameraViewProtocol.h"@interface IOSCamera : UIViewController <AVCaptureMetadataOutputObjectsDelegate>{    id<CameraScanViewProtocol> delegate;}@property (retain, nonatomic) IBOutlet UIView *viewPreview;- (IBAction)backQtApp:(id)sender;-(void) startScan;@property (retain) id<CameraScanViewProtocol> delegate;@end

  

IOSCamera.cpp#import "IOSCamera.h"

@interface IOSCamera ()@property (nonatomic,strong) AVCaptureSession * captureSession;@property (nonatomic,strong) AVCaptureVideoPreviewLayer * videoPreviewLayer;-(BOOL) startReading;-(void) stopReading;-(void) openQtLayer;@end@implementation CameraScanView@synthesize delegate;    //Sync delegate for interactive with qt- (void)viewDidLoad {    [super viewDidLoad];    // Do any additional setup after loading the view from its nib.        // Initially make the captureSession object nil.    _captureSession = nil;        // Set the initial value of the flag to NO.    _isReading = NO;        // Begin loading the sound effect so to have it ready for playback when it‘s needed.    [self loadBeepSound];
}- (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated.}/*#pragma mark - Navigation- (void)dealloc { [_viewPreview release]; [super dealloc];}- (void)viewDidUnload { [self setViewPreview:nil]; [super viewDidUnload];}
- (IBAction)backQtApp:(id)sender {    [delegate scanCancel];
    [self stopReading];
}

-(void) openQtLayer{
    // Bring back Qt‘s view controller:
    UIViewController *rvc = [[[UIApplication sharedApplication] keyWindow] rootViewController];
    [rvc dismissViewControllerAnimated:YES completion:nil];
}

-(void) startScan{
    if (!_isReading) {
        // This is the case where the app should read a QR code when the start button is tapped.
        if ([self startReading]) {
            // If the startReading methods returns YES and the capture session is successfully
            // running, then change the start button title and the status message.
            NSLog(@"Start Reading !!");
        }
    }
}

#pragma mark - Private method implementation

- (BOOL)startReading {
    NSError *error;
    
    // Get an instance of the AVCaptureDevice class to initialize a device object and provide the video
    // as the media type parameter.
    AVCaptureDevice *captureDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
    
    // Get an instance of the AVCaptureDeviceInput class using the previous device object.
    AVCaptureDeviceInput *input = [AVCaptureDeviceInput deviceInputWithDevice:captureDevice error:&error];
    
    if (!input) {
        // If any error occurs, simply log the description of it and don‘t continue any more.
        NSLog(@"%@", [error localizedDescription]);
        return NO;
    }
    
    // Initialize the captureSession object.
    _captureSession = [[AVCaptureSession alloc] init];
    // Set the input device on the capture session.
    [_captureSession addInput:input];
    
    
    // Initialize a AVCaptureMetadataOutput object and set it as the output device to the capture session.
    AVCaptureMetadataOutput *captureMetadataOutput = [[AVCaptureMetadataOutput alloc] init];
    [_captureSession addOutput:captureMetadataOutput];
    
    // Create a new serial dispatch queue.
    dispatch_queue_t dispatchQueue;
    dispatchQueue = dispatch_queue_create("myQueue", NULL);
    [captureMetadataOutput setMetadataObjectsDelegate:self queue:dispatchQueue];
    [captureMetadataOutput setMetadataObjectTypes:[NSArray arrayWithObject:AVMetadataObjectTypeQRCode]];
    
    // Initialize the video preview layer and add it as a sublayer to the viewPreview view‘s layer.
    _videoPreviewLayer = [[AVCaptureVideoPreviewLayer alloc] initWithSession:_captureSession];
    [_videoPreviewLayer setVideoGravity:AVLayerVideoGravityResizeAspectFill];
    [_videoPreviewLayer setFrame:_viewPreview.layer.bounds];
    [_viewPreview.layer addSublayer:_videoPreviewLayer];
    
    
    // Start video capture.
    [_captureSession startRunning];
    _isReading = YES;
    return YES;
}


-(void)stopReading{
    // Stop video capture and make the capture session object nil.
    [_captureSession stopRunning];
    _captureSession = nil;
   
   // Remove the video preview layer from the viewPreview view‘s layer.
   [_videoPreviewLayer removeFromSuperlayer];
   _isReading = NO;
   [self openQtLayer];
}

#pragma mark - AVCaptureMetadataOutputObjectsDelegate method implementation

-(void)captureOutput:(AVCaptureOutput *)captureOutput didOutputMetadataObjects:(NSArray *)metadataObjects fromConnection:(AVCaptureConnection *)connection{
    
    // Check if the metadataObjects array is not nil and it contains at least one object.
    if (metadataObjects != nil && [metadataObjects count] > 0) {
        // Get the metadata object.
        AVMetadataMachineReadableCodeObject *metadataObj = [metadataObjects objectAtIndex:0];
        if ([[metadataObj type] isEqualToString:AVMetadataObjectTypeQRCode]) {
            // If the found metadata is equal to the QR code metadata then update the status label‘s text,
            // stop reading and change the bar button item‘s title and the flag‘s value.
            // Everything is done on the main thread.
            [delegate scanResult:[metadataObj stringValue]];  //send scan result to qt show
            
            [self performSelectorOnMainThread:@selector(stopReading) withObject:nil waitUntilDone:NO];
            
            _isReading = NO;
        }
    }
}

@end
 

OK.大概流程就這些了,添加xib檔案等就不介紹了.

 

qt for ios掃描二維碼功能實現

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.