iOS开发-二维码扫描和应用跳转

序言

前面我们已经调到过怎么制作二维码,在我们能够生成二维码之后,如何对二维码进行扫描呢?

在iOS7之前,大部分应用中使用的二维码扫描是第三方的扫描框架,例如ZXing或者ZBar。使用时集成麻烦,出错也不方便调试。在iOS7之后,苹果自身提供了二维码的扫描功能,从效率上来说,原生的二维码远高于这些第三方框架。本文讲解如何使用原生框架实现二维码扫描功能,并且进行扫描后的项目跳转。
ps:本期的源代码会在文章结尾给出链接


扫描相关类

二维码扫描需要获取摄像头并读取照片信息,因此我们需要导入系统的AVFoundation框架,创建视频会话。我们需要用到一下几个类:

  • AVCaptureSession 会话对象。此类作为硬件设备输入输出信息的桥梁,承担实时获取设备数据的责任
  • AVCaptureDeviceInput 设备输入类。这个类用来表示输入数据的硬件设备,配置抽象设备的port
  • AVCaptureMetadataOutput 输出类。这个支持二维码、条形码等图像数据的识别
  • AVCaptureVideoPreviewLayer 图层类。用来快速呈现摄像头获取的原始数据
    二维码扫描功能的实现步骤是创建好会话对象,用来获取从硬件设备输入的数据,并实时显示在界面上。在扫描到相应图像数据的时候,通过AVCaptureVideoPreviewLayer类型进行返回

应用跳转

在使用第三方登陆、分享sdk的时候,我们的项目会在本机安装有目标平台的应用的情况下进行应用跳转,并且传递信息过去。这在沙盒机制下的iOS应用而言,理应是不符合规则的。但是,iOS SDK给我们提供了一个叫做url scheme的机制来实现这个功能。

url scheme让我们可以像使用Safari打开网页的方式跳转到其他应用中,并使用类似网络请求的GET请求的参数拼凑方式来在不同应用之间传递数据。

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


1.png

展开新增的字典,我们修改其中的URL Identifier以及新增加一个字段
URL Schemes。
Identifier用来跳转后,让跳转应用识别从哪里跳转过来的,我们可以设置为bundleID反转,来确保其特殊性。
URL Schemes是一个数组,我们将在这个数组里面自定义自己的url schemes,这里我们填写应用名。最终效果如下:


9A8E2746-D1D9-4BC2-81FE-23E13C5EF202.png

接着,我们就可以在其他应用中通过openURL:方法打开我们的app。


二维码扫描

二维码扫描的步骤:
1、创建设备会话对象,用来设置设备数据输入
2、获取摄像头,并且将摄像头对象加入当前会话中
3、实时获取摄像头原始数据显示在屏幕上
4、扫描到二维码/条形码数据,通过协议方法回调

  • 会话对象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)发现和预期的不一样,因为这个属性是以屏幕右上角为坐标原点,并且宽高的顺序要对换过来

1.jpg

如图所示,由于坐标系的不同,原本CGRectMake(0.3, 0.35, 0.4, 0.3)到了新坐标系中就变成了CGRectMake(0.35, 0.3, 0.3, 0.4)。那么大家设置成新的扫描范围之后,重新运行扫描程序,看看效果——然而,我们发现并不能扫描成功,这是因为这个扫描区域不仅仅是坐标系原点发生了改变。如下图所示

1.png

按照上面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的跳转机制后,二维码能够帮助我们的应用获得更加强大的能力,使得我们的应用之间有了更多联系。

文集:iOS开发

本文demo:二维码扫描集成
转载表明链接:http://sindrilin.com/ios-dev/2015/11/01/二维码扫描和应用跳转.html

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,185评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,445评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,684评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,564评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,681评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,874评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,025评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,761评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,217评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,545评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,694评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,351评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,988评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,778评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,007评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,427评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,580评论 2 349

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,633评论 18 139
  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,811评论 25 707
  • 一、前言 最近在做一个关于扫描二维码签到的小东西,所以还是上来写一篇关于二维码的文章,网上也有一些扫描二维码的框架...
    kim逸云阅读 4,385评论 2 8
  • 今天情绪失控在知道回婆婆家吃饭的时候。 我太Tmd不想去婆婆家吃饭!昨天前面忙的回家晚,到家后儿子和爱人才从婆婆家...
    云中看花阅读 167评论 0 0
  • 我一直觉得自己不是一个多么幸运的人,但比起那些真正不幸的人,我觉得我的不幸也算不得什么。我现在不是还活的好好的吗?...
    菀薇阅读 660评论 0 2