二維碼掃描和應用跳轉

轉載自: http://sindrilin.com/ios-dev/2015/11/01/二維碼掃描和應用跳轉.htmlhtml

 

前面咱們已經調到過怎麼製做二維碼,在咱們可以生成二維碼以後,如何對二維碼進行掃描呢?ios

在iOS7以前,大部分應用中使用的二維碼掃描是第三方的掃描框架,例如ZXing或者ZBar。使用時集成麻煩,出錯也不方便調試。在iOS7以後,蘋果自身提供了二維碼的掃描功能,從效率上來講,原生的二維碼遠高於這些第三方框架。本文講解如何使用原生框架實現二維碼掃描功能,而且進行掃描後的項目跳轉。數組

掃描相關類

二維碼掃描須要獲取攝像頭並讀取照片信息,所以咱們須要導入系統的AVFoundation框架,建立視頻會話。咱們須要用到一下幾個類:xcode

  • AVCaptureSession 會話對象。此類做爲硬件設備輸入輸出信息的橋樑,承擔實時獲取設備數據的責任
  • AVCaptureDeviceInput 設備輸入類。這個類用來表示輸入數據的硬件設備,配置抽象設備的port
  • AVCaptureMetadataOutput 輸出類。這個支持二維碼、條形碼等圖像數據的識別
  • AVCaptureVideoPreviewLayer 圖層類。用來快速呈現攝像頭獲取的原始數據 二維碼掃描功能的實現步驟是建立好會話對象,用來獲取從硬件設備輸入的數據,並實時顯示在界面上。在掃描到相應圖像數據的時候,經過AVCaptureVideoPreviewLayer類型進行返回

應用跳轉

在使用第三方登錄、分享sdk的時候,咱們的項目會在本機安裝有目標平臺的應用的狀況下進行應用跳轉,而且傳遞信息過去。這在沙盒機制下的iOS應用而言,理應是不符合規則的。可是,iOS SDK給咱們提供了一個叫作url scheme的機制來實現這個功能。微信

url scheme讓咱們能夠像使用Safari打開網頁的方式跳轉到其餘應用中,並使用相似網絡請求的GET請求的參數拼湊方式來在不一樣應用之間傳遞數據。網絡

使用url scheme的第一步是在項目的info.plist文件中添加新row,命名爲URL typessession

展開新增的字典,咱們修改其中的URL Identifier以及新增長一個字段
URL Schemes。
Identifier用來跳轉後,讓跳轉應用識別從哪裏跳轉過來的,咱們能夠設置爲bundleID反轉,來確保其特殊性。
URL Schemes是一個數組,咱們將在這個數組裏面自定義本身的url schemes,這裏咱們填寫應用名。最終效果以下:
app

接着,咱們就能夠在其餘應用中經過openURL:方法打開咱們的app。框架

二維碼掃描

二維碼掃描的步驟:ide

