有没有什么办法像“提高说话”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() }