A couple of weeks ago I published my first
Android App Surgery, a technical review of
MySettings from JQSoft. One of my UX suggestions was that they drop the "Exit" menu item. This turned out to be more controversial than I expected and soon dominated the discussion
in the comments.
So, when should your app include an
exit button?
The Short Answer
Never.
The Long Answer
Your app doesn't need an exit button.
It really doesn't. Arguments to the contrary can generally be summarized as:
- Users expect it.
- It's a way to let users say "stop doing everything and stop consuming juice".
Do Users Really Want It?
Let me posit this assertion: no they don't.
Of the apps that ship with the device (Gmail, Contacts, Maps, Gallery, etc.) exactly
none of them include an exit button, and most users are comfortable with that. Nonetheless many developers are adamant, "I added it after users demanded it!".
Fair enough, so why do some users demand an exit button? How do they cope with the bundled apps without an exit button? In my experience what they really want is:
An unambiguous way to guarantee that an app will stop consuming resources (battery, CPU cycles, data transfer, etc).
The Goggles Do Nothing!
Many users perceive that an exit button implements this requirement and ask for it to be added. Developers, looking to please their users, obligingly add one. Shortly thereafter they both fail.
- In most cases the exit button simply calls Activity.finish. This is exactly equivalent to hitting the back button. Exactly. Services keep running and polling keeps happening. Users may think they've killed the app but they haven't, and soon they'll be even more annoyed.
- Exit behavior is now ambiguous. Should your exit button just close the Activity, or should it also stop all associated Services, Receivers, and Alarms? What should back do? What happens if they hit home instead? What happens if your app has a widget? Should the exit button stop that from updating too?
The solution is to make the back button behave as you'd expect the exit button to. Better yet, simply stop consuming resources whenever the app isn't visible.
Users: Consider this. If an app needs an exit button because the back button doesn't properly manage resource use, what do you think the chances are that this exit button will be implemented properly?
Kill Everything When Not in Use
As soon as an app isn't visible its
onStop handler is fired, as soon as it's not the foreground Activity
onPause is triggered. This happens no matter what the circumstance - including hitting the back or home buttons or selecting a notification.
At this point (ideally within onPause) you should behave as though your user has hit
exit.
Location and
Sensor Listeners should be removed, Services
stopped and
unbound, and Intent Receivers
unregistered.
Once your app moves back to the foreground - triggering
onStart and
onResume - you hook everything back up.
"Sure," you're thinking, "but what about apps that need to run in the background?"
Foreground Services and Ongoing Notifications
Some applications, such as turn-by-turn navigation and music players, need to run (and use resources like GPS) while invisible. This is generally achieved using a
foreground Service. It's also the
only reason for creating a foreground Service.
Users should always know if such a Service is running, and be provided with a simple way of unambiguously turning it off when it is. In navigation there's an "exit navigation" menu item. Pausing playback in a music player is enough to kill the playback Service. In both cases
ongoing notifications provide a simple shortcut to the app, where you can easily stop the Service.
As far as the user is concerned, if the app isn't visible and there's no notification icon it's not consuming resources. If there's an icon, it's running in the background and I can click the notification to go turn it off.
Background Services and Polling
Some applications (such as News & Weather) need to occasionally run in the background to get updates. Whenever possible use
inexact repeating Alarms to schedule your updates, and then
kill your service as soon as the update is complete.
This will help with resource use, but is still only half the answer. How can a user demand the app stop using resources completely?
What's the easiest way for me to prevent every app from transferring data?
Settings > Accounts & sync > Background data
Unchecking this should ensure that no app send or receive data while it's not visible. However: This needs to be enforced at an
application level - so if this comes as a surprise to you have a
fix to implement and an update to go push.
Go ahead, I'll wait.
Offer Users Options
Provided the user is cool with background updates in general, you need to let them adjust the frequency - or disable them - for your app. Be conservative by default. If users aren't getting updates as quickly as they want they'll look for a way to increase the frequency.
Be Adaptive
A Twitter discussion from this post resulted in a suggestion that "Android should offer a way to listen for low battery so that an app can be more conservative with it's use of resources." Register a Broadcast Receiver and
thou shalt receive.
You can also monitor for things like
connectivity status and type, so you can disable updates when there's no data connection, or modify the frequency based on the connection type.
In each case it's always good practice to offer these tweaks as user configurable options.
Conclusion
If you build an application that's predictable, configurable, and unambiguous your users won't ask for an exit button. The first time they see an unknown background Service that's been running for an hour, or the GPS icon unexpectedly starts flashing, or the device gets hot while in their pocket they're going to get narky.
Next on my hit list: Splash screens, task killers, and modal "loading" dialogs.
Edit: Added a video version of my position.