有没有什么办法像“提高说话”function一样来监控用户的iPhone动作?
我想在用户将iphone抬到脸上时得到通知。 就像siri一样。 可能吗?
添加更具体的要求:当用户将手机靠近他的耳朵时,我想使屏幕变暗。 我知道接近传感器可以实现这一点。 但令人讨厌的是,当用户将手指放在传感器上时,屏幕会不时变暗。 所以我想知道如何避免这种情况下,只有当用户提起iphone说话时只能使屏幕变暗?
请参阅在UIDevice类参考中 使用接近传感器 。 那么你:
-
启用它:
UIDevice *device = [UIDevice currentDevice]; device.proximityMonitoringEnabled = YES;
-
检查是否成功启用; 如果成功则观察
UIDeviceProximityStateDidChangeNotification
通知; 如果没有,您的设备可能无法使用:if (device.proximityMonitoringEnabled) { [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleProximityChange:) name:UIDeviceProximityStateDidChangeNotification object:nil]; } else { // device not capable }
-
并写下您的select器:
- (void)handleProximityChange:(NSNotification *)notification { NSLog(@"%s proximityState=%d", __FUNCTION__, [[UIDevice currentDevice] proximityState]); }
为了检测用户是否把它拿在脸上,我可能会用CMMotionManager
与接近传感器结婚,并看重gravity
属性,看他们是否拿着手机几乎垂直。 所以,定义一些类的属性:
@property (nonatomic, strong) CMMotionManager *motionManager; @property (nonatomic, strong) NSOperationQueue *deviceQueue;
然后,您可以启动CMMotionManager
,查找设备是否处于垂直位置:
self.deviceQueue = [[NSOperationQueue alloc] init]; self.motionManager = [[CMMotionManager alloc] init]; self.motionManager.deviceMotionUpdateInterval = 5.0 / 60.0; UIDevice *device = [UIDevice currentDevice]; [self.motionManager startDeviceMotionUpdatesUsingReferenceFrame:CMAttitudeReferenceFrameXArbitraryZVertical toQueue:self.deviceQueue withHandler:^(CMDeviceMotion *motion, NSError *error) { BOOL vertical = (motion.gravity.z > -0.4 && motion.gravity.z < 0.4 & motion.gravity.y < -0.7); if ((vertical && !device.proximityMonitoringEnabled) || (!vertical && device.proximityMonitoringEnabled)) { device.proximityMonitoringEnabled = vertical; } }];
这些gravity
阈值是否有意义是有点主观的。 你也可以,而不是只是看看电话是否大致垂直举行,看看其他加速度计的数据(例如,他们提出的对象与否)。 似乎有很多方法来剥皮猫。
我知道这是旧的,但我简化了一下逻辑,并在Swift中做了一个包装类。
你可以在这里find它
class DeviceRaisedToEarListener: NSObject { private let deviceQueue = NSOperationQueue() private let motionManager = CMMotionManager() private var vertical: Bool = false private(set) var isRaisedToEar: Bool = false { didSet { if oldValue != self.isRaisedToEar { self.stateChanged?(isRaisedToEar: self.isRaisedToEar) } } } var stateChanged:((isRaisedToEar: Bool)->())? = nil override init() { super.init() self.setupMotionManager() } private func setupMotionManager() { self.motionManager.deviceMotionUpdateInterval = 5.0 / 60.0 let device = UIDevice.currentDevice() // Only listen for proximity changes if the device is held vertically self.motionManager.startDeviceMotionUpdatesUsingReferenceFrame(CMAttitudeReferenceFrame.XArbitraryZVertical, toQueue: self.deviceQueue) { (motion, error) in self.vertical = (motion.gravity.z > -0.4 && motion.gravity.z < 0.4 && motion.gravity.y < -0.7) } } func startListening() { UIDevice.currentDevice().proximityMonitoringEnabled = true NSNotificationCenter.defaultCenter().addObserver(self, selector: "handleProximityChange:", name: UIDeviceProximityStateDidChangeNotification, object: nil) } func stopListening() { UIDevice.currentDevice().proximityMonitoringEnabled = false NSNotificationCenter.defaultCenter().removeObserver(self) } func handleProximityChange(notification: NSNotification) { self.isRaisedToEar = UIDevice.currentDevice().proximityState && self.vertical } deinit { self.stopListening() } } // How to use: private func setupRaiseListener() { self.deviceListener.stateChanged = { [weak self] isRaisedToEar in println("is raised? \(isRaisedToEar)") } self.deviceListener.startListening() }