androidapi-docs-iconCreated with Sketch.applearrowCreated with Sketch.codeCreated with Sketch.download-iconCreated with Sketch.faq-iconCreated with Sketch.githubicon-closeCreated with Sketch.icon_affiliateCreated with Sketch.icon_b2b2cCreated with Sketch.icon_business_useCreated with Sketch.icon_joint_brandingCreated with Sketch.icon_kickbackCreated with Sketch.key-iconCreated with Sketch.next-iconCreated with Sketch.previous-iconCreated with Sketch.settingsCreated with Sketch.shortcutlabs-by-swedensmartphoneCreated with Sketch.

Partners

Flic for iOS: Part 2

Foreword

What is background capabilities and why do I need it?

Quick answer: If you are developing a foreground-only application, like a game, where Flic will only be used when the app is open, then you do not need to implement this part. If you, however, want your iOS application to contunue to use the Flic while the application is no longer in the foreground then you need to implement background capabilities. What this means is that the iOS device will maintain the connection with the Flic and wake up your app to the background whenever an event occurred. This works both when your application is suspended and when it is terminated.

In short this means for the fliclib framework that the app will be woken up to the background during the following scenarios:

  • When a Flic is pressed while connected and a press event needs to be sent
  • When a Flic connects
  • When a Flic disconnects
  • When the bluetooth state changes

Background capabilities on iOS

The iOS platform has some very strict restrictions on what an application is allowed to do when it is not in the foreground. When the application is not in the foreground you are by default not allowed to do any kind of work in the background. Apple provides a few different background execution modes that an application can choose to use provided that the app lives up to the requirements specified for the different background modes. Take a look at Appleā€™s own documentation of App States and Multitasking if you want to learn more about this.

One such background mode affects Bluetooth Low Energy communication which is the protocol used by Flic. This background mode, called bluetooth-central, is the mode that the Fliclib framework needs to use if you are planning to communicate with a Flic while the app is not in the foreground. This will allow your application to be woken up by the system from the suspended state to the background whenever an event has happened on the Flic. At this time the app will be allowed to perform some tasks that are related to the bluetooth event for a short period of time before being suspended again. The following three guidelines below are specified by Apple and has to be followed when using this background execution mode:

  • Apps should be session based and provide an interface that allows the user to decide when to start and stop the delivery of Bluetooth-related events.
  • Upon being woken up, an app has around 10 seconds to complete a task. Ideally, it should complete the task as fast as possible and allow itself to be suspended again. Apps that spend too much time executing in the background can be throttled back by the system or killed.
  • Apps should not use being woken up as an opportunity to perform extraneous tasks that are unrelated to why the app was woken up by the system.

Also take a look at the Being a Responsible Background App in Apple's iOS App Programming Guide.

The requirement that apps needs to be session based simply means that the end user of the App must be prompted with a quick and easy way of entirely turning off all bluetooth communication with that specific App. This is something that you as a developer are responsible to live up to; failing to do so may lead to your app being rejected by Apple. We have made it simple for you by providing two methods on the manager (enable: and disable:) that you can use for this purpose. You can at any time check the status by reading from the readonly property enabled on the manager.

State Preservation and Restoration

If you are reading this then you are probably aware of the fact that iOS has the right to terminate your app at any time without notice; no matter if your app is in the foreground, background or suspended state. By default this means that all tasks that your application is doing will be stopped. This could for example be due to memory limitations on the system or any other reason.

Luckily fliclib will take care of this for you! This means that you will be able to continue communicating with the Flics even after your app gets terminated by the system. Whenever a bluetooth event happens when the app is terminated the app gets launched back into the background again, at which point you are able to go ahead and restore the manager. The manager will be restored back to the last previously known state and all the Flic objects that were associated to that particular manager will be recreated. After that you can simply collect all the Flic objects again and continue to use them normally, but remember that all the rules associated with background execution still applies here. Keep in mind that fliclib does not support the built in State Preservation and Restoration for viewControllers, instead you must use the preservation methods specified by fliclib.

Unfortunately there are a few cases where background execution from state preservation in the terminated state works differently from the regular background execution from suspended state. The app will not be brought back to the background during the following two scenarios:

  • When the bluetooth state changes (this will also cause all pending connections to be canceled)
  • After the app is terminated due to a system reboot

These two cases are particularly important to understand when using the fliclib since they can cause a problem if the user expects it to work when it in fact does not. When it comes to rebooting the iOS device Apple does not provide a way to restart the Bluetooth Low Energy related tasks. This ultimately means that in order for your app to continue the communicating with a Flic after a system reboot it need to be launched into the background again through other means, for example by subscribing to significant-change location service, or alternatively by being launched to the foreground again by the user. As mentioned above, a bluetooth state change will also destruct any bluetooth communication. This means that if the user turns off the bluetooth module on the device while the app is terminated, then it will not start working properly again even if the bluetooth module is powered on again. The same thing applies here as with the reboot, meaning that the app has to be launched by other means. These restrictions are very unfortunate, but for now they are existing and we have to learn to live with them. The best thing that we can recommend (if these issues affect your app) is that you inform your users about this so that they are aware of it.

Please note that these issues are considered as being bugs in the iOS system, and will hopefully be fixed by Apple in the future.

Set up Xcode

The only further configuration needed to Xcode is to add Bluetooth Low Energy as a background mode.

  1. Under Project Settings -> Capabilitier check the Uses Bluetooth LE accessories option in the Background Modes settings Show how to enable BLE

Integrate Flic

We will now go through the steps needed in order to fully integrate Flic in your code. We will do it in a blank Xcode project.

  1. We now need to let fliclib know that we want to use background capabilities. To do that we need to set the backgroundExecution flag when in the manager configuration call that we showed earlier. By setting this flag to YES you will activate the fliclib background capabilities. From this point on you will continue to get Flic events even when your app is not in the foreground.
  2. The second thing that we should talk about is what happens if your application gets terminated. When a Flic related event happens while your app is completely terminated the iOS device will re-launch your app to the background. However, since this can now be considered as a brand new launch of the application, we need to re-initialize fliclib. To do this just initialize the manager as normal when the app boots. When doing this you will after a short time get a callback on the manager delegate, flicManagerDidRestoreState:, where you can collect all Flic buttons again and reset their delegates if needed. If you have your own classes that depend on the button instances then this would also be the safe place to collect the buttons using the knownButtons method. If you have manny buttons and need to distinguish between them then the buttonIdentifier can be used for this purpose.
  3. Unfortunately Apple's Bluetooth Framework has a few issues that can cause our lib to end up in a bad state. This means that fliclib is not on its own guaranteed to work 100% of the time. To avoid this we have a method on the manager class called onLocationChange that you can call at regular intervals. We recommend that you register for Significant-change Location callbacks provided by iOS. This will wake up your app at regular intervals, at which you can call the said method on the manager. Take a look at Apple's documentation of significant location changes if you want to know more about how it works.

    Setup example:

That's it! Your app is now properly set up for background execution.