Android App Mistakes: Avoiding the Anti-Patterns

53
Android App Mistakes: Avoiding the Anti-Patterns by Mark Murphy, CommonsWare

description

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.

Transcript of Android App Mistakes: Avoiding the Anti-Patterns

Page 1: Android App Mistakes: Avoiding the Anti-Patterns

Android App Mistakes:Avoiding the Anti-Patterns

by Mark Murphy, CommonsWare

Page 2: Android App Mistakes: Avoiding the Anti-Patterns

Introduction

• Anti-Patterns

• Code pollution

• Fatal assumptions

• Goal: help you avoid these anti-patterns

• Developers

• OEMs

Page 3: Android App Mistakes: Avoiding the Anti-Patterns

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()

Page 4: Android App Mistakes: Avoiding the Anti-Patterns

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

Page 5: Android App Mistakes: Avoiding the Anti-Patterns

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

Page 6: Android App Mistakes: Avoiding the Anti-Patterns

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

Page 7: Android App Mistakes: Avoiding the Anti-Patterns

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

Page 8: Android App Mistakes: Avoiding the Anti-Patterns

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

Page 9: Android App Mistakes: Avoiding the Anti-Patterns

Background Becomes Foreground

• What is the Anti-Pattern?

• Doing significant processing in background callbacks

• onReceive()

• onCreate() / onStart() / onDestroy()

Page 10: Android App Mistakes: Avoiding the Anti-Patterns

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)

Page 11: Android App Mistakes: Avoiding the Anti-Patterns

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

Page 12: Android App Mistakes: Avoiding the Anti-Patterns

Boot-Time Services

• What is the Anti-Pattern?

• Configuring a BroadcastReceiver to respond to the BOOT_COMPLETED broadcast Intent

Page 13: Android App Mistakes: Avoiding the Anti-Patterns

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

Page 14: Android App Mistakes: Avoiding the Anti-Patterns

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

Page 15: Android App Mistakes: Avoiding the Anti-Patterns

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

Page 16: Android App Mistakes: Avoiding the Anti-Patterns

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

Page 17: Android App Mistakes: Avoiding the Anti-Patterns

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)

Page 18: Android App Mistakes: Avoiding the Anti-Patterns

Use Mutable Statics

• What is the Anti-Pattern?

• Using static data members for more than final “constant” values

• Caching

• Cross-component communication

Page 19: Android App Mistakes: Avoiding the Anti-Patterns

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

Page 20: Android App Mistakes: Avoiding the Anti-Patterns

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.

Page 21: Android App Mistakes: Avoiding the Anti-Patterns

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

Page 22: Android App Mistakes: Avoiding the Anti-Patterns

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

Page 23: Android App Mistakes: Avoiding the Anti-Patterns

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

Page 24: Android App Mistakes: Avoiding the Anti-Patterns

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

Page 25: Android App Mistakes: Avoiding the Anti-Patterns

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

Page 26: Android App Mistakes: Avoiding the Anti-Patterns

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

Page 27: Android App Mistakes: Avoiding the Anti-Patterns

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

Page 28: Android App Mistakes: Avoiding the Anti-Patterns

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

Page 29: Android App Mistakes: Avoiding the Anti-Patterns

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

Page 30: Android App Mistakes: Avoiding the Anti-Patterns

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

Page 31: Android App Mistakes: Avoiding the Anti-Patterns

Assume Touch

• Why Is This Important?

• Not all Android devices will be touchscreens

• Television set-top boxes

• Low-end smartphones / high-end “feature phones”

Page 32: Android App Mistakes: Avoiding the Anti-Patterns

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

Page 33: Android App Mistakes: Avoiding the Anti-Patterns

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

Page 34: Android App Mistakes: Avoiding the Anti-Patterns

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

Page 35: Android App Mistakes: Avoiding the Anti-Patterns

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

Page 36: Android App Mistakes: Avoiding the Anti-Patterns

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

Page 37: Android App Mistakes: Avoiding the Anti-Patterns

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

Page 38: Android App Mistakes: Avoiding the Anti-Patterns

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

Page 39: Android App Mistakes: Avoiding the Anti-Patterns

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

Page 40: Android App Mistakes: Avoiding the Anti-Patterns

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

Page 41: Android App Mistakes: Avoiding the Anti-Patterns

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

Page 42: Android App Mistakes: Avoiding the Anti-Patterns

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

Page 43: Android App Mistakes: Avoiding the Anti-Patterns

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

Page 44: Android App Mistakes: Avoiding the Anti-Patterns

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

Page 45: Android App Mistakes: Avoiding the Anti-Patterns

Breaking the SDK

• What is the Right Answer?

• Test, test, test!

• CTS is nowhere near sufficient

• Developer device seeding program

• Direct

• Through services (DeviceAnywhere)

Page 46: Android App Mistakes: Avoiding the Anti-Patterns

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

Page 47: Android App Mistakes: Avoiding the Anti-Patterns

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

Page 48: Android App Mistakes: Avoiding the Anti-Patterns

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

Page 49: Android App Mistakes: Avoiding the Anti-Patterns

Block Replacement Firmware

• What is the Anti-Pattern?

• Using cryptographic signing to prevent people from replacing firmware

Page 50: Android App Mistakes: Avoiding the Anti-Patterns

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

Page 51: Android App Mistakes: Avoiding the Anti-Patterns

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

Page 52: Android App Mistakes: Avoiding the Anti-Patterns

Summary

• Avoid anti-patterns

• Better for your apps

• Better for your devices

• Better for Android overall

Page 53: Android App Mistakes: Avoiding the Anti-Patterns

Contact Info

• http://commonsware.com

[email protected]

• http://commonsware.com/blog

• Twitter: commonsguy

• +1.484.350.4004