Post on 14-Jan-2015
description
Android App Mistakes:Avoiding the Anti-Patterns
by Mark Murphy, CommonsWare
Introduction
• Anti-Patterns
• Code pollution
• Fatal assumptions
• Goal: help you avoid these anti-patterns
• Developers
• OEMs
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()
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
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
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
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
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
Background Becomes Foreground
• What is the Anti-Pattern?
• Doing significant processing in background callbacks
• onReceive()
• onCreate() / onStart() / onDestroy()
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)
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
Boot-Time Services
• What is the Anti-Pattern?
• Configuring a BroadcastReceiver to respond to the BOOT_COMPLETED broadcast Intent
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
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
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
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
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)
Use Mutable Statics
• What is the Anti-Pattern?
• Using static data members for more than final “constant” values
• Caching
• Cross-component communication
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
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.
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
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
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
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
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
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
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
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
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
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
Assume Touch
• Why Is This Important?
• Not all Android devices will be touchscreens
• Television set-top boxes
• Low-end smartphones / high-end “feature phones”
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
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
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
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
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
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
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
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
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
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
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
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
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
Breaking the SDK
• What is the Right Answer?
• Test, test, test!
• CTS is nowhere near sufficient
• Developer device seeding program
• Direct
• Through services (DeviceAnywhere)
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
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
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
Block Replacement Firmware
• What is the Anti-Pattern?
• Using cryptographic signing to prevent people from replacing firmware
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
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
Summary
• Avoid anti-patterns
• Better for your apps
• Better for your devices
• Better for Android overall
Contact Info
• http://commonsware.com
• mmurphy@commonsware.com
• http://commonsware.com/blog
• Twitter: commonsguy
• +1.484.350.4004