感測器集錦 :指紋識別、運動感測器、加速計、環境光感、距離感測器、磁力計、陀螺儀
一、指紋識別
應用:指紋解鎖、指紋登入、指紋支付
蘋果從iPhone5S開始,具有指紋識別技術,從iOS8.0之後蘋果允許第三方 App 使用 Touch ID進行身份驗證。 連續三次指紋識別錯誤後,會自動彈出密碼框,通過Touch ID的密碼進行身份驗證,如果此時取消密碼驗證,再2次指紋識別失敗後,也就是 3 + 2 = 5次指紋識別失敗後,Touch ID功能被鎖定,就只能通過密碼來進行身份驗證和解鎖Touch ID 功能。
全部程式碼如下:
#import <LocalAuthentication/LocalAuthentication.h>
-(void)OnTouchIDBtn:(UIButton *)sender{
//判斷裝置是否支援Touch ID
if ([[UIDevice currentDevice].systemVersion floatValue] < 8.0) {
[self createAlterView:@"不支援指紋識別"];
return;
}else{
LAContext *ctx = [[LAContext alloc] init];
//設定 輸入密碼 按鈕的標題
ctx.localizedFallbackTitle = @"驗證登入密碼";
//設定 取消 按鈕的標題 iOS10之後
ctx.localizedCancelTitle = @"取消";
//檢測指紋資料庫更改 驗證成功後返回一個NSData物件,否則返回nil
//ctx.evaluatedPolicyDomainState;
// 這個屬性應該是類似於支付寶的指紋開啟應用,如果你開啟他解鎖之後,按Home鍵返回桌面,再次進入支付寶是不需要錄入指紋的。因為這個屬性可以設定一個時間間隔,在時間間隔內是不需要再次錄入。預設是0秒,最長可以設定5分鐘
//ctx.touchIDAuthenticationAllowableReuseDuration = 5;
NSError * error;
_localizedReason = @"通過Home鍵驗證已有手機指紋";
// 判斷裝置是否支援指紋識別
if ([ctx canEvaluatePolicy:LAPolicyDeviceOwnerAuthentication error:&error]) {
// 驗證指紋是否匹配,需要彈出輸入密碼的彈框的話:iOS9之後用 LAPolicyDeviceOwnerAuthentication ; iOS9之前用LAPolicyDeviceOwnerAuthenticationWithBiometrics
[ctx evaluatePolicy:LAPolicyDeviceOwnerAuthentication localizedReason:_localizedReason reply:^(BOOL success, NSError * error) {
if (success) {
[self createAlterView:@"指紋驗證成功"];
}else{
// 錯誤碼 error.code
NSLog(@"指紋識別錯誤描述 %@",error.description);
// -1: 連續三次指紋識別錯誤
// -2: 在TouchID對話方塊中點選了取消按鈕
// -3: 在TouchID對話方塊中點選了輸入密碼按鈕
// -4: TouchID對話方塊被系統取消,例如按下Home或者電源鍵
// -8: 連續五次指紋識別錯誤,TouchID功能被鎖定,下一次需要輸入系統密碼
NSString * message;
switch (error.code) {
case -1://LAErrorAuthenticationFailed
message = @"已經連續三次指紋識別錯誤了,請輸入密碼驗證";
_localizedReason = @"指紋驗證失敗";
break;
case -2:
message = @"在TouchID對話方塊中點選了取消按鈕";
return ;
break;
case -3:
message = @"在TouchID對話方塊中點選了輸入密碼按鈕";
break;
case -4:
message = @"TouchID對話方塊被系統取消,例如按下Home或者電源鍵或者彈出密碼框";
break;
case -8:
message = @"TouchID已經被鎖定,請前往設定介面重新啟用";
break;
default:
break;
}
[self createAlterView:message];
}
}];
}else{
if (error.code == -8) {
[self createAlterView:@"由於五次識別錯誤TouchID已經被鎖定,請前往設定介面重新啟用"];
}else{
[self createAlterView:@"TouchID沒有設定指紋,請前往設定"];
}
}
}
}
- (void)createAlterView:(NSString *)message{
UIAlertController * vc = [UIAlertController alertControllerWithTitle:@"提示" message:message preferredStyle:UIAlertControllerStyleAlert];
[self presentViewController:vc animated:NO completion:^(void){
[NSThread sleepForTimeInterval:1.0];
[vc dismissViewControllerAnimated:YES completion:nil];
}];
}
複製程式碼
二、運動感測器/加速計/陀螺儀
應用:水平位置測試、搖一搖、計步器、遊戲、特效動畫
加速計和運動感測器主要監測裝置在X、Y、Z軸上的加速度 ,根據加速度數值,就可以判斷出在各個方向上的作用力度,陀螺儀主要用來監測裝置的旋轉方向和角度。
這幾個感測器都是依賴於蘋果官方CoreMotion框架,用法都差不多,先判斷各個感測器是否可用開啟,然後設定各個感測器的採集頻率,接著就開始採集資料,並返回採集到的運動資訊引數:各個方向的重力加速度、旋轉方向角度等等。
- 示例效果:圖片旋轉的第一張圖片用於檢測裝置是否處於水平位置,第二張圖是裝置無論在豎直/水平方向上怎麼旋轉,圖片都保持於水平/豎直方向垂直。滾動小球不僅用了加速計,還用到了CoreMotion框架中行為管理CMMotionManager中的碰撞、重力行為,和動力學屬性:摩擦、密度、彈力、阻力等
- 運動感測器的示例程式碼如下,其它的用法都差不多,只是相關的方法名稱、屬性名稱和返回的引數型別和值不同,詳情可以看demo,註釋還算清晰;對於眼鏡的繪製可以看下我之前的筆記:CALayer系列、CGContextRef、UIBezierPath、文字屬性Attributes
self.motionManager= [[CMMotionManager alloc] init];
//判斷裝置運動感測器是否可用
if(!self.motionManager.isDeviceMotionAvailable){
NSLog(@"手機沒有此功能,換腎吧");
}
//更新速率是100Hz
self.motionManager.deviceMotionUpdateInterval = 0.1;
//開始更新採集資料
//需要時採集資料
//[motionManager startDeviceMotionUpdates];
//實時獲取資料
[self.motionManager startDeviceMotionUpdatesToQueue:[NSOperationQueue mainQueue] withHandler:^(CMDeviceMotion * _Nullable motion, NSError * _Nullable error) {
//獲取X的值
double x = motion.gravity.x;
//手機水平位置測試
//判斷y是否小於0,大於等於-1.0
if(motion.gravity.y < 0.0 && motion.gravity.y >= -1.0){
//設定旋轉
[imageView1 setRotation:80 * motion.gravity.y];
}else if (motion.gravity.z * -1 > 0 && motion.gravity.z * -1 <= 1.0){
[imageView1 setRotation:80 - (80 * motion.gravity.z * -1)];
}
//X、Y方向上的夾角
double rotation = atan2(motion.gravity.x, motion.gravity.y) - M_PI;
NSLog(@"%.2f",rotation);
//圖片始終保持垂直方向
imageView2.transform = CGAffineTransformMakeRotation(rotation);
}];
複製程式碼
三、環境光感處理器
應用:常見的比如說根據環境的亮度去調整螢幕的亮度,在黑暗情況下,手機會自動調暗螢幕亮度,以防刺眼;iPhone 系統相機拍照時光線暗時會自動開啟閃光燈;共享單車在黑暗的情況下掃碼時檢測到特別暗就自動提示開啟閃光燈。
- 利用攝像頭獲取環境光感引數,通過攝像頭採集環境引數,然後在代理方法中輸出,光感越小,環境越暗,然後根據需要做相應的操作。
- 示例中是環境變暗後就自動提示是否開啟閃光燈,開啟之後,環境變亮後會自動提示是否關閉閃光燈。
// 1.獲取硬體裝置
AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
if (device == nil) {
NSLog(@"該換腎了");
return;
}
// 2.建立輸入流
AVCaptureDeviceInput *input = [[AVCaptureDeviceInput alloc]initWithDevice:device error:nil];
// 3.建立裝置輸出流
AVCaptureVideoDataOutput *output = [[AVCaptureVideoDataOutput alloc] init];
[output setSampleBufferDelegate:self queue:dispatch_get_main_queue()];
// AVCaptureSession屬性
_session = [[AVCaptureSession alloc]init];
// 設定為高質量採集率
[_session setSessionPreset:AVCaptureSessionPresetHigh];
// 新增會話輸入和輸出
if ([_session canAddInput:input]) {
[_session addInput:input];
}
if ([_session canAddOutput:output]) {
[_session addOutput:output];
}
// 9.啟動會話
[_session startRunning];
#pragma mark- AVCaptureVideoDataOutputSampleBufferDelegate的方法
- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection {
CFDictionaryRef metadataDict = CMCopyDictionaryOfAttachments(NULL,sampleBuffer, kCMAttachmentMode_ShouldPropagate);
NSDictionary *metadata = [[NSMutableDictionary alloc] initWithDictionary:(__bridge NSDictionary*)metadataDict];
CFRelease(metadataDict);
NSDictionary *exifMetadata = [[metadata objectForKey:(NSString *)kCGImagePropertyExifDictionary] mutableCopy];
float brightnessValue = [[exifMetadata objectForKey:(NSString *)kCGImagePropertyExifBrightnessValue] floatValue];
NSLog(@"環境光感 : %f",brightnessValue);
// 根據brightnessValue的值來開啟和關閉閃光燈
AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
BOOL result = [device hasTorch];// 判斷裝置是否有閃光燈
if ((brightnessValue < 0) && result) {// 開啟閃光燈
if(device.torchMode == AVCaptureTorchModeOn){
return;
}
UIAlertController * alertVC = [UIAlertController alertControllerWithTitle:@"提示" message:@"小主是否要開啟閃光燈?" preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction * openAction = [UIAlertAction actionWithTitle:@"開啟" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
[device lockForConfiguration:nil];
[device setTorchMode: AVCaptureTorchModeOn];//開
[device unlockForConfiguration];
}];
[alertVC addAction:openAction];
UIAlertAction * cancleAction = [UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) {}];
[alertVC addAction:cancleAction];
[self presentViewController:alertVC animated:NO completion:nil];
}else if((brightnessValue > 0) && result) {// 關閉閃光燈
if(device.torchMode == AVCaptureTorchModeOn){
UIAlertController * alertVC = [UIAlertController alertControllerWithTitle:@"提示" message:@"小主是否要關閉閃光燈?" preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction * openAction = [UIAlertAction actionWithTitle:@"關閉" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
[device lockForConfiguration:nil];
[device setTorchMode: AVCaptureTorchModeOff];//關
[device unlockForConfiguration];
}];
[alertVC addAction:openAction];
UIAlertAction * cancleAction = [UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) { }];
[alertVC addAction:cancleAction];
[self presentViewController:alertVC animated:NO completion:nil];
}
}
}
複製程式碼
四、距離感測器
距離感測器: 感應是否有其他物體靠近螢幕,iPhone手機中內建了距離感測器,位置在手機的聽筒附近,當我們在打電話或聽微信語音的時候靠近聽筒,手機的螢幕會自動熄滅,這就靠距離感測器來控制
- 首先開啟距離感測器,然後新增通知UIDeviceProximityStateDidChangeNotification監聽有物品靠近還是離開,從而做出操作,記得最後要關閉距離感測器,有始有終哦。
- 示例中是預設用揚聲器播放音樂,當有物體(比如耳朵)靠近聽筒附近時就切換聽筒播放音樂,物體離開後就繼續用揚聲器播放音樂。
- (void)distanceSensor{
// 開啟距離感測器
[UIDevice currentDevice].proximityMonitoringEnabled = YES;
// 通過通知監聽有物品靠近還是離開
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(proximityStateDidChange:) name:UIDeviceProximityStateDidChangeNotification object:nil];
AVAudioSession *audioSession = [AVAudioSession sharedInstance];
//預設情況下揚聲器播放
[audioSession setCategory:AVAudioSessionCategoryPlayback error:nil];
[audioSession setActive:YES error:nil];
NSString * path = [[NSBundle mainBundle] pathForResource:@"SeeYouAgain" ofType:@"mp3"];
if(path == nil){
return;
}
_play = [[AVPlayer alloc] initWithURL:[NSURL fileURLWithPath:path]];
[_play play];
}
- (void)proximityStateDidChange:(NSNotification *)note
{
if ([UIDevice currentDevice].proximityState) {
NSLog(@"有東西靠近");
//聽筒播放
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayAndRecord error:nil];
} else {
NSLog(@"有物體離開");
//揚聲器播放
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:nil];
}
}
- (void)dealloc{
[_play pause];
_play = nil;
//關閉距離感測器
[UIDevice currentDevice].proximityMonitoringEnabled = NO;
[self removeObserver];
}
複製程式碼
五、磁力計
請看我的上一篇部落格:iOS仿系統指南針
傳࿆送࿆之࿆門࿆ ——> 感測器集錦
溫馨提示:請真機除錯看效果。
- 如果需要跟我交流的話:
※ Github: github.com/wsl2ls
※ 個人部落格:wsl2ls.github.io
※ 微信公眾號:iOS2679114653
※ QQ:1685527540