iOS掃一掃功能開發

之前很多二維碼掃描都是基于zxing做的,但是zxing用起來真的很麻煩,又一直不更新。隨著iOS6退出歷史舞臺,終于可以使用iOS7以后,用系統的AVFoundation做的二維碼掃描器了。

初始化相機,掃描器

- (void)setupCamera
{
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    // 耗時的操作
        // Device
        _device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
        
        // Input
        _input = [AVCaptureDeviceInput deviceInputWithDevice:self.device error:nil];
        
        // Output
        _output = [[AVCaptureMetadataOutput alloc]init];
        //    [_output setMetadataObjectsDelegate:self queue:dispatch_get_main_queue()];
        [_output setMetadataObjectsDelegate:self queue:dispatch_get_main_queue()];
        
        // Session
        _session = [[AVCaptureSession alloc]init];
        [_session setSessionPreset:AVCaptureSessionPresetHigh];
        if ([_session canAddInput:self.input])
        {
            [_session addInput:self.input];
        }
        
        if ([_session canAddOutput:self.output])
        {
            [_session addOutput:self.output];
        }
        
        // 條碼類型 AVMetadataObjectTypeQRCode
        _output.metadataObjectTypes =@[AVMetadataObjectTypeQRCode];
        dispatch_async(dispatch_get_main_queue(), ^{
            // 更新界面
            // Preview
            _preview =[AVCaptureVideoPreviewLayer layerWithSession:self.session];
            _preview.videoGravity = AVLayerVideoGravityResizeAspectFill;
            //    _preview.frame =CGRectMake(20,110,280,280);
            _preview.frame = self.view.bounds;
            [self.view.layer insertSublayer:self.preview atIndex:0];
            // Start
            [_session startRunning];
        });
    });
}

在viewWillAppear和viewWillDisappear里對session做優化。

-(void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];
    if (_session && ![_session isRunning]) {
        [_session startRunning];
    }
    timer = [NSTimer scheduledTimerWithTimeInterval:.02 target:self selector:@selector(animation1) userInfo:nil repeats:YES];
}

- (void)viewWillDisappear:(BOOL)animated
{
    [super viewWillDisappear:animated];
    [timer invalidate];
}

以上timer是個掃描動畫的計時器,可以略過不看。

處理掃描的結果

- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputMetadataObjects:(NSArray *)metadataObjects fromConnection:(AVCaptureConnection *)connection
{
    
    NSString *stringValue;
    
    if ([metadataObjects count] >0)
    {
        AVMetadataMachineReadableCodeObject * metadataObject = [metadataObjects objectAtIndex:0];
        stringValue = metadataObject.stringValue;
    }
    
    [_session stopRunning];
    [timer invalidate];
    NSLog(@"%@",stringValue);
    
}

用二維碼掃描器掃自己的二維碼

NSString *url = [NSURL URLWithString:@"html/judgement.html" relativeToURL:[ZXApiClient sharedClient].baseURL].absoluteString;
    
    if ([stringValue hasPrefix:url]) {
        //如果掃出來的url是自己的域名開頭的,那么做如下的處理。
    } 

用二維碼掃描器掃別人的二維碼

[[UIApplication sharedApplication] openURL:[NSURL URLWithString:stringValue]];

直接使用openUrl系統自帶的瀏覽器打開url就行,或者自己寫個內置的瀏覽器打開。

用別人的掃描器掃自己的二維碼

首先將自己的二維碼定義成http://www.xxx.com/xxxxx這樣的自己域名的url。
那么第三方的二維碼掃出來后,會跳向這個網址。

其次在服務器上部署這個頁面,加入如下的代碼

<script language="javascript">
  if (navigator.userAgent.match(/(iPhone|iPod|iPad);?/i)) {
    var loadDateTime = new Date();
    window.setTimeout(function() {
      var timeOutDateTime = new Date();
      if (timeOutDateTime - loadDateTime < 5000) {
        window.location = "要跳轉的頁面URL";
      } else {
        window.close();
      }
    },
    25);
    window.location = " test:// ";
  } else if (navigator.userAgent.match(/android/i)) {
    var state = null;
    try {
      state = window.open("apps custom url schemes ", '_blank');
    } catch(e) {}
    if (state) {
      window.close();
    } else {
      window.location = "要跳轉的頁面URL";
    }
  }
</script>

這段代碼是基于url schemes的原理,如果你的app里存在這個url schemes(例子里是test://),那么會立刻打開這個url,如果不存在,就會超過25毫秒,那么就指向另一個頁面,一般是下載頁。

接著,在app的url schemes里設置,比如test

Paste_Image.png

這個時候,瀏覽器發出test://的請求的時候,就能立刻打開這個app了。

最后,如果不滿足于掃描二維碼只能打開app,想對二維碼里的內容做一些操作的話,可以:

  • 將二維碼的內容定義成http://www.xxx.com/xxxxx?uid=xxx這樣,當然后面的參數需要加密。
  • 在js代碼里獲取這個參數,并原封不動的附加在url schemes后面,如test://uid=xxx
  • 在appDelegate里加上如下代碼。
 - (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url
{
    if ([url.absoluteString hasPrefix:@"test://uid="]) {
        NSString *uid = [url.absoluteString substringFromIndex:11];
        NSLog(@"uid=%@",uid);
        //對uid進行操作
    } else {
        //其他的地方拋過來的url,比如微信
        return [WXApi handleOpenURL:url delegate:self];
    }
    return YES;
}

用別人的掃描器掃別人的二維碼

34ebbc5ccf91e9deffe7f8d1fead2675.png

最后來張效果圖

2015-04-08 09_52_30.gif

應許多同學要求,上個demo

demo

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容