When running an app in “kiosk mode”, how can we ensure that the user never sees the home screen? Four easy steps.
One interesting use case for iPads is as a kiosk device. For example, it can be used as an interactive exhibit in a museum, installed at a trade fair stand, or at a point of sale (look no farther than the Apple Stores).
In all these scenarios, we want to restrict usage to a pre-defined set of apps, which shall be running indefinitely. Users shall not be allowed to enter the home screen, which would allow launching a different app and tampering with the device settings. This leads us to our first three steps:
- Step 1. Disable the home button.
e.g. by physically covering it with the encasing
- Step 2. Disable the system-wide pinch gesture (iOS 5) for closing the running app.
(Settings: General → Multitasking Gestures: OFF)
- Step 3. Disable the screen’s auto-lock.
(Settings: General → Auto-Lock → Never)
In principle, these simple measures will indeed preclude exiting to the home screen. But what if the kiosk app crashes?
As your apps grow more and more complex, crashes become more likely. We can seldom guarantee outright that the app contains not a single sneaky exception in some most convoluted combination of actions. In addition, because they may run for extended periods of time (think weeks or months), kiosk apps might run into special memory problems that you hadn’t considered during development.
Luckily, it turns out you can implement a crash handler and invoke it when your app comes down crashing, whatever the cause. Think about it: the kiosk app crashes ungently — and yet we are given the chance to do something useful at the very last moment. (I actually find this not just generous but quite amazing from an engineering perspective.)
In our kiosk-app scenario we want to somehow “restart” the app that crashed. iOS allows an app to register for custom URL protocols. Opening a URL that uses this protocol launches the associated app, passing in the full URL.
So our first idea was to register our kiosk app for, say, the “mykioskapp” protocol. Calling
[sharedApp openURL:[NSURL URLWithString:@"mykioskapp://test"]] would then launch our app.
So we tried doing this in the crash handler. And as in any good adventure game, that would have been too obvious and there is one last obstacle to overcome: Launch-by-calling-URL doesn’t work in the crash handler because the app is purportedly still running, so “launching it” has no effect.
“Let me bounce an idea off you…”
So here’s an idea: What if we installed a kind of trampoline that bounces the crashing app back to life?
Armed with this simple idea, the implementation is straightforward:
- Register the “restart” protocol in the Trampoline app.
- In the Kiosk app’s crash handler, launch the restarter:
[sharedApp openURL:[NSURL URLWithString:@"restart://test"]]
- In the Trampoline app (e.g. in -viewDidAppear:), relaunch the crashed app:
[sharedApp openURL:[NSURL URLWithString:@"mykioskapp://test"]]
Voilà! So that’s the final ingredient for keeping users in your app:
- Step 4. Use a Trampoline to resurrect the crashed app.
Of course you can expand on this basic idea, like adding a countdown, an apology, logging the stacktrace, making a light flash red in the control center, etc.
We’d be happy to hear what you do with this!