iOS开发 传感器(加速计、摇一摇、计步器)
一、传感器
1、什么是传感器
传感器是一种感应\检测周围环境的一种装置, 目前已经广泛应用于智能手机上
传感器的作用
用于感应\检测设备周边的信息
不同类型的传感器, 检测的信息也不一样
iPhone中的下面现象都是由传感器完成的
在地图应用中, 能判断出手机头面向的方向
一关灯, iPhone会自动调整屏幕的亮度
打电话时, 人脸贴近iPhone屏幕时, 屏幕会自动锁屏
… …
二、各种传感器
1、传感器的类型
iPhone内置的传感器有
运动传感器\加速度传感器\加速计(Motion/Accelerometer Sensor)
环境光传感器(Ambient Light Sensor)
距离传感器(Proximity Sensor)
磁力计传感器(Magnetometer Sensor)
内部温度传感器(Internal Temperature Sensor)
湿度传感器(Moisture Sensor)
陀螺仪(Gyroscope)
… …
2、环境光传感器(Ambient Light Sensor)
是iPhone和Mac设备中最为古老的传感器成员
它能够让你在使用 Mac、iPhone、iPad时,眼睛更为舒适
从一个明亮的室外走入相对黑暗的室内后,iOS设备会自动调低亮度,让屏幕显得不再那么光亮刺眼
当你使用iPhone拍照时,闪光灯会在一定条件下自动开启
几乎所有的Mac 都带有背光键盘,当周围光线弱到一定条件时,会自动开启键盘背光
3、距离传感器(Proximity Sensor)
用于检测是否有其他物体靠近设备屏幕
当你打电话或接电话时将电话屏幕贴近耳边,iPhone会自动关闭屏幕 ,好处是
节省电量
防止耳朵或面部不小心触摸屏幕而引发一些不想要的意外操作
题外话:利用距离传感器,能找出很多电视剧的穿帮镜头
4、磁力计传感器(Magnetometer Sensor)
可以感应地球磁场, 获得方向信息, 使位置服务数据更精准
可以用于电子罗盘和导航应用
iPad的Smart Cover盒盖睡眠操作就是基于磁力计传感器
5、内部温度传感器(Internal Temperature Sensor)
从 iPad一代开始,iOS设备都加入了一个内部温度传感器,用于检测内部组件温度,当温度超过系统设定的阈值时,会出现以下提示
6、湿度传感器(Moisture Sensor)
湿度传感器跟其他基于微电子的传感器不同,是一个简单的物理传感器
简单来说,湿度传感器就是一张遇水变红的试纸
Apple的维修人员就是通过检测试纸是否变红,来判断设备是否进水
(设备进水不在保修范围之内)
7、陀螺仪(Gyroscope)
陀螺仪是随着iPhone4的上市首次出现在iOS设备上的传感器
陀螺仪的原理是检测设备在X、Y、Z轴上所旋转的角速度
陀螺仪在赛车类游戏中有重大作用:
模拟汽车驾驶时方向盘旋转的动作
使得这类游戏的操控体验更为真实
8、加速计传感器(Motion/Accelerometer Sensor)
最早出现在iOS设备上的传感器之一
加速计用于检测设备在X、Y、Z轴上的加速度 (哪个方向有力的作用)
加速计可以用于检测设备的摇晃,经典应用场景
摇一摇
计步器
小结:
三、距离传感器的使用
默认情况下,每一个应用程序距离传感器都是关闭状态
如果需要,需要通过代码将其打开
// 开启距离感应功能 [UIDevice currentDevice].proximityMonitoringEnabled = YES; // 监听距离感应的通知 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(proximityChange:) name:UIDeviceProximityStateDidChangeNotification object:nil]; - (void)proximityChange:(NSNotification *)notification { if ([UIDevice currentDevice].proximityState == YES) { NSLog(@"某个物体靠近了设备屏幕"); // 屏幕会自动锁住 } else { NSLog(@"某个物体远离了设备屏幕"); // 屏幕会自动解锁 } }
四、加速计
1、加速计原理
检测设备在X、Y、Z轴上的加速度 (哪个方向有力的作用,哪个方向运动了)
根据加速度数值,就可以判断出在各个方向上的作用力度
2、UIAccelerometer
1)加速计程序的开发
在iOS4以前:使用UIAccelerometer,用法非常简单(到了iOS5就已经过期)
从iOS4开始:CoreMotion.framework
虽然UIAccelerometer已经过期,但由于其用法极其简单,很多程序里面都还有残留
2)UIAccelerometer的使用步骤
获得单例对象 UIAccelerometer *accelerometer = [UIAccelerometer sharedAccelerometer]; 设置代理 accelerometer.delegate = self; 设置采样间隔 accelerometer.updateInterval = 1.0/30.0; // 1秒钟采样30次 实现代理方法 - (void)accelerometer:(UIAccelerometer *)accelerometer didAccelerate:(UIAcceleration *)acceleration // acceleration中的x、y、z三个属性分别代表每个轴上的加速度
3、Core Motion
1)Core Motion
在iOS4之前,加速度计由UIAccelerometer类来负责采集数据
随着iPhone4的推出加速度计全面升级,并引入了陀螺仪与Motion(运动)相关的编程成为重头戏苹果特地在iOS4中增加了专门处理Motion的框架-CoreMotion.framework
Core Motion不仅能够提供实时的加速度值和旋转速度值,更重要的是,苹果在其中集成了很多牛逼的算法
2)Core Motion获取数据的两种方式
获取加速计信息
push
实时采集所有数据(采集频率高)
创建运动管理者对象 CMMotionManager *mgr = [[CMMotionManager alloc] init]; 判断加速计是否可用(最好判断) if (mgr.isAccelerometerAvailable) { // 加速计可用 } 设置采样间隔 mgr.accelerometerUpdateInterval = 1.0/30.0; // 1秒钟采样30次 开始采样(采样到数据就会调用handler,handler会在queue中执行) - (void)startAccelerometerUpdatesToQueue:(NSOperationQueue *)queue withHandler:(CMAccelerometerHandler)handler;
pull
在有需要的时候,再主动去采集数据
创建运动管理者对象 CMMotionManager *mgr = [[CMMotionManager alloc] init]; 判断加速计是否可用(最好判断) if (mgr.isAccelerometerAvailable) { // 加速计可用 } 开始采样 - (void)startAccelerometerUpdates; 在需要的时候采集加速度数据 CMAcceleration acc = mgr.accelerometerData.acceleration; NSLog(@"%f, %f, %f", acc.x, acc.y, acc.z);
获取陀螺仪信息
- (void)pullGyro { // pull方式获取陀螺仪信息 // 1.判断陀螺仪是否可用 if (!self.mgr.isGyroAvailable) { NSLog(@"设备小于iPhone4,或者陀螺仪损坏"); return; } // 2.开始采样 [self.mgr startGyroUpdates]; } - (void)pushGyro { // push方式获取陀螺仪信息 // 1.判断陀螺仪是否可用 if (!self.mgr.isGyroAvailable) { NSLog(@"设备小于iPhone4,或者陀螺仪损坏"); return; } // 2.设置采样 self.mgr.gyroUpdateInterval = 1.0 / 10; // 3.开始采样 [self.mgr startGyroUpdatesToQueue:[NSOperationQueue mainQueue] withHandler:^(CMGyroData * _Nullable gyroData, NSError * _Nullable error) { if (error) { NSLog(@"%@", error); return; } // 获取陀螺仪的信息 CMRotationRate rotationRate = gyroData.rotationRate; NSLog(@"x:%f y:%f z:%f", rotationRate.x, rotationRate.y, rotationRate.z); }]; }
4、Core Motion框架结构示意图
五、摇一摇
监控摇一摇的方法
方法1:通过分析加速计数据来判断是否进行了摇一摇操作(比较复杂)
方法2:iOS自带的Shake监控API(非常简单)
判断摇一摇的步骤:实现3个摇一摇监听方法
- (void)motionBegan:(UIEventSubtype)motion withEvent:(UIEvent *)event /** 检测到摇动 */ - (void)motionCancelled:(UIEventSubtype)motion withEvent:(UIEvent *)event /** 摇动取消(被中断) */ - (void)motionEnded:(UIEventSubtype)motion withEvent:(UIEvent *)event /** 摇动结束 */
六、计步器
计步器是从iOS7开始引入(内部原理还是加速计)
iOS7 : CMStepCounter –> iOS8过期
// 1.判断计步器是否可用 if (![CMStepCounter isStepCountingAvailable]) { NSLog(@"计步器不可用"); return; } // 2.开始计步 // 2.1.创建计步器 CMStepCounter *stepCounter = [[CMStepCounter alloc] init]; // 2.2.开始计步 // updateOn : 用户走了多少步之后,更新block NSOperationQueue *queue = [[NSOperationQueue alloc] init]; [stepCounter startStepCountingUpdatesToQueue:queue updateOn:5 withHandler:^(NSInteger numberOfSteps, NSDate * _Nonnull timestamp, NSError * _Nullable error) { if (error) return; // 1.GCD方式 // dispatch_sync(dispatch_get_main_queue(), ^{ // self.stepLabel.text = [NSString stringWithFormat:@"您一共走了%ld步", numberOfSteps]; // }); NSString *stepString = [NSString stringWithFormat:@"您一共走了%ld步", numberOfSteps]; [self.stepLabel performSelectorOnMainThread:@selector(setText:) withObject:stepString waitUntilDone:YES]; }];
iOS8用法
/** 计步器对象 */ @property (nonatomic, strong) CMPedometer *pedometer; #pragma mark - 懒加载代码 - (CMPedometer *)pedometer { if (_pedometer == nil) { self.pedometer = [[CMPedometer alloc] init]; } return _pedometer; } // 1.判断计步器是否可用 if (![CMPedometer isStepCountingAvailable]) { return; } // 2.开始计步 // 2.1.创建计步对象 // 2.2.开始计步 // FromDate : 从什么时间开始计步 NSDate *date = [NSDate date]; [self.pedometer startPedometerUpdatesFromDate:date withHandler:^(CMPedometerData * _Nullable pedometerData, NSError * _Nullable error) { if (error) { NSLog(@"%@", error); return; } NSLog(@"您一共走了%@步", pedometerData.numberOfSteps); }];
计算前7天内的 某段时间一共走了多少步
NSDateFormatter *fmt = [[NSDateFormatter alloc] init]; fmt.dateFormat = @"yyyy-MM-dd"; NSDate *fromDate = [fmt dateFromString:@"2015-9-26"]; NSDate *toDate = [fmt dateFromString:@"2015-9-28"]; [self.pedometer queryPedometerDataFromDate:fromDate toDate:toDate withHandler:^(CMPedometerData * _Nullable pedometerData, NSError * _Nullable error) { NSLog(@"%@", pedometerData.numberOfSteps); }];