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

Android App Mistakes: Avoiding the Anti-Patterns

Embed Size (px)

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.

Citation preview

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