| Scott Main | 50e990c | 2012-06-21 17:14:39 -0700 | [diff] [blame] | 1 | page.title=Designing for Seamlessness |
| Scott Main | 6afeb0e | 2013-04-16 21:05:51 -0700 | [diff] [blame] | 2 | excludeFromSuggestions=true |
| Scott Main | 50e990c | 2012-06-21 17:14:39 -0700 | [diff] [blame] | 3 | @jd:body |
| 4 | |
| 5 | <div id="qv-wrapper"> |
| 6 | <div id="qv"> |
| 7 | |
| 8 | <h2>In this document</h2> |
| 9 | <ol> |
| 10 | <li><a href="#drop">Don't Drop Data</a></li> |
| 11 | <li><a href="#expose">Don't Expose Raw Data</a></li> |
| 12 | <li><a href="#interrupt">Don't Interrupt the User</a></li> |
| 13 | <li><a href="#threads">Got a Lot to Do? Do it in a Thread</a></li> |
| 14 | <li><a href="#multiple-activities">Don't Overload a Single Activity Screen</a></li> |
| 15 | <li><a href="#themes">Extend System Themes</a></li> |
| 16 | <li><a href="#flexui">Design Your UI to Work with Multiple Screen Resolutions</a></li> |
| 17 | <li><a href="#network">Assume the Network is Slow</a></li> |
| 18 | <li><a href="#keyboard">Don't Assume Touchscreen or Keyboard</a></li> |
| 19 | <li><a href="#battery">Do Conserve the Device Battery</a></li> |
| 20 | </ol> |
| 21 | |
| 22 | </div> |
| 23 | </div> |
| 24 | |
| 25 | <p>Even if your application is fast and responsive, certain design decisions can |
| 26 | still cause problems for users — because of unplanned interactions with |
| 27 | other applications or dialogs, inadvertent loss of data, unintended blocking, |
| 28 | and so on. To avoid these problems, it helps to understand the context in which |
| 29 | your applications run and the system interactions that can affect your |
| 30 | application. In short, you should strive to develop an application that |
| 31 | interacts seamlessly with the system and with other applications. </p> |
| 32 | |
| 33 | <p>A common seamlessness problem is when an application's background process |
| 34 | — for example, a service or broadcast receiver — pops up a dialog in |
| 35 | response to some event. This may seem like harmless behavior, especially when |
| 36 | you are building and testing your application in isolation, on the emulator. |
| 37 | However, when your application is run on an actual device, your application may |
| 38 | not have user focus at the time your background process displays the dialog. So |
| 39 | it could end up that your application would display it's dialog behind the |
| 40 | active application, or it could take focus from the current application and |
| 41 | display the dialog in front of whatever the user was doing (such as dialing a |
| 42 | phone call, for example). That behavior would not work for your application or |
| 43 | for the user. </p> |
| 44 | |
| 45 | <p>To avoid these problems, your application should use the proper system |
| 46 | facility for notifying the user — the |
| 47 | {@link android.app.Notification Notification} classes. Using |
| 48 | notifications, your application can signal the user that an event has |
| 49 | taken place, by displaying an icon in the status bar rather than taking |
| 50 | focus and interrupting the user.</p> |
| 51 | |
| 52 | <p>Another example of a seamlessness problem is when an activity inadvertently |
| 53 | loses state or user data because it doesn't correctly implement the onPause() |
| 54 | and other lifecycle methods. Or, if your application exposes data intended to be |
| 55 | used by other applications, you should expose it via a ContentProvider, rather |
| 56 | than (for example) doing so through a world-readable raw file or database.</p> |
| 57 | |
| 58 | <p>What those examples have in common is that they involve cooperating nicely |
| 59 | with the system and other applications. The Android system is designed to treat |
| 60 | applications as a sort of federation of loosely-coupled components, rather than |
| 61 | chunks of black-box code. This allows you as the developer to view the entire |
| 62 | system as just an even-larger federation of these components. This benefits you |
| 63 | by allowing you to integrate cleanly and seamlessly with other applications, and |
| 64 | so you should design your own code to return the favor.</p> |
| 65 | |
| 66 | <p>This document discusses common seamlessness problems and how to avoid them.</p> |
| 67 | |
| 68 | <h2 id="drop">Don't Drop Data</h2> |
| 69 | |
| 70 | <p>Always keep in mind that Android is a mobile platform. It may seem obvious to |
| 71 | say it, but it's important to remember that another Activity (such as the |
| 72 | "Incoming Phone Call" app) can pop up over your own Activity at any moment. |
| 73 | This will fire the onSaveInstanceState() and onPause() methods, and will likely result in |
| 74 | your application being killed.</p> |
| 75 | |
| 76 | <p>If the user was editing data in your application when the other Activity |
| 77 | appeared, your application will likely lose that data when your application is |
| 78 | killed. Unless, of course, you save the work in progress first. The "Android |
| 79 | Way" is to do just that: Android applications that accept or edit input should |
| 80 | override the onSaveInstanceState() method and save their state in some appropriate |
| 81 | fashion. When the user revisits the application, she should be able to |
| 82 | retrieve her data.</p> |
| 83 | |
| 84 | <p>A classic example of a good use of this behavior is a mail application. If the |
| 85 | user was composing an email when another Activity started up, the application |
| 86 | should save the in-process email as a draft.</p> |
| 87 | |
| 88 | <h2 id="expose">Don't Expose Raw Data</h2> |
| 89 | |
| 90 | <p>If you wouldn't walk down the street in your underwear, neither should your |
| 91 | data. While it's possible to expose certain kinds of application to the world |
| 92 | to read, this is usually not the best idea. Exposing raw data requires other |
| 93 | applications to understand your data format; if you change that format, you'll |
| 94 | break any other applications that aren't similarly updated.</p> |
| 95 | |
| 96 | <p>The "Android Way" is to create a ContentProvider to expose your data to other |
| 97 | applications via a clean, well-thought-out, and maintainable API. Using a |
| 98 | ContentProvider is much like inserting a Java language interface to split up and |
| 99 | componentize two tightly-coupled pieces of code. This means you'll be able to |
| 100 | modify the internal format of your data without changing the interface exposed |
| 101 | by the ContentProvider, and this without affecting other applications.</p> |
| 102 | |
| 103 | <h2 id="interrupt">Don't Interrupt the User</h2> |
| 104 | |
| 105 | <p>If the user is running an application (such as the Phone application during a |
| 106 | call) it's a pretty safe bet he did it on purpose. That's why you should avoid |
| 107 | spawning activities except in direct response to user input from the current |
| 108 | Activity.</p> |
| 109 | |
| 110 | <p>That is, don't call startActivity() from BroadcastReceivers or Services running in |
| 111 | the background. Doing so will interrupt whatever application is currently |
| 112 | running, and result in an annoyed user. Perhaps even worse, your Activity may |
| 113 | become a "keystroke bandit" and receive some of the input the user was in the |
| 114 | middle of providing to the previous Activity. Depending on what your |
| 115 | application does, this could be bad news.</p> |
| 116 | |
| 117 | <p>Instead of spawning Activity UIs directly from the background, you should |
| 118 | instead use the NotificationManager to set Notifications. These will appear in |
| 119 | the status bar, and the user can then click on them at his leisure, to see |
| 120 | what your application has to show him.</p> |
| 121 | |
| 122 | <p>(Note that all this doesn't apply to cases where your own Activity is already |
| 123 | in the foreground: in that case, the user expects to see your next Activity in |
| 124 | response to input.)</p> |
| 125 | |
| 126 | <h2 id="threads">Got a Lot to Do? Do it in a Thread</h2> |
| 127 | |
| 128 | <p>If your application needs to perform some expensive or long-running |
| 129 | computation, you should probably move it to a thread. This will prevent the |
| 130 | dreaded "Application Not Responding" dialog from being displayed to the user, |
| 131 | with the ultimate result being the fiery demise of your application.</p> |
| 132 | |
| 133 | <p>By default, all code in an Activity as well as all its Views run in the same |
| 134 | thread. This is the same thread that also handles UI events. For example, when |
| 135 | the user presses a key, a key-down event is added to the Activity's main |
| 136 | thread's queue. The event handler system needs to dequeue and handle that |
| 137 | event quickly; if it doesn't, the system concludes after a few seconds that |
| 138 | the application is hung and offers to kill it for the user.</p> |
| 139 | |
| 140 | <p>If you have long-running code, running it inline in your Activity will run it |
| 141 | on the event handler thread, effectively blocking the event handler. This will |
| 142 | delay input processing, and result in the ANR dialogs. To avoid this, move |
| 143 | your computations to a thread. This <a |
| 144 | href="responsiveness.html">Design for Responsiveness</a> document |
| 145 | discusses how to do that..</p> |
| 146 | |
| 147 | <h2 id="multiple-activities">Don't Overload a Single Activity Screen</h2> |
| 148 | |
| 149 | <p>Any application worth using will probably have several different screens. |
| 150 | When designing the screens of your UI, be sure to make use of multiple Activity |
| 151 | object instances.</p> |
| 152 | |
| 153 | <p>Depending on your development background, you may interpret an Activity as |
| 154 | similar to something like a Java Applet, in that it is the entry point for |
| 155 | your application. However, that's not quite accurate: where an Applet subclass |
| 156 | is the single entry point for a Java Applet, an Activity should be thought of |
| 157 | as one of potentially several entry points to your application. The only |
| 158 | difference between your "main" Activity and any others you might have is that |
| 159 | the "main" one just happens to be the only one that expressed an interest in |
| 160 | the "android.intent.action.MAIN" action in your AndroidManifest..xml file.</p> |
| 161 | |
| 162 | <p>So, when designing your application, think of your application as a federation |
| 163 | of Activity objects. This will make your code a lot more maintainable in the long |
| 164 | run, and as a nice side effect also plays nicely with Android's application |
| 165 | history and "backstack" model.</p> |
| 166 | |
| 167 | <h2 id="themes">Extend System Themes</h2> |
| 168 | |
| 169 | <p>When it comes to the look-and-feel of the user interface, it's important to |
| 170 | blend in nicely. Users are jarred by applications which contrast with the user |
| 171 | interface they've come to expect. When designing your UIs, you should try and |
| 172 | avoid rolling your own as much as possible. Instead, use a Theme. You |
| 173 | can override or extend those parts of the theme that you need to, but at least |
| 174 | you're starting from the same UI base as all the other applications. For all |
| 175 | the details, read <a href="{@docRoot}guide/topics/ui/themes.html">Styles and Themes</a>.</p> |
| 176 | |
| 177 | <h2 id="flexui">Design Your UI to Work with Multiple Screen Resolutions</h2> |
| 178 | |
| 179 | <p>Different Android-powered devices will support different screen resolutions. |
| 180 | Some will even be able to change resolutions on the fly, such as by switching |
| 181 | to landscape mode. It's important to make sure your layouts and drawables |
| 182 | are flexible enough to display properly on a variety of device screens.</p> |
| 183 | |
| 184 | <p>Fortunately, this is very easy to do. In brief, what you must do is |
| 185 | provide different versions of your artwork (if you use any) for the key |
| 186 | resolutions, and then design your layout to accommodate various dimensions. |
| 187 | (For example, avoid using hard-coded positions and instead use relative |
| 188 | layouts.) If you do that much, the system handles the rest, and your |
| 189 | application looks great on any device.</p> |
| 190 | |
| 191 | <h2 id="network">Assume the Network is Slow</h2> |
| 192 | |
| 193 | <p>Android devices will come with a variety of network-connectivity options. All |
| 194 | will have some data-access provision, though some will be faster than others. |
| 195 | The lowest common denominator, however, is GPRS, the non-3G data service for |
| 196 | GSM networks. Even 3G-capable devices will spend lots of time on non-3G |
| 197 | networks, so slow networks will remain a reality for quite a long time to |
| 198 | come.</p> |
| 199 | |
| 200 | <p>That's why you should always code your applications to minimize network |
| 201 | accesses and bandwidth. You can't assume the network is fast, so you should |
| 202 | always plan for it to be slow. If your users happen to be on faster networks, |
| 203 | then that's great — their experience will only improve. You want to avoid the |
| 204 | inverse case though: applications that are usable some of the time, but |
| 205 | frustratingly slow the rest based on where the user is at any given moment are |
| 206 | likely to be unpopular.</p> |
| 207 | |
| 208 | <p>One potential gotcha here is that it's very easy to fall into this trap if |
| 209 | you're using the emulator, since the emulator uses your desktop computer's |
| 210 | network connection. That's almost guaranteed to be much faster than a cell |
| 211 | network, so you'll want to change the settings on the emulator that simulate |
| 212 | slower network speeds. You can do this in Eclipse, in the "Emulator Settings" |
| 213 | tab of your launch configuration or via a <a |
| 214 | href="{@docRoot}tools/help/emulator.html#netspeed">command-line |
| 215 | option</a> when starting the emulator.</p> |
| 216 | |
| 217 | <h2 id="keyboard">Don't Assume Touchscreen or Keyboard</h2> |
| 218 | |
| 219 | <p> |
| 220 | Android will support a variety of handset form-factors. That's a fancy way of |
| 221 | saying that some Android devices will have full "QWERTY" keyboards, while |
| 222 | others will have 40-key, 12-key, or even other key configurations. Similarly, |
| 223 | some devices will have touch-screens, but many won't. |
| 224 | </p><p> |
| 225 | When building your applications, keep that in mind. Don't make assumptions |
| 226 | about specific keyboard layouts -- unless, of course, you're really interested |
| 227 | in restricting your application so that it can only be used on those devices. |
| 228 | </p> |
| 229 | |
| 230 | <h2 id="battery">Do Conserve the Device Battery</h2> |
| 231 | <p> |
| 232 | A mobile device isn't very mobile if it's constantly plugged into the |
| 233 | wall. Mobile devices are battery-powered, and the longer we can make that |
| 234 | battery last on a charge, the happier everyone is — especially the user. |
| 235 | Two of the biggest consumers of battery power are the processor, and the |
| 236 | radio; that's why it's important to write your applications to do as little |
| 237 | work as possible, and use the network as infrequently as possible. |
| 238 | </p><p> |
| 239 | Minimizing the amount of processor time your application uses really comes |
| 240 | down to <a href="performance.html">writing efficient |
| 241 | code</a>. To minimize the power drain from using the radio, be sure to handle |
| 242 | error conditions gracefully, and only fetch what you need. For example, don't |
| 243 | constantly retry a network operation if one failed. If it failed once, it's |
| 244 | likely because the user has no reception, so it's probably going to fail again |
| 245 | if you try right away; all you'll do is waste battery power. |
| 246 | </p><p> |
| 247 | Users are pretty smart: if your program is power-hungry, you can count on |
| 248 | them noticing. The only thing you can be sure of at that point is that your |
| 249 | program won't stay installed very long. |
| 250 | </p> |