之前很多二維碼掃描都是基于zxing做的拙泽,但是zxing用起來真的很麻煩隆豹,又一直不更新屯碴。隨著iOS6退出歷史舞臺践叠,終于可以使用iOS7以后言缤,用系統(tǒng)的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做優(yōu)化管挟。
-(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是個掃描動畫的計時器,可以略過不看弄捕。
處理掃描的結(jié)果
- (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系統(tǒng)自帶的瀏覽器打開url就行察藐,或者自己寫個內(nèi)置的瀏覽器打開皮璧。
用別人的掃描器掃自己的二維碼
首先將自己的二維碼定義成http://www.xxx.com/xxxxx
這樣的自己域名的url。
那么第三方的二維碼掃出來后分飞,會跳向這個網(wǎng)址悴务。
其次在服務(wù)器上部署這個頁面,加入如下的代碼
<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 = "要跳轉(zhuǎn)的頁面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 = "要跳轉(zhuǎn)的頁面URL";
}
}
</script>
這段代碼是基于url schemes的原理譬猫,如果你的app里存在這個url schemes(例子里是test://)讯檐,那么會立刻打開這個url,如果不存在染服,就會超過25毫秒别洪,那么就指向另一個頁面,一般是下載頁柳刮。
接著挖垛,在app的url schemes里設(shè)置,比如test
這個時候秉颗,瀏覽器發(fā)出test://
的請求的時候痢毒,就能立刻打開這個app了。
最后蚕甥,如果不滿足于掃描二維碼只能打開app哪替,想對二維碼里的內(nèi)容做一些操作的話,可以:
- 將二維碼的內(nèi)容定義成
http://www.xxx.com/xxxxx?uid=xxx
這樣菇怀,當(dāng)然后面的參數(shù)需要加密凭舶。 - 在js代碼里獲取這個參數(shù),并原封不動的附加在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;
}