Android App Mistakes: Avoiding the Anti-Patterns

7,351 views

Published on

There are many mistakes that developers and OEMs can make that affect not only users, but other developers as well. This presentation reviews these anti-patterns and the ways to address them. Developed from the "Code Pollution" blog post series on AndroidGuys.com. From a May 2010 presentation in Lund, Sweden.

Published in: Technology
2 Comments
22 Likes
Statistics
Notes
No Downloads
Views
Total views
7,556
On SlideShare
0
From Embeds
0
Number of Embeds
4
Actions
Shares
0
Downloads
289
Comments
2
Likes
22
Embeds 0
No embeds

No notes for slide

Android App Mistakes: Avoiding the Anti-Patterns

  1. 1. Android App Mistakes: Avoiding the Anti-Patterns by Mark Murphy, CommonsWare
  2. 2. Introduction • Anti-Patterns • Code pollution • Fatal assumptions • Goal: help you avoid these anti-patterns • Developers • OEMs
  3. 3. Everlasting Services • What is the Anti-Pattern? • Trying to have a service “always running”, instead of periodically running or running when your activity is on-screen • startService() without a stopService() or stopSelf()
  4. 4. Everlasting Services • Why Is This Important? • Android kills off old services to reclaim RAM • Users kill off services they do not understand • Task killer • Settings > Applications > Services
  5. 5. Everlasting Services • What is the Right Answer? • Rare use cases for everlasting services • VOIP app • Otherwise, aim to keep the service out of RAM when not actively doing work • AlarmManager
  6. 6. Background Control • What is the Anti-Pattern? • Implementing a polling mechanism without any sort of user control • Implementing an everlasting service without user option to not have it
  7. 7. Background Control • Why Is This Important? • Users may blame your app • Battery drain • RAM consumption • Users may kill or uninstall your app to regain control
  8. 8. Background Control • What is the Right Answer? • If polling, let user choose period (including “never”) • If everlasting service, let user say “no” • VOIP app...but only for outgoing calls
  9. 9. Background Becomes Foreground • What is the Anti-Pattern? • Doing significant processing in background callbacks • onReceive() • onCreate() / onStart() / onDestroy()
  10. 10. Background Becomes Foreground • Why Is This Important? • Normally, background processing is CPU- capped at ~10% • During those callbacks, priority changes to normal foreground priority • May impact real foreground (e.g., game)
  11. 11. Background Becomes Foreground • What is the Right Answer? • BroadcastReceiver delegates to IntentService • IntentService does everything in onHandleIntent() • Or other means of using background threads instead of work in callbacks
  12. 12. Boot-Time Services • What is the Anti-Pattern? • Configuring a BroadcastReceiver to respond to the BOOT_COMPLETED broadcast Intent
  13. 13. Boot-Time Services • Why Is This Important? • Too many boot-time services slows the boot down for user • Lots of process churn • May cause those broadcasts to be delayed for everyone
  14. 14. Boot-Time Services • What is the Right Answer? • Use it only if truly necessary (e.g., restore AlarmManager alarms) • Do not do significant work right away • Wait for later trigger or user interaction
  15. 15. Using Multiple Processes • What is the Anti-Pattern? • Forcing Android to use more than one process for your application • Remote services for internal use • Process attributes in manifest • Forking processes from JVM
  16. 16. Using Multiple Processes • Why Is This Important? • Each process takes up a significant chunk of RAM • More active processes = more likely other things get kicked out of RAM • If user feels RAM is over-utilized, more likely to come after you with task killer
  17. 17. Using Multiple Processes • What is the Right Answer? • Just avoid multiple processes! • Remote services/AIDL are for third-party use, not your own • Be careful on forking system processes (e.g., interpreters, built-in binaries)
  18. 18. Use Mutable Statics • What is the Anti-Pattern? • Using static data members for more than final “constant” values • Caching • Cross-component communication
  19. 19. Use Mutable Statics • Why Is This Important? • Android can close components to reclaim memory...if memory can be GC’d • Static references inhibit GC • Static references to things that hold onto components defeats Android’s intentions
  20. 20. Use Mutable Statics • What is the Right Answer? • Avoid mutable statics where possible • Be very careful with the ones you need • Ensure they do not hold references (direct or indirect) to activities, services, etc.
  21. 21. Leak Like a Sieve • What is the Anti-Pattern? • Register...and do not unregister • Acquire...and do not release • Assign to static...and not null out reference later
  22. 22. Leak Like a Sieve • Why Is This Important? • Once again, the issue is GC • Registered listeners, etc. are held in static references inside of Android • Must get those released • Free up RAM • Stop events from continuing to fire
  23. 23. Leak Like a Sieve • What is the Right Answer? • Aim to use lifecycle pairs • Register in onCreate(), release in onDestroy(), etc. • Use onDestroy() as “backstop”, releasing everything registered or acquired • Exception handling and finally {} block
  24. 24. Force Wrong UI • What is the Anti-Pattern? • Adding an Exit menu choice or button • Trying to create a blocking modal dialog • Otherwise attempting to pretend Android is some other OS
  25. 25. Force Wrong UI • Why Is This Important? • Android has a style all its own • Different, not necessarily bad • Breaking that style will cause some user confusion...or developer confusion when users do not behave as expected
  26. 26. Force Wrong UI • What is the Right Answer? • Use Android navigation and APIs naturally, not trying to emulate some other model • Navigation: pretend you are writing a Web application • Flow is much like a Web browser
  27. 27. Ignore Screen Sizes • What is the Anti-Pattern? • Focusing on one screen size • Focusing on customizing for individual screen sizes • Instead of coming up with layouts, etc. that work across sizes
  28. 28. Ignore Screen Sizes • Why Is This Important? • Your app may not work well on existing devices • Your app may not work well on future devices • Many new screen sizes are coming
  29. 29. Ignore Screen Sizes • What is the Right Answer? • Write to be resolution-independent • RelativeLayout • Don’t use pixel dimensions • Test on a wide range of layouts to confirm your independence actually works
  30. 30. Assume Touch • What is the Anti-Pattern? • Writing an application that assumes the existence of a touchscreen and does not mandate it via the manifest • Not testing an application via the D-pad and keyboard alone
  31. 31. Assume Touch • Why Is This Important? • Not all Android devices will be touchscreens • Television set-top boxes • Low-end smartphones / high-end “feature phones”
  32. 32. Assume Touch • What is the Right Answer? • If your app only makes sense with touchscreen, require it via the manifest • If your app could be used by D-pad or equivalent, test it out, make sure it makes sense • “Tab order” issues
  33. 33. Make Busy App Widgets • What is the Anti-Pattern? • Trying to update an app widget every second...from your code • Rolling your own timer • Faking an animation
  34. 34. Make Busy App Widgets • Why Is This Important? • App widgets cross the process boundary on every update • Your code -> home screen process • IPC is expensive in terms of CPU time • Hence, expensive for battery
  35. 35. Make Busy App Widgets • What is the Right Answer? • App widgets are largely static or driven by user input • Update the app widgets on user demand or slow timers • 30 minute minimum for updatePeriodMillis
  36. 36. Assume Unlimited Data • What is the Anti-Pattern? • Assuming users have unlimited SMS plans • Using SMS for chatty app protocols • Assuming users have unlimited data plans • Constantly refreshing or downloading data
  37. 37. Assume Unlimited Data • Why Is This Important? • “Unlimited” SMS or data only available in some markets to some users • Everybody else pays by the message or MB • Even “unlimited” usually comes with caps • Net: costs users money or capability
  38. 38. Assume Unlimited Data • What is the Right Answer? • Allow user controls over chattiness or refresh periods • Pay attention to WiFi vs. mobile data connections • WiFi is less prone to costing users money
  39. 39. Reach Past the SDK • What is the Anti-Pattern? • Using reflection to access public classes, etc. that are not part of the SDK • Accessing undocumented content providers • Assuming existence of certain binaries
  40. 40. Reach Past the SDK • Why Is This Important? • Your app may break on today’s or tomorrow’s phones • Broken apps = unhappy users • Will they think ill of you...or Android? • Weakens arguments against OEMs
  41. 41. Reach Past the SDK • What is the Right Answer? • Stick to the SDK • Work with the core Android team to figure out how to open more up • Coordinate SDK-hack wrappers • Strength in numbers
  42. 42. Anti-Patterns, OEM Style • Plenty of anti-patterns for creating Android devices • Impacts ability of developers to deliver quality apps for your device • Impacts user satisfaction with apps, your device, and Android overall
  43. 43. Breaking the SDK • What is the Anti-Pattern? • Changing Android and breaking API • Changing Android and changing behavior of documented resources • Inadequately setting expectations • Example: contacts and Facebook
  44. 44. Breaking the SDK • Why Is This Important? • Broken SDK means some apps break when run on your device • Until developers spend extra effort trying to work around your errors • Broken expectations cause angst for users and developers alike
  45. 45. Breaking the SDK • What is the Right Answer? • Test, test, test! • CTS is nowhere near sufficient • Developer device seeding program • Direct • Through services (DeviceAnywhere)
  46. 46. Hamper Developers • What is the Anti-Pattern? • Break access to DDMS • Block non-Market app installs • Innovate without adequate explanation • Example: CDMA on Android 1.5
  47. 47. Hamper Developers • Why Is This Important? • Users buy these devices for the apps • Important for apps to work well on your device • Users will think poorly of your device • Users will think poorly of Android
  48. 48. Hamper Developers • What is the Right Answer? • End users are not your only user base you need to think about • Have developer programs for communication and support • Don’t screw up the firmware too bad
  49. 49. Block Replacement Firmware • What is the Anti-Pattern? • Using cryptographic signing to prevent people from replacing firmware
  50. 50. Block Replacement Firmware • Why Is This Important? • Segment of your user base values this • Can result in bad PR • Never know when a replacement firmware may increase the value of your device, or give you access to firmware talent
  51. 51. Block Replacement Firmware • What is the Right Answer? • Best = support replacement firmware • ADP1, ADP2 • Great = endorse replacement firmware • Nexus One • OK = “fig leaf” on firmware issue
  52. 52. Summary • Avoid anti-patterns • Better for your apps • Better for your devices • Better for Android overall
  53. 53. Contact Info • http://commonsware.com • mmurphy@commonsware.com • http://commonsware.com/blog • Twitter: commonsguy • +1.484.350.4004

×