一、建立設備會話對象,用來設置設備數據輸入
二、獲取攝像頭,而且將攝像頭對象加入當前會話中
三、實時獲取攝像頭原始數據顯示在屏幕上
四、掃描到二維碼/條形碼數據,經過協議方法回調

  • 會話對象AVCaptureSession的建立

    _session = [AVCaptureSession new];
    [_session setSessionPreset: AVCaptureSessionPresetHigh];    //高質量採集
    [self setupIODevice];
  • setupIODevice方法中懶加載方式建立輸入對象和輸出對象,注意必須在輸出數據對象加入到當前會話後才能設置識別的數據格式。這裏設置爲掃描二維碼以及條形碼

    [_session addInput: self.input];
    [_session addOutput: self.output];
    _output.metadataObjectTypes = @[AVMetadataObjectTypeQRCode, AVMetadataObjectTypeEAN13Code, AVMetadataObjectTypeEAN8Code, AVMetadataObjectTypeCode128Code];
  • 建立AVCaptureMetadataOutput設置好掃描成功回調代理以及回調線程

    _output = [AVCaptureMetadataOutput new];
    [_output setMetadataObjectsDelegate: self queue: dispatch_get_main_queue()];
  • 建立AVCaptureDeviceInput輸入設備爲手機攝像頭

    AVCaptureDevice * device = [AVCaptureDevice defaultDeviceWithMediaType: AVMediaTypeVideo];
    _input = [AVCaptureDeviceInput deviceInputWithDevice: device error: nil];
  • 建立AVCaptureVideoPreviewLayer對象來實時獲取攝像頭圖像,咱們須要調用[self.view addSubview: self.scanView]把攝像頭獲取的圖像實時展現在屏幕上

    _scanView = [AVCaptureVideoPreviewLayer layerWithSession: self.session];
    _scanView.videoGravity = AVLayerVideoGravityResizeAspectFill;
    _scanView.frame = self.bounds;
  • 實現captureOutput: didOutputMetadataObjects: fromConnection:來獲取掃描獲得的數據。回調參數metadataObjects中存放了掃描結果,咱們須要先判斷這個數組的數據個數不爲0再執行下面的代碼:

    [self stop];
    AVMetadataMachineReadableCodeObject * metadataObject = metadataObjects[0];
    if ([self.delegate respondsToSelector: @selector(scanView:codeInfo:)]) {
        [self.delegate scanView: self codeInfo: metadataObject.stringValue];
        [self removeFromSuperview];
    } else {
        [[NSNotificationCenter defaultCenter] postNotificationName: LXDSuccessScanQRCodeNotification object: self userInfo: @{ LXDScanQRCodeMessageKey: metadataObject.stringValue }];

讀取二維碼信息進行應用跳轉

首先要說明的是,二維碼並不是必定要存儲應用的url scheme。例如公衆號的二維碼,雖然不知道是怎樣的數據存儲,但確定不是應用跳轉。能夠給本身的應用指定一個二維碼數據規則,例如支付寶付款掃描是讀取商品的ID、價格等信息,而後進行頁面跳轉付款。
這裏咱們使用上面設置的url scheme,咱們經過製做二維碼方法來定製一個存儲應用跳轉信息的二維碼,經過下面的代理建立一個存儲url scheme(使用url scheme的時候要注意在後面加上://後才能使用openURL進行跳轉)的二維碼,這一步應該放到模擬器上面生成

- (IBAction)createBarcode:(id)sender
    {
    UIImage * image = [UIImage imageOfQRFromURL: @"LXDDrawLosts://" codeSize: 160.f red: 123 green: 189 blue: 229 insertImage: nil];
    CGSize size = image.size;
    UIImageView * imageView = [[UIImageView alloc] initWithFrame:  ((CGRect){(CGPointZero), (size)})];
    imageView.center = self.view.center;
    imageView.image = image;
    [self.view addSubview: imageView];
}

建立二維碼掃描控制器,而後對咱們生成的二維碼進行掃描(這一步要在真機上面完成,上面url scheme的應用應當經過xcode安裝在手機上,才能完成跳轉)

LXDScanCodeController * scanCodeController = [LXDScanCodeController scanCodeController];
scanCodeController.scanDelegate = self;
[self.navigationController pushViewController: scanCodeController animated: YES];

掃描成功後判斷是否能夠打開跳轉,若是你的應用有一套二維碼數據存儲的規則,那麼在不能跳轉的時候應該按照這套規則解析數據。這裏我直接在沒法跳轉的狀況下顯示警告框告訴用戶沒法解析二維碼:

NSURL * url = [NSURL URLWithString: codeInfo];
if ([[UIApplication sharedApplication] canOpenURL: url]) {
    [[UIApplication sharedApplication] openURL: url];
} else {
    UIAlertView ** * alertView = [[UIAlertView alloc] initWithTitle: @"警告" message: [NSString stringWithFormat: @"%@:%@", @"沒法解析的二維碼", codeInfo] delegate: nil cancelButtonTitle: @"肯定" otherButtonTitles: nil];
    [alertView show];
}

按照上面的步驟進行的話,那麼在你掃完二維碼以後,你的手機就會跳轉到剛纔設置url scheme的應用中。

掃描優化

上面已經完成了二維碼的掃描功能實現,可是如今你會發現咱們在使用上面代碼進行掃描的時候,整個屏幕都是掃描範圍,這樣會影響掃描的準確性以及咱們調整掃描範圍的難度。
蘋果提供了一種方式讓咱們規定掃描範圍:在AVCaptureMetadataOutput中有一個叫作rectOfInterest的CGRect類型屬性,這個屬性用來限制掃描範圍。
這個屬性的每個值取值範圍在0~1之間,表明的是對應軸上的比例大小。最開始我覺得這個是以左上角爲原點,後來設置爲CGRectMake(0.3, 0.35, 0.4, 0.3)發現和預期的不同,由於這個屬性是以屏幕右上角爲座標原點,而且寬高的順序要對換過來

如圖所示,因爲座標系的不一樣,本來CGRectMake(0.3, 0.35, 0.4, 0.3)到了新座標系中就變成了CGRectMake(0.35, 0.3, 0.3, 0.4)。那麼你們設置成新的掃描範圍以後,從新運行掃描程序,看看效果——然而,咱們發現並不能掃描成功,這是由於這個掃描區域不只僅是座標系原點發生了改變。以下圖所示

按照上面CGRect的設置,我是想要把掃描範圍控制在屏幕x軸上面0.3-0.7,y軸上0.35-0.65之間的範圍。可是在這個屬性中,width和height分別表示的是在rectOfInterest座標中掃描矩形右下角的座標點位置。所以,這個掃描範圍應該是CGRectMake(0.35, 0.3, 0.65, 0.7)。除了設置好掃描範圍以內,咱們還能夠仿照微信的掃描,給非掃描範圍加上一層半透明的黑色layer


應用傳值

前面說過,url scheme不只僅支持應用跳轉,它還支持使用相似get請求的方式在應用間傳值。上面跳轉的url scheme是LXDDrawLosts://,那麼相似get請求,咱們在這個字符串後面加上一個?表示區分開參數和應用id,使用&分隔不一樣參數,而後後面按照字段名=屬性值的方式拼湊連接。
好比,假設這是一個即時通信app,那麼我能夠制定這樣的一個跳轉參數規則:

  • method 表示操做類型
  • userId 用戶id
  • title 分享標題
  • message 分享消息
  • link_url 分享連接

那麼,若是傳入的是
LXDDrawLosts://?method=addFriends&userId=10086
這可能表明的是掃描後添加id爲10086的新好友。

又好比

LXDDrawLosts://?method=shareMessage&title=分享測試&message=這是林欣達的分享測試&link_url=http://www.jianshu.com/users/0cf7d455eb9e/latest_articles
這表明分享信息到你的app中。這些都是咱們本身的應用能夠制定的規則,若是有興趣,能夠新浪微博開放平臺或者騰訊開放平臺,他們的文檔中應該有url scheme的傳值標準。

說完了經過url scheme傳入參數後,怎麼把這些參數取出來呢?AppDelegate中提供了application:openURL: sourceApplication: annotation:方法讓咱們能夠取出傳入的值。
在咱們經過url scheme跳轉到本應用的時候,這個方法就會被系統調用。其中,有兩個重要的參數須要咱們知道

  • sourceApplication 這個字符串保存了跳轉方app的url Identifier,就是上文中除了url scheme之外的另外一個字段
  • url 這個連接中存儲了跳轉的url scheme以及參數列表,咱們經過[url scheme]方法獲取前者;用[url query]方法獲取?以後的參數列表,而後使用字符串的分隔方法把這些數據讀取出來

單純的二維碼數據並無過於強大的功能,但結合了url scheme的跳起色制後,二維碼可以幫助咱們的應用得到更增強大的能力,使得咱們的應用之間有了更多聯繫。

相關文章
相關標籤/搜索