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.
2. Introduction
• Anti-Patterns
• Code pollution
• Fatal assumptions
• Goal: help you avoid these anti-patterns
• Developers
• OEMs
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. 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. 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. 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. 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. 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. Background Becomes Foreground
• What is the Anti-Pattern?
• Doing significant processing in
background callbacks
• onReceive()
• onCreate() / onStart() / onDestroy()
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. 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. Boot-Time Services
• What is the Anti-Pattern?
• Configuring a BroadcastReceiver to
respond to the BOOT_COMPLETED
broadcast Intent
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. 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. 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. 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. 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. Use Mutable Statics
• What is the Anti-Pattern?
• Using static data members for more than
final “constant” values
• Caching
• Cross-component communication
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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. Block Replacement Firmware
• What is the Anti-Pattern?
• Using cryptographic signing to prevent
people from replacing firmware
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. 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