Swift CoreMotion detects Tap or Knock on the device while in the background

I'm currently in the process of building my first iOS Swift app, with this app I want to take an action while the app is running in the background.

The action must be performed as soon as the user double-clicked on the device.

I have enabled Background Modes: Location Updates in the Features app

And set up the AccelerometerUpdatesToQueue function in the AppDelegate:

let manager = CMMotionManager()

func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
// Override point for customization after application launch.

if manager.accelerometerAvailable {
    manager.accelerometerUpdateInterval = 0.01
    manager.startAccelerometerUpdatesToQueue(NSOperationQueue.mainQueue()) {
        [weak self] (data: CMAccelerometerData!, error: NSError!) in

        println(data.acceleration.z)
    }
}

     return true
}

      

The console prints out the acceleration.z value as expected, but as soon as I hit the home button, the console prints stop.

I have searched the internet for sample code on how to do this and I know it is possible ... because we all know the "Knock Knock to unlock" application, but I cannot find a piece of sample code for Swift.

+3


source to share


2 answers


I got it to work! This is my solution, feel free to suggest improvements :)



class AppDelegate: UIResponder, UIApplicationDelegate {

    var window: UIWindow?

    let manager = CMMotionManager()
    var knocked : Bool = false
    let motionUpdateInterval : Double = 0.05
    var knockReset : Double = 2.0

    func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {

        if manager.deviceMotionAvailable {
            manager.deviceMotionUpdateInterval = motionUpdateInterval // seconds

            manager.startDeviceMotionUpdatesToQueue(NSOperationQueue.mainQueue()) {
                [weak self] (data: CMDeviceMotion!, error: NSError!) in


                if (data.userAcceleration.z < -0.7) || (data.userAcceleration.z > 0.7) { // Check if device is knocked

                    // Check for double knock
                    if self!.knocked == false {
                        // First knock
                        println("First Knock")
                        self!.knocked = true

                    }else{
                        // Second knock
                        println("Double Knocked")
                        self!.knocked = false
                        self!.knockReset = 2.0

                        // Action:
                    }
                }

                // Countdown for reset action (second knock must be within the knockReset limit)
                if (self!.knocked) && (self!.knockReset >= 0.0) {

                    self!.knockReset = self!.knockReset - self!.motionUpdateInterval

                }else if self!.knocked == true {
                    self!.knocked = false
                    self!.knockReset = 2.0
                    println("Reset")
                }

            }
        }

        return true
    }

      

+5


source


Thanks for posting this. This helps me, although I need to figure out how to separate this data from regular traffic data. One suggestion ... use fabs to get the absolute value of userAcceleration.z.

 if (data.userAcceleration.z < -0.7) || (data.userAcceleration.z > 0.7) { // Check if device is knocked

      



becomes

if (fabs(data.userAcceleration.z) > 0.7) { // Check if device is knocked

      

0


source







All Articles