有没有办法监控用户的iphone移动,如“提高说话”功能?

时间:2013-03-19 02:13:09

标签: ios sensor proximity siri

我想在用户将iphone抬到脸上时收到通知。就像siri一样。有可能吗?

添加更具体的要求: 当用户将手机放在耳边时,我想让屏幕变暗。我知道可以启用接近传感器来实现这一点。但令人讨厌的是,当用户将手指移到传感器上时,屏幕会不时变暗。所以我想知道如何避免这种情况,只有当用户抬起iphone说话时才会使屏幕变暗?

2 个答案:

答案 0 :(得分:7)

请参阅 UIDevice类参考中的Using the Proximity Sensor所以,您:

  • 启用它:

    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
    }
    
  • 然后编写你的选择器:

    - (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阈值是否有意义是有点主观的。您也可以,而不是仅仅查看手机是否大致垂直握持,查看其他加速度计数据(例如,他们是否提升了对象)。似乎有很多方法可以给猫皮肤。

答案 1 :(得分:2)

我知道这是旧的,但我简化了逻辑并在Swift中创建了一个包装类。

You can find it here

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()
}