iosibeacon

Beacon range in background


I'm developing an app which connects to the beacons. I'm able to run the app and also to detect beacons when app is in background (I send local notifications in the didRangeBeacons method and I receive them). I need to run a piece of code in the background when a beacon is detected. How can I do? I tried to write my Alamofire call exactly after sending the local notification, but nothing happens. Some suggestions?


Solution

  • When an app is in the background and it gets a didRangeBeacons callback, it only gets 5 seconds to run by the operating system before it is suspended. This will close any web service connections that are open at that time. You can extend this background running time from 5 seconds to 180 seconds upon request. Below is an example in Swift 3 that shows how to do that.

    var threadStarted = false
    var backgroundTask: UIBackgroundTaskIdentifier = UIBackgroundTaskInvalid
    
    func extendBackgroundRunningTime() {
      if (self.backgroundTask != UIBackgroundTaskInvalid) {
        // if we are in here, that means the background task is already running.
        // don't restart it.
        return
      }
    
      print("Attempting to extend background running time")
    
      self.backgroundTask = UIApplication.shared.beginBackgroundTask(withName: "DummyTask", expirationHandler: {
        UIApplication.shared.endBackgroundTask(self.backgroundTask)
        self.backgroundTask = UIBackgroundTaskInvalid
      })
    
      if threadStarted {
        print("Background task thread already started.")
      }
      else {
        threadStarted = true
        DispatchQueue.global(priority: DispatchQueue.GlobalQueuePriority.default).async {
          while (true) {
            // A dummy tasks must be running otherwise iOS suspends immediately
            Thread.sleep(forTimeInterval: 1);
          }
        }
      }
    }
    

    By adding code like this, it is much more likely that your web service call will complete before iOS suspends your app.

    You can call the extendBackgroundRunningTime() from your didRangeBeacons or didEnterRegion methods.