
Android™
Programming
Pushing the Limits
Erik Hellman
This edition first published 2014
© 2014 Erik Hellman
Registered office
John Wiley & Sons Ltd, The Atrium, Southern Gate, Chichester, West Sussex, PO19 8SQ, United Kingdom
For details of our global editorial offices, for customer services and for information about how to apply for permission to reuse the copyright
material in this book please see our website at www.wiley.com.
The right of the author to be identified as the author of this work has been asserted in accordance with the Copyright, Designs and Patents
Act 1988.
All rights reserved. No part of this publication may be reproduced, stored in a retrieval system, or transmitted, in any form or by any means,
electronic, mechanical, photocopying, recording or otherwise, except as permitted by the UK Copyright, Designs and Patents Act 1988,
without the prior permission of the publisher.
Wiley also publishes its books in a variety of electronic formats. Some content that appears in print may not be available in electronic books.
This publication is designed to provide accurate and authoritative information in regard to the subject matter covered. It is sold on the
understanding that the publisher is not engaged in rendering professional services. If professional advice or other expert assistance is
required, the services of a competent professional should be sought.
Trademarks: Wiley and the Wiley logo are trademarks or registered trademarks of John Wiley and Sons, Inc. and/ or its affiliates in the United
States and/or other countries, and may not be used without written permission. Android is a trademark of Google, Inc. All other trademarks
are the property of their respective owners. John Wiley & Sons, Ltd. is not associated with any product or vendor mentioned in the book.
A catalogue record for this book is available from the British Library.
ISBN 978-1-118-71737-0 (paperback); ISBN 978-1-118-71730-1 (ePDF); 978-1-118-71735-6 (ePub)
Set in 9.5 pt Myriad Pro by Indianapolis Composition Services
Printed in the United States by Bind-Rite
Dedication
This book is dedicated to my amazing dad, Ingemar Hellman, who taught me programming when I was
nine years old. None of this would have been possible if it weren’t for all the amazing things he taught me.
Erik Hellman,
Second generation software developer
Publisher’s Acknowledgements
Some of the people who helped bring this book to market include the following:
Editorial and Production
VP Consumer and Technology Publishing Director: Michelle Leete
Associate Director–Book Content Management: Martin Tribe
Associate Publisher: Chris Webb
Project Editor: M. Faunette Johnston
Copy Editor: Melba Hopper
Technical Editor: Erik Westenius
Editorial Manager: Jodi Jensen
Senior Project Editor: Sara Shlaer
Editorial Assistant: Annie Sullivan
Marketing
Associate Marketing Director: Louise Breinholt
Marketing Manager: Lorna Mein
Senior Marketing Executive: Kate Parrett
Marketing Assistant: Polly Thomas
Composition Services
Compositor: Jennifer Goldsmith, Andrea Hornberger
Proofreader: Wordsmith Editorial
Indexer: Potomac Indexing, LLC
About the Author
Erik Hellman grew up in the small town of Borlänge in the middle of Sweden and currently lives in the city
of Malmö with his wife. From an early age he showed a great interest in all kinds of technology, much thanks
to his father. This interest has carried on over the years and he likes to spend time tinkering with all kinds of
technology, be it hardware or software.
Erik currently works as a developer consultant at Factor10. He previously worked for Sony Mobile as one of the
lead architects for their Android development and later as a research engineer where he participated in the
development of the next generation of mobile solutions from Sony.
Erik has a lifetime of experience with software development and programming. His father taught him how to
write code in Turbo Pascal at the age of nine, as well as how to design relational databases in Oracle 3 on his
old IBM AT 286. Much later, Erik studied Software Engineering at Blekinge Institute of Technology where he also
worked as an assistant teacher in various software engineering courses.
Erik can often be found at various developer conferences where he likes to speak about cutting-edge software
technologies. You can also find out more about Erik and his other hobbies at his blog (http://blog.hellsoft.se) or
follow him on Google+ (http://gplus.to/ErikHellman) or Facebook (https://www.facebook.com/ErikHellman).
Acknowledgements
First of all, I’d like to thank my wife Kaisa-Leena. Without her love, support, and infinite patience with me during
the writing of this book, this book would never have been finished.
A big thank you goes out to all my friends and former colleagues at Sony Mobile. Almost everything I’ve learned
about Android and mobile technologies came from my years working with all of you. I’m extremely proud to
have been part of the team that built the Xperia series of devices. A special thank you to my former boss, Henrik
Bengtsson, and his team at the Sony Mobile Research in Lund.
Finally, I’d like to thank my editors; Faunette, Melba, Erik, and all the people working at Wiley for helping me
write this book. A big thanks goes to my technical editor Erik Westenius for his eye for details and making sure
that my code and examples are understandable. Also, a thank you to Kristoffer Åberg at Sony Mobile for giving
me valuable input on the UI design sections.
Contents
Chapter 1 Fine-Tuning Your Development Environment .. . . . . . . . . . . . . . . . . . 9
viii Contents
Chapter 2 Efficient Java Code for Android .. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
Part II Getting the Most Out of Components . . . . . . . . . . . . . . . . . . . . . . . . . . 55
Chapter 3 Components, Manifests, and Resources . . . . . . . . . . . . . . . . . . . . . . . 57
Contents ix
Chapter 4 Android User Experience and Interface Design .. . . . . . . . . . . . . . . . 77
Chapter 5 Android User Interface Operations . . . . . . . . . . . . . . . . . . . . . . . . . . . . 93
x Contents
Chapter 6 Services and Background Tasks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 111
Chapter 7 Android IPC . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 131
Contents xi
Chapter 8 Mastering BroadcastReceivers and Configuration Changes .. . . 151
Chapter 9 Data Storage and Serialization Techniques . . . . . . . . . . . . . . . . . . . 165
xii Contents
Chapter 10 Writing Automated Tests .. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 191
Chapter 11 Advanced Audio, Video, and Camera Applications. . . . . . . . . . 207
Chapter 12 Secure Android Applications . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 231
Contents xiii
Documentation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 248
Chapter 13 Maps, Location, and Activity APIs. . . . . . . . . . . . . . . . . . . . . . . . . . . 249
Websites . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 265
Chapter 14 Native Code and JNI .. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 267
xiv Contents
Chapter 15 The Hidden Android APIs .. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 287
Chapter 16 Hacking the Android Platform. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 299
Contents xv
Chapter 17 Networking, Web Service, and Remote APIs .. . . . . . . . . . . . . . . . 319
Documentation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 347
Chapter 18 Communicating with Remote Devices. . . . . . . . . . . . . . . . . . . . . . 349
xvi Contents
Chapter 19 Google Play Services. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 369
Chapter 20 Distributing Applications on Google Play Store .. . . . . . . . . . . . . 389
Introduction
If you’re reading this book, you’re probably familiar with the Android platform, smartphones, and application
development. You’re well aware of the tremendous growth of Android devices over the last few years and the
potential that the platform holds for application developers. I could give you specific numbers and statistics
about Android, but that wouldn’t serve much purpose because those numbers most likely would be invalid by
the time you read this book. It’s enough to say that the Android platform is here to stay, and you can expect its
growth to continue for the foreseeable future.
All of this is great news to people like you and me. Those of us who are aiming to becoming experts at Android
development face a bright future. The demand for skilled application developers for Android is growing every
day, and at the same time, the demand on developers is growing because the features that users want and the
possibilities provided by the new technologies require us to constantly think ahead.
Although Google provides a great set of tools and APIs to help you perform your magic, you still need to push
yourself on what you can now do with Android. That is the goal of this book: to push the limits of the Android
platform and build ever more advanced applications.
Who This Book Is For
You’ve probably written a few Android applications already and are eager to learn more advanced APIs and
tricks. Perhaps you generally program using Java, but you don’t have any problems learning a new language.
As a developer, you’re not afraid to try out new things, be it a new IDE or a brand new API. You like to test all the
latest features, and you don’t’ become discouraged when things initially fail.
While you can find plenty of introductory books on Android development, this is not such a book. Instead, this
book is targeted toward developers who have previous experience with application development for Android.
You know all the basics and how to create an app using the Activity, Service, BroadcastReceiver,
and ContentProvider classes. You’re familiar with the core concept of the application manifest and the
different types of application resources for Android. If you can build a simple Android application in a matter of
minutes, you’re well prepared for the contents of this book.
My goal for this book is just what the title says: pushing the limits. In each chapter, I try to push the limits on what
typical Android developers know and use in their daily work. Even though you may be familiar with some of this
book’s topics, I provide an in-depth discussion on each topic; so, trust me, there’s something new for all Android
developers in this book.
2 Android Programming: Pushing the Limits
What This Book Covers
The Android platforms have developed at an amazing pace. Even while writing this book, I had to change my
original plans because Google kept coming out with new APIs, tools, and technologies for Android developers!
While many of the examples in this book require a later version of Android, my assumption is that you are
familiar with the different API levels and understand which Android version is required in each case.
My goal is to discuss those aspects of Android that I believe are of value for developers. Some technologies were
excluded, either because they aren’t “pushing the limits” or they wouldn’t add real value to the book. So, rather
than being a collection of “recipes” for Android applications or an extensive walkthrough of all the features,
each chapter goes into the deep technical details of their respective topic. Thus, rather than provide complete
applications, I provide numerous pieces of substantial code that you can use to enhance your own applications.
Depending on your experience, you might encounter some unfamiliar technologies. For example, Chapter 12
covers security issues and assumes a basic understanding of encryption and private/public keys, and Chapter
18 covers technologies such as USB communication, Bluetooth Low Energy, and WiFi Direct. But don’t worry.
In such cases, I direct you to sources where you can find additional information. Each chapter has a Further
Resources section where I’ve listed additional resources such as books and websites where you can find more
information on the topics covered in each chapter.
How This Book Is Structured
This book is divided into three parts. The first part covers tools available to Android developers and the specifics
on the Java programming language for Android. The second part focuses on core Android components
and how to use them in an optimal way. The third and final part focuses on the latest and most advanced
technologies, including both the Android platform and the services that can be used with an Android device.
Part I: Building a Better Foundation
Chapter 1: Fine-Tuning Your Development Environment deals with the Android development tools. You’ll
find an introduction to the new IDE for Android called Android Studio. There is also a brief introduction to
Gradle, which is now used as the standard build system for Android applications.
Chapter 2: Efficient Java Code for Android focuses on the Java programming language and the specifics
for Android. I discuss some tricks that can help you reduce the load on memory and on the Dalvik garbage
collector. You’ll also find some examples showing the pros and cons of the different methods for multi-
threading.
Part II: Getting the Most Out of Components
Chapter 3: Components, Manifests, and Resources gives a general overview of the components and goes
on to describe some of the less frequently used parts of the application manifest. You’ll also find examples of
advanced use of Android resources.
Introduction 3
Chapter 4: Android User Experience and Interface Design focuses on the theory behind the design of user
interfaces. I describe how you should work when designing your user interfaces, starting with user stories,
personas, and the design-process for the different screens in your application. I explain how people think about,
react to, and interpret the various aspects of user interfaces. I describe details about fonts and what makes one
font more readable than another. This chapter gives a better understanding of the theories behind good design
that you can apply while designing your own interfaces.
Chapter 5: Advanced User Interface Operations focuses on the technical aspects of the Android UI. I show
how to use the new APIs with multiple screens in an application. A complete example of how to build a custom
View is covered followed by a section on advanced multi-touch handling.
Chapter 6: Services and Background Tasks focuses on how to use the Service component for optimal
background operations in your application. This chapter focuses on Services that aren’t published to other
applications.
Chapter 7: Android IPC covers Android IPC and how you can communicate between two separate Android
applications running on the same device. I explain the details of the Binder and how you can use it to build
applications that support plug-in functionality.
Chapter 8: Mastering BroadcastReceivers and Configuration Changes focuses on the use of
BroadcastReceivers and how to use them optimally to listen for system-wide events and configuration
changes. I describe the different types of broadcasts and how to use them, and I give some guidelines on how
to use the receiver component in a way that reduces the load on the device.
Chapter 9: Data Storage and Serialization Techniques focuses on data persistence and on the
ContentProvider component. I show how to use the SharedPreferences and how to create a Settings
UI using the ready-made Android components. High-performance providers are covered as well as different
methods for serializing data where the standard SQLite-based solution isn’t sufficient. Also, the serialization
methods explained here are useful when communicating with Services online. I conclude this chapter with
some details on how to use the Android backup agent in your application.
Chapter 10: Writing Automated Tests is dedicated to building automated tests for your Android application. I
give thorough examples of everything from simple unit tests to complete integration tests for the four different
components. I highly recommend that all readers go through this chapter thoroughly because writing tests for
your application will greatly improve your development cycle and the quality of your code.
Part III: Pushing the Limits
Chapter 11: Advanced Audio, Video, and Camera Applications deals with advanced graphics, audio, and
video. I explain the use of the different audio APIs, including the use of Open SL ES for any high-performance
and low-latency requirements you might have regarding audio. I explain the use of both Text-To-Speech and the
Speech Recognition API for Android. The use of OpenGL ES for high-performance processing of camera input
and video is demonstrated as well. Finally, I discuss a feature introduced in Android 4.3 for using an OpenGL ES
surface as an encoding source, which you can employ to record a video of your OpenGL ES scene.
4 Android Programming: Pushing the Limits
Chapter 12: Secure Android Applications looks at the different security aspects in Android with a focus on
how to use the cryptographic APIs. I explain how to use key management in android in a secure way and how to
encrypt data on a device. I conclude this chapter with a section covering the Device Management API.
Chapter 13: Maps, Location, and Activity APIs focuses on the new maps and location API for Android. You
find out about the new fused Location Provider and how to use features such as geofencing and activity
recognition in order to build advanced location-based applications.
Chapter 14: Native Code and JNI delves into native development for Android using the C programming
language. I explain the use of the Android NDK (Native Development Kit) and how you can combine native code
with Java code through the use of JNI.
Chapter 15: The Hidden Android APIs looks at how the hidden APIs in Android work, how you can find them,
and how you can safely invoke them in your application. You also find out how to search the Android source
code in order to discover the hidden APIs.
Chapter 16: Hacking the Android Platform describes how to work with the Android Open Source Project
(AOSP), build your own custom firmware, and extend the Android platform. I explain how the AOSP is
designed and to work when modifying the Android platform. You’ll also find an introduction on the process of
contributing your changes to the AOSP so that they can become a standard part of the Android platform.
Chapter 17: Networking, Web Services, and Remote APIs looks at integrating online web services in an Android
application and how to optimize network operations. I cover the use of recommended third-party libraries for
working with network operations, from standard HTTP to Web Sockets and SPDY, and I explain how to invoke three
different types of web services. I explain the concept of authenticating toward third-party web services, including
how to use OAuth2 in your Android application as well as how to integrate the Facebook SDK for Android.
Chapter 18: Communicating with Remote Devices delves into the different methods for communicating
with remote devices using the various connectivity technologies available on Android. I explain how to talk
to USB devices using the built-in APIs in Android. I describe the APIs for communicating with Bluetooth Low
Energy devices (also called Bluetooth Smart). You’ll find an introduction on utilizing the network discovery API
for Android, and I show how you can implement ad hoc peer-to-peer communication using the WiFi Direct
standard. You’ll also find a section on implementing on-device services supporting both RESTful web services
and asynchronous communication using Web Sockets.
Chapter 19: Google Play Services covers the use of some of the APIs from Google Play Services. You’ll find
out how to get authorization for any of the online Google APIs and an example of using the Application Data
feature for Google Drive to store your application’s data across multiple devices. You’ll also find a guide to
building Google Cloud Endpoints using the built-in feature in Android Studio, and I show how you can extend
this with your own services. This chapter also includes a guide on implementing Google Cloud Messaging. Also,
I demonstrate how you can use the real-time multiplayer API that is part of the Google Play Game Services to
build advanced multiplayer games.
Chapter 20: Distributing Applications on Google Play Store, the final chapter, focuses on aspects of
distributing your application on the Google Play Store and how to include the different monetization options.
I explain how to add In-app Billing and ads in your application as well as the use of the licensing service for
verifying the license of your application on the user’s device. The chapter ends with a guide to utilizing the APK
Expansion Files feature to distribute application data that exceeds your application’s 50MB limit.
Introduction 5
What You Need to Use This Book
Although you can run many of the examples in this book on an emulator, I strongly recommend that you
acquire a device with the latest version of Android because many examples in the book use hardware that isn’t
available on the emulator. Although any Google-certified Android device is sufficient (that is, an Android device
with the Google Play Store) for the examples in this book, given that it has the correct Android version, I always
recommend purchasing a Google Nexus device so that you can try all the latest platform features as early as
possible.
You also need a computer running Linux, OS X, or Windows for your development environment, as well as an
Internet connection to access the online resources needed in some chapters. You need to have Java SDK version
6 installed on your computer. (You can download it at http://java.oracle.com) in order to run the IDE
and other tools.
In Chapter 18, you’ll need additional hardware to implement the examples. You’ll need a device with Bluetooth
Low Energy support, such as an activity tracker or a heartbeat monitor. For the samples on USB communication,
you’ll need an Android device that supports USB On-The-Go, a USB OTG cable, and a USB-connected device that
you can connect to. The easiest approach to testing USB is to use an Arduino Uno board.
Source Code
Most of the source code samples in this book aren’t complete implementations; rather they are snippets of
code I use to demonstrate the most important parts of the topic being covered. My assumption is that you are
familiar enough with Android development to understand where to fit these snippets of code into your own
project.
Some of the samples and source code snippets in the book are available on my GitHub site (https://
github.com/ErikHellman/apptl). However, I strongly recommend that you manually type the code you
find in the book instead of simply copying a file. Doing so will give you a better understanding of how the code
works.
You can also download the code files from the book’s companion website at http://www.wiley.com/go/
Errata
I’ve tried to review and verify everything in the book as much as possible, but sometimes mistakes happen.
It could be a typo in the text or the source code, but it could also be something that is missing or simply
mistaken. I’ll update any errors in the sample code in the GitHub repository at https://github.com/
ErikHellman/apptl with proper bug fixes.
Part IBuilding a Better
Foundation
Chapter 1 Fine-Tuning Your Development Environment
Chapter 2 Efficient Java Code for Android
Chapter 1
Fine-Tuning Your
Development
Environment
Depending on what you’re developing, you have different choices when it comes to the tools you can use.
Your requirements on the development environment differs if you’re writing an HTML5 application or if you’re
developing a server-side application in Java. Some platforms offer more choice than others, and as I describe
next, developing Android applications gives you a lot of choice for your development environment.
I begin this chapter with some more advanced internals of the Android SDK and how you can use them in
your daily development and how they can assist you in improving the quality of your application. I continue
by describing how to structure your code projects in an optimal way for reuse by using library projects. You
also learn how to take version control to a new level by integrating Git with a code-review tool called Gerrit.
As a developer, you will spend most of your time using the IDE tool. While the Eclipse IDE is still supported by
Google, they are now pushing developers to use their new Android Studio IDE for all Android projects. So, I give
an introduction to Android Studio as well as to the new build system called Gradle. Finally, I go through the
developer settings that are available on Android devices.
Operating Systems for Android Development
This is probably the one topic you don’t have to worry about. Either you can pick the operating system on
your computer used for development, or it is limited by the IT-policies of your employer. For most Android
developers, any of the officially supported operating systems works fine. However, there are situations where
the choice will matter.
Google supports Windows, Linux, and OS X for developing Android applications. Although Windows is officially
supported by the Android SDK, you’ll have problems if you decide to do advanced development, especially
when it comes to writing native applications or building your own custom ROM. The best choice is either Linux
or OS X. If possible, try to have one of these as your primary operating system, and you’ll run into far fewer
problems. Another reason for avoiding Windows on your Android development environment is that you won’t
need to install new USB drivers for every Android device you work on.
Advanced Android SDK Tools
After you have your operating system and the required (and recommended) tools installed on your computer,
you can focus on the Android SDK. You will find the download for your operating system and the latest
installation instructions at http://developer.android.com/sdk. Android Studio comes with an SDK
10 Part I: Building a Better Foundation
bundle that is completely managed from within the IDE, but if you prefer to have a standalone version you can
download that as well.
Make sure that you always keep the SDK up to date and that you download the APIs for all the Android versions
that you’re developing for. The easiest way to update your standalone Android SDK is to run the update tool
from the command prompt:
$ android update sdk --no-ui
Inside the Android SDK folder, you will find a number of subfolders. From a tools perspective, only the
platform-tools and tools folders are of interest for now. I will introduce some of these tools and explain
how to use them, starting with the adb (Android Debug Bridge) tool. If you are frequently using the command
line tools in the Android SDK I recommend that you add the path to these folders in your local PATH variable.
You can find the official documentation for most of the tools in the Android SDK at http://
developer.android.com/tools/help/index.html.
The adb Tool
In the platform-tools folder, you will find the adb tool that is used to communicate with your device to
install and start apps during development. In earlier versions of the Android SDK, this tool was found in the
tools directory, but it has since been moved. Besides being used for installing, starting, and debugging
applications from your IDE, the adb tool enables you to manually call many of the low-level operations on your
Android device for debugging purposes. To list all the commands available, simply type adb help all in
your terminal (Linux or Mac OS X) or command prompt (Windows).
Some common adb commands are
■ adb devices—List all connected Android devices and Emulators.
■ adb push <local> <remote>—Copy a file from your computer to a device (usually on the SD card).
■ adb pull <remote> <local>—Copy a file from the device to your computer.
adb and Multiple Devices
If you ever need to develop and debug an application for two or more devices simultaneously, such as for a
multiplayer game or an instant-message application, adb needs an additional argument to know which device
you want to address. You do so by adding –s <serial number> as the first parameter to adb. You can see
the serial number for your connected devices by executing the adb devices command. To run the logcat
command on a specific device, run the following:
$ adb devices
List of devices attached
0070015947d30e4b device
015d2856b8300a10 device
$ adb –s 015d2856b8300a10 logcat
Chapter 1: Fine-Tuning Your Development Environment 11
When you have multiple devices connected or emulators started a dialog box will appear when you
launch your application in your IDE.
Mastering Logcat Filtering
Logging is an important part of Android application development. Although using breakpoints and a debugger
from your IDE is extremely powerful when you want to follow the execution flow and inspect the values and
state of different variables, simply reading the output from logcat can sometimes be more efficient. Android
logging is handled by the logcat function, which is usually integrated in your IDE but can also be called via
the adb command.
Because Android outputs all system and application log messages to the same stream, it can become quite
complicated to find the messages that relate to your application. Luckily, there are some easy ways to filter the
logs, as I show in the following code.
Android log messages are prepended with a tag and a priority. Usually, you declare a separate log tag for each
class in your application like this:
private static final String TAG = “MyActivity”;
You can then use this tag when printing a log message somewhere in the code for that class:
Log.d(TAG, “Current value of moderation: “ + moderation);
To filter out all log messages except those that have MyActivity as the value for the tag, you can execute
logcat as follows.
$ adb logcat MyActivity:* *:S
The parameters after logcat are the filters you want to apply. They are formatted as <tag>:<priority>
where an asterisk (*) indicates all possible values. One important thing that can easily be missed is that you
must include the special filter *:S, which tells logcat to silence all messages. In combination with your own
filters, you can easily control logcat to print only the messages you want to see.
If you use filters when viewing the logcat output, I also recommend adding AndroidRuntime:*. This will
show you relevant information from the Android system as well as exceptions that are generated by your
application but caught by the platform.
Connecting adb over Wi-Fi
Usually, you connect to your Android device using a USB cable plugged into your computer. However, you can
also connect to an Android device over Wi-Fi using a standard TCP/IP connection. This can be very useful when
developing applications that are listening for events related to USB (since then the normal connection to your
computer will interfere), like connected/disconnected or when you simply don’t want to bother with USB cables
during development.
12 Part I: Building a Better Foundation
In order to enable adb connection over Wi-Fi, you first need to plug your device into your computer using USB as
you normally do. Also, make sure your computer and your Android device are connected to the same Wi-Fi. You also
need to know the IP address of your Android device, which you can find on your device by choosing Settings➪
Wi-Fi➪Advanced. In the bottom of the list that appears you will find your device IP address for the current Wi-Fi.
After you have this set up correctly, run the following commands from your terminal:
$ adb devices
List of devices attached
0070015947d30e4b device
$ adb tcpip 5555
$ adb connect 192.168.1.104
$ adb devices
List of devices attached
192.168.1.104:5555 device
The first command is just to verify that your device is connected in debugging mode. The second command tells
the device to restart the adb daemon on the device in TCP/IP mode and listen on port 5555 (the default port for
adb). The third command tells the adb Service on your computer to connect to the IP address (using default
port 5555) of the device. Finally, the fourth command verifies that the computer is connected to the device over
TCP/IP. You can now unplug the USB cable from your device and start developing with your IDE as usual.
The device will keep the adb daemon in TCP/IP mode until it is restarted or until you run the command adb
usb, which restarts the adb daemon in USB mode.
Connecting adb over WiFi is not guaranteed to work on all devices. Also, the communication
performance with the device is much worse, which can be annoying when you need to deploy a large
application.
Executing Commands on an Android Device
Because an Android system is basically a custom Linux distribution, you can interact with it in much the same
way as you can with Linux on your PC. By running a special adb command, you can start a standard Linux-shell
on your Android device that lets you perform command-line operations in the same way as you do on your
other Linux installations as shown here.
$ adb shell
When running a shell on your Android device, two useful commands are am and pm. These commands aren’t
related to the time of day; instead, they enable you to interact with the Application and Package Managers,
respectively, which can be useful during early development and testing. For instance, if you’re implementing a
Service that will be started by some externally triggered Intent, you can manually send this Intent using
the am command.
To start a Service using an Intent action, simply type the following on the command line:
$ adb shell am startservice –a <intent action>
Chapter 1: Fine-Tuning Your Development Environment 13
You can add parameters for extras and even specify a certain component name. In addition to startservice,
you can launch an Activity or send a broadcast Intent. Calling adb shell am without additional
parameters will display a full list of possible commands. You will find that this command is especially
useful when you start developing an Android application and need to test a Service before you create
the Activity that will launch it. Also, it’s useful for simulating Intents that will be launched by other
applications, such as ACTION_VIEW or ACTION_SEND.
The Package Manager is a central Android component that manages the installed applications on a device.
You can control use of the pm command in a similar way to how you work with the Application Manager.
The Package Manager lets you interact with the installed applications (packages), allowing you to list, install,
uninstall, and inspect the features and permissions on the device. Although the pm command isn’t as useful
during development as the am command, it can sometimes be helpful if you want to find out details about the
device that are otherwise a bit complicated to discover. For instance, if you want to list all the installed packages
(that is, installed apps), you can type the following:
$ adb shell pm list packages
In addition to the adb commands just covered, there are many others you need to be familiar with. If you
haven’t done so already, take some time to experiment with the adb commands.
You can find a list of adb commands and their uses at http://developer.android.com/
Stress-Testing an Application’s UI with Monkey
Most developers often consider testing a tedious and boring task, and Android developers are probably no
exception. A good developer handles testing by writing automated tests that verify parts of the code in the
application when running on the device. You can also find code inspection tools that search for common
coding mistakes (you’ll look at one of these in the section “Static Code Analysis with Lint,” later in this chapter).
However, as much as you might wish, writing automated tests and performing static code analysis is never
100% foolproof. A user doesn’t behave according to a certain pattern all the time. Users can click a button at
an unexpected moment or accidentally click the wrong button, which can cause your application to crash. You
basically need something that behaves like a user would, or better yet, like a monkey would!
The Android SDK comes with a powerful tool called the Application Exerciser Monkey, or simply, Monkey . This
is a command-line tool that allows you to generate pseudo-random user events like touches or system events
on a device. The purpose is to stress test your application by simulating what a user could do. Although Monkey
doesn’t simulate a typical use-case scenario for your application, it provides valuable feedback on how your
application will work if the user interacts with your user interface in an unpredictable way.
The following command executes the Monkey tool on an application with the specific <package name> and
injects as many random events as specified by <event count>.
$ adb shell monkey –p < package name> < event count>
14 Part I: Building a Better Foundation
The default behavior for Monkey is to stop when an unhandled exception occurs and to report the error. This
behavior is useful for finding things like unexpected NullPointerExceptions or similar issues in your
code. You can fine-tune the behavior through various parameters and tell Monkey to halt only if, for instance, a
security exception occurs.
Scripting Monkey with Monkeyrunner
A more advanced way of executing Monkey on your application is by writing a Python script that uses the
Monkeyrunner API. This can be very useful in a continuous development environment where you want to run
the Monkey tool and perform other actions as well. It also allows you to provide input values for keystrokes and
capture screen shots programmatically that can be compared (also using the Monkeyrunner API) to a set of
screen shots known to be correct.
For a team of Android developers, this can prove to be a huge advantage because it provides a robust
regression-testing solution with very little effort. Even small changes to your code can sometimes provide
unexpected results that can be very difficult to detect when you’re the only person testing the application
before release. Using the Monkey tool, and preferably building Monkeyrunner scripts for regression testing, is
highly recommended before publishing your application.
You can find the API for the Monkeyrunner at http://developer.android.com/tools/help/
monkeyrunner_concepts.html#APIClasses
The Gradle Build System for Android
With the release of Android Studio, Google also introduced a new modular build system that replaces the old
Ant scripts that were generated by the older versions of the SDK. When you create a new project in Android
Studio, it will also create all the Gradle scripts for your project.
Gradle is a modular build system similar to Ivy and Maven. It combines the flexibility of Ant with the
dependency management from Maven. Instead of writing build-scripts in complex XML-files, Gradle has its own
Groovy DSL (Domain-Specific Language) that allows you to express more clearly your build configuration.
The following code is the default build.gradle file that is generated for new projects. The first block tells
gradle which repository to download plug-ins and dependencies for the build. (This is not the same as the
dependencies for your project, which is defined in a later block.) The next part tells Gradle to apply a plug-
in, in this case the Android plug-in, which enables the specifics for Android development. Next come the
dependencies for your project, in this case only the support library that is located in the libs directory of your
project. The final block, starting with android, specifies the configuration for your project.
buildscript {
repositories {
maven { url ‘http://repo1.maven.org/maven2’ }
}
dependencies {
classpath ‘com.android.tools.build:gradle:0.5+’
}
Chapter 1: Fine-Tuning Your Development Environment 15
}
apply plugin: ‘android’
dependencies {
compile files(‘libs/android-support-v4.jar’)
}
android {
compileSdkVersion 18
buildToolsVersion “18.0.0”
defaultConfig {
minSdkVersion 18
targetSdkVersion 18
}
}
The user guide for the new Gradle build system can be found at http://tools.android.com/
tech-docs/new-build-system/user-guide.
The default directory structure for an Android project using the new build system is slightly different from what
you may be used to. Instead of having a flat structure, there are two main source sets: source code and test
sources. They are in the following directories:
src/main/
src/instrumentTest/
Under the main directory the Java source code is placed in the java and resources are placed in the res
directory. The AndroidManifest.xml file is located directly in the main directory (see Figure 1-1).
The other directories for project files are assets (for binary assets), aidl (for Android IDLs), rs (RenderScript
sources) and jni (native C/C++ code).
While building and running your project is supported directly in the Android Studio IDE, you can interact with
the build system through the command line as well. Gradle defines a number of tasks and to list all available
tasks, simply type the following from the root of your Android project.
$ ./gradlew tasks
If you, for instance, want to build the application from scratch you would run the following.
$ ./gradlew clean build
This will execute first the clean task, followed by the build task.

16 Part I: Building a Better Foundation
Figure 1-1: The directory structure and Gradle build file shown in the Android Studio IDE
Migrating Existing Projects to Gradle
Since most existing Android projects are not using the Gradle build system, a migration guide might be in
order. The easiest way to migrate is to create a new Android project using Android Studio. Then, copy your own
project to a sub-folder in the new project.
Next, take the build.gradle file for the application created by Android studio and copy it to the root of your
own application.
android {
sourceSets {
main {
manifest.srcFile ‘AndroidManifest.xml’
java.srcDirs = [‘src’]
resources.srcDirs = [‘src’]
aidl.srcDirs = [‘src’]
renderscript.srcDirs = [‘src’]
res.srcDirs = [‘res’]
assets.srcDirs = [‘assets’]
}
}
}
Chapter 1: Fine-Tuning Your Development Environment 17
Edit the android section of the file so that it looks like the previous example. This should work well for
all existing Android projects that follow the old standard directory structure. If your project has a different
structure, simply change the paths from the previous example. (Note that all paths are relative.)
Optimize and Obfuscate with ProGuard
An Android application is the compiled result from your Java, XML, and other resource files. The Java code is
compiled into a binary format called dex, which is what the Dalvik virtual machine on Android reads when
executing your code. This format is not designed to be human-readable, tools are available for decompiling a
dex file back to a human-readable format.
In some cases, decompiling the code can be a security issue—for instance, when your code contains keys or
other values that should not be easily accessible (such as integration with Licensing Server). Although it isn’t
possible to completely prevent decompilation of your code, you can make it much more difficult by obfuscating
it before you publish it. This method will make reverse engineering much more time-consuming and hopefully
discourage hacking attempts on your application.
You obfuscate your code for Android by using the ProGuard tool that’s integrated in the Android SDK. The tool
is supported by the Gradle build system, and all you need to do is to add the following to the android section in
build.gradle.
buildTypes {
release {
runProguard true
proguardFile getDefaultProguardFile(‘proguard-android.txt’)
}
}
This will enable ProGuard to be applied to the release-build of your application. During normal development
this step is excluded.
Another reason to obfuscate your code is that doing so performs some additional optimizations, as well as
shrinking the resulting dex binary by removing unused code. This is especially useful when you’ve included a
large third-party library, because it can significantly reduce the final file size and memory usage during runtime.
Android Library Projects and Third-Party Libraries
Developers tend to write the same code over and over for new applications, which is why we create code
libraries that can be reused in the next project. The result is a faster development cycle because there’s less code
to write and test.
Android offers you two ways to reuse code among your application projects: by using either a precompiled
JAR file or a library project. The first method is preferable when you’re dealing with third-party code that you
don’t control or when you have a stable and complete set of library functions that won’t change during the
current project. The second method, using a library project, is useful if you’re developing multiple applications
in the same project that will share some code—for example, when you’ve decided to create one application
for smartphones and one for tablets, or when you have two different applications that will communicate (for
example, client and server).
18 Part I: Building a Better Foundation
Precompiled JAR Libraries
Using a precompiled JAR file in your Android project is very simple. Simply copy the file to the libs directory in
your project folder and then add it as a library within your IDE. The code in the JAR file will be available directly,
and when you build the application, the Android tool chain will automatically include and package the included
classes. If you’re obfuscating your application code with ProGuard, all included JAR files will be processed as
well. This is especially useful when you’re including large third-party libraries where you use only part of the
classes it provides. To include a local JAR file as a dependency to your project, simply add it to the dependency
section in build.gradle like this:
dependencies {
compile files(‘libs/android-support-v4.jar’)
}
Another way of doing this is by using a remote dependency repository, such as the central Maven repository.
To enable this and include a third-party library found in that repository, you update your build.gradle as
follows:
repositories {
mavenCentral()
}
dependencies {
compile ‘com.google.code.gson:gson:2.2.4’
}
The string in the dependencies section is an identifier for a specific version of a library. The call to
mavenCentral() will configure your build environment with the correct Maven settings.
To search for third-party libraries you can use the Maven search site at http://search.maven.
org/. Once you’ve found the right library, simply click on the version and copy the identifier
string from the Grails section. Note that not all libraries found on the central Maven repository are
supported on Android. Refer to the documentation first.
Setting Up a Library Project
An Android library project is basically a standard Android project that doesn’t declare any components that can
be started (Activities, Services, BroadcastReceivers, or ContentProviders) and that won’t
generate an APK when compiled or exported. The library’s sole purpose is to be shared by multiple application
projects so that you don’t have to copy the same code between them, which is very useful for sharing constants,
utility functions, common custom views, and other components. Because you’re dealing with the actual code and
not a precompiled JAR file, the code can be changed, which will affect all the applications that include this library.
Because Android development uses the Java programming language, using a library project to share code
between an Android application and a server-side component written in Java (for instance, a Java Enterprise
Chapter 1: Fine-Tuning Your Development Environment 19
application) can be especially useful. Common code to share in such a setup is the class representation of the
shared data and how to serialize and deserialize objects of these classes.
The Android SDK comes with a number of ready-to-use library projects that can be found under extras/
google in the SDK folder. More specifically, you can find library projects for the Play Services, APK extensions,
In-app Billing and Licensing features. To use these, you simply have to import them into your IDE and add a
dependency to your own project. Note: You can refer to multiple library projects in one application project.
You can set up a library project from the Android Studio IDE. Simply create a new module and choose Android
Library as the module type. A gradle.build will be generated for the new library project as shown next.
buildscript {
repositories {
maven { url ‘http://repo1.maven.org/maven2’ }
}
dependencies {
classpath ‘com.android.tools.build:gradle:0.4’
}
}
apply plugin: ‘android-library’
dependencies {
compile files(‘libs/android-support-v4.jar’)
}
android {
compileSdkVersion 17
buildToolsVersion “17.0.0”
defaultConfig {
minSdkVersion 7
targetSdkVersion 16
}
}
Note that the only difference from the default build file for Android project is the use of the plug-in android-
library instead of android.
To include a library project in your application’s build configuration, you simply refer to it as a dependency as
shown in the following.
dependencies {
compile project(‘:libraries:MyLibrary’)
}
Version Control and Source Code Management
Chances are that most development projects you’ll work on will involve other developers. A development
team usually comprises four to eight people, all working on the same code in parallel. Although the team could
20 Part I: Building a Better Foundation
decide who will make the changes for every file, it’s much more practical to apply a version control system to the
project files that supports a parallel method for development. Another benefit of a version control system is
that you can track changes back in time (who made what changes and when in a specific part of a file) and then
merge changes from different developers into the same file.
One of the most common version control systems used today is Git, and it’s also the system used to manage the
source code of both the Android Open Source Project and the Linux kernel. Git is a distributed version control
system that allows a developer to work independently from other developers. After the developer completes
the changes to the source code for a certain feature, he can push the changes to a server where the other
developers can retrieve it.
You can read more about Git and download it for various platforms at http://git-scm.com. For
a deeper introduction to Git and version control, I recommend the book, Version Control with Git (see
the “Further Resources” section at the end of this chapter).
A great feature with Git is that you don’t need a server in order to use it, which makes it suitable for all types of
projects, from projects where you’re the only developer to projects consisting of multiple teams. I recommend
that you always initiate a new Git repository for every new Android application you start developing. Although
you can perform all Git operations from your IDE, it’s always good to be able to use the command-line tool as
well. The example that follows shows how to initialize a new Git repository:
$ git init <path to project directory>
Initialized empty Git repository in <path to project directory> ./git
After you set up a Git repository for your project, you can start to add and commit changes. Usually, you
perform these operations through your IDE, but if you want, you can also perform the add and commit
commands from the command line. If you’re new to Git, I recommend that you take a tutorial before you start
using it.
Git becomes really powerful when a team of developers needs to work together on the same source code. The
team should set up a remote Git repository to which all the team members can synchronize their changes. The
easiest way to do so is either to set up a gitolite server, which is dedicated server software that provides remote
access to Git repositories, or to use a ready-made hosting solution like GitHub for remote Git repositories.
Gitolite allows you to set up your own server for hosting Git repositories, as well as define fine-grained access
control. If you need full control of your source code management or aren’t able to store your source code
outside the company network, gitolite is your best choice.
You can find the documentation and download for gitolite at http://gitolite.com/gitolite.
An excellent quick installation guide can be found at http://gitolite.com/gitolite/
Chapter 1: Fine-Tuning Your Development Environment 21
GitHub is a web-based hosting service for development projects that use Git. This online service provides both
a free and a paid service for individuals and businesses. The great thing about GitHub is that it provides an easy
way to share code with anyone on the Internet. If you want to be able to access your central repository when
outside the office or share your code as open source, then GitHub is a good choice.
Read more about GitHub at http://github.com.
Regardless of the size of your project, version control is very important. Even if you’re making only a small
prototype or test app, it’s good practice to always set up a Git repository. When you can track the history of your
code, you not only have the ability to track your changes efficiently but also the ability to understand why a
change occurred, because each commit will contain a message describing it. Take the little extra time required
to set up version control every time you start a project. Doing so will pay off.
Many developers working with software code will find one more very useful “tool” related to version control:
namely, two pairs of eyes inspecting the work, rather than just one, because developers working alone can
easily miss their own mistakes. This is why code reviewing is such a powerful technique when it comes to
improving the quality of your code. The problem with code reviewing is that it has often taken a lot of effort.
Fortunately, there are now excellent tools to support code review, and one of the best is Gerrit.
Gerrit’s two main advantages are that it integrates with Git perfectly and it’s completely web-based. Gerrit is
also the same code-review tool used for the Android Open Source Project. The basic idea with Gerrit is that a
developer pushes a change up the main repository. Before the change gets merged to the main branch, Gerrit
sends a notification to all project members that have “subscribed” for these changes, letting them know that there
is something new to review. Each reviewer can then compare the change with the previous commit and give the
change a ranking and a comment, indicating if something should be fixed or if it looks okay. If something needs
to be fixed, the original developer can push up another update that gets tracked by Gerrit. When everything looks
okay and is verified, the change can be pushed to the main branch and be available to all developers.
You can find out more about Gerrit and download the server at https://code.google.com/p/
When you’re working on a team with many developers, code reviewing with Gerrit is a great tool because
it supports a distributed review method. The reviewer doesn’t need to be located near the developer to ask
questions or give feedback but can do so directly in the tool. It might seem at first that this extra tool will add
unnecessary overhead to a project, but anyone who has been doing code reviewing on a regular basis knows
how much it improves the quality of the code. For an example of what the Gerrit tool looks like, see Figure 1-2.

22 Part I: Building a Better Foundation
Figure 1-2 The web interface for the Gerrit code-review tool
Mastering Your IDE
In May 2013 at the Google IO conference, Google announced a new IDE for Android named Android Studio.
This IDE is based on the open-source version of IntelliJ IDEA (Community Edition). The reason for switching
from Eclipse, which was the previously supported IDE, to IntelliJ IDEA was due to the complexity involved in
developing the Android plug-in for Eclipse. IntelliJ IDEA provided a far more superior platform for development
and allowed the Android tools team at Google to take the development experience to a new level as they could
integrate the Android tools into the IDE instead of simply providing a plug-in.
In this section, I cover three useful features that are supported by Android Studio: debugging, static code
analysis, and refactoring. Although these features have been available from both IntelliJ IDEA and Eclipse for
some time, I keep seeing many developers, both beginners and experienced developers, not using them to
their full extent. A developer who fully masters these features in his IDE will notice that he becomes much more
efficient in producing high-quality code.
Debugging Android Applications
Debugging capabilities give you fine-grained control over the execution of an application. You can set
breakpoints where execution will pause and inspect every aspect of the application state. This feature becomes
most useful when it comes to discovering the source of a bug or when you need to carefully inspect exactly
what happens during execution. The capability to debug Android applications is built into the IDEs, providing a
simple user interface for stepping through the code, inspecting variables, and even changing their values.

Chapter 1: Fine-Tuning Your Development Environment 23
You can debug Android applications on your device through the Android SDK. Your IDE will connect to the
debugging Service (adb) running on your device, which in turn connects to the Dalvik virtual machine
(VM) that your application is running. The procedure is basically the same one you follow when you run an
application from your IDE.
Figure 1-3 shows one of the sample applications from the Android SDK opened in Android Studio. As you can
see, I set a break point in the code and started the debugging from my IDE. The figure shows how the IDE looks
once the execution hits the breakpoint.
Figure 1-3 Breakpoint reached when debugging sample application in Android Studio
When a breakpoint is reached, you can inspect the state of the application at that specific point. All variables
accessible in that scope are listed in the debugger UI in the IDE. While debugging applications, you can change
the value of a variable in the current scope without having to restart the application and change the assignment
in the code, which is useful for testing how an application works depending on different input values. For
instance, if your application reads input from a sensor and you are unable to control the values from this sensor,
setting a breakpoint after data from the sensor has been read can be a powerful tool during development.
Android Studio contains a very powerful debugger tool that not only allows you to change the value of
variables but also to execute arbitrary code at the current scope, as shown in Figure 1-4. This capability is
especially helpful when you’re performing more advanced inspections that require the temporary injection of
several lines of code at the breakpoint.

24 Part I: Building a Better Foundation
Figure 1-4 Executing the code evaluation tool in Android Studio
Remember that using the debugger is not a substitute for writing tests for your application.
Static Code Analysis with lint
Even the best developers make mistakes in their code, and over the years different ways of dealing with this fact
have been developed. Writing unit tests has proven to be very effective and is something I highly recommend
to all developers. However, even with carefully written unit tests, it’s hard to cover all possible situations that
might occur in the code, which is why it’s important to complement unit testing with other methods@mdfor
instance, static code analysis. Fortunately, Google has added such a tool, called lint, to the Android SDK.
The lint tool performs checks on your project’s source files, both XML and Java, and searches for missing
elements, poorly structured code, unused variables, and more. In your IDE, the results appear as highlighted areas
(see Figure 1-5) indicating that something needs to be fixed. Hovering the cursor over these highlights shows you
more details and in some cases allows you to perform the “quick fix” command in order to correct the problem.

Chapter 1: Fine-Tuning Your Development Environment 25
Figure 1-5 Android Studio showing missing attributes highlighted in a XML layout file
Although it’s a very powerful tool, sometimes lint can indicate a warning in code that may be correct. A warning
could be about an unused method declaration or a missing recommended attribute in the manifest. In these
cases, the lint warnings may become irritating, especially if several developers are involved in a project. In that
case, it may be a good idea to actively suppress a warning for a specific part of the code to indicate that things
are okay, despite what lint thinks.
Suppressing lint warnings can be done for both Java and XML source files. For Java, you use the annotation @
SuppressLint with the warning you want to suppress as an argument, as shown in Figure 1-6.
In XML files, you include the lint namespace and add tools:ignore=”WarningName” (where
WarningName is the warning you want to suppress; see Figure 1-7) to the part where you want to suppress the
warning.
Remember that lint warnings are there for a purpose. They indicate areas that are potential bugs, so always
carefully consider whether you really want to suppress the warning. It’s often better to leave the warning in
place rather than remove it, as a reminder that it should be dealt with later.


26 Part I: Building a Better Foundation
Figure 1-6 Warning suppressed in Java source
Figure 1-7 Warning suppressed in XML source
Chapter 1: Fine-Tuning Your Development Environment 27
Refactoring Your Code
When you write code, you rarely get it perfect on the first try. You tend to change the structure and names of
methods, variables, and classes. When the number of classes grows in a project, you might move them into a
separate package. As you write more and more code, you suddenly realize that you have code that does the
same thing written in several different places with just minor differences.
Making changes in existing code can become a complicated process when that code is referenced in many
places. If you want to add another parameter to a method, you need to find all the places where the method
is used and update those. This can become a very complicated and error-prone process if done manually.
Fortunately, your IDE has a built-in function called Refactoring that makes this task simple and eliminates
the risk of introducing any bugs.
Many refactoring tasks are available in your IDEs. Refactoring involves simple things like renaming and moving
variables, methods, classes, and packages, as well as more complex operations such as changing the signature
of methods, encapsulating fields, replacing code duplicates, and replacing inheritance with delegation. I cover
some of the most common tasks in the following sections.
To use refactoring in Android Studio, place the cursor at the position in the code where you want to change
something and then select the refactoring task from the Refactor menu.
Extracting Constants
When you write code it is easy to ignore some best practices that we all know would benefit us in the long
run. A common example is when writing constant values in the code (that is, using the actual value instead
of a variable) instead of declaring a constant variable (a variable declared as public static final). The
problem is that once you decide to change the value, you need to find all the occurrences of that value and
replace it with the constant’s name. This is where the Extract Constant refactoring task comes in. As shown
in Figure 1-8, this task allows you to quickly and correctly replace all occurrences of that value with a newly
declared constant.
Changing the Method Signature
The method signature defines the access modifier (private, protected, package local or public),
return type, name, and parameters for a method. If you have a commonly used method where you want to
add an extra parameter, making the correct change in all places where the method is used in your project can
become complicated. Figure 1-9 shows how you can change all the parts of a method signature as well as all the
places where it’s used in your code.


28 Part I: Building a Better Foundation
Figure 1-8 Extracting a repeated value to a constant in Android Studio
Figure 1-9 Changing a method signature in Android Studio

Chapter 1: Fine-Tuning Your Development Environment 29
Extracting the Method from Code Block
It’s good practice to keep methods small to make code more readable and allow for more efficient reuse of
the code. When you see that a method is growing out of proportion, you can mark off a block in the code and
perform an Extract Method task as shown in Figure 1-10. After that, you can also perform the Change Method
Signature task to make the method more generic and reusable if needed.
Figure 1-10 Extracting a block of code to a separate method in Android Studio
There are many more refactoring options available in the IDE. I recommend that you become familiar with all of
these as they will make you a more productive developer. For more refactoring options in Android Studio, which
is based on IntelliJ IDEA, users can find a comprehensive guide to most of the refactoring tools at http://
www.jetbrains.com/idea/features/refactoring.html.
Developer Options on Android Devices
In the Settings application on your Android device, you can find the Developer Menu. Depending on which
version of Android you’re running, this can present different options. Also, some device manufacturers may add
their own settings in the Developer menu. In this section, I cover the most important details of the Developer
menu in Android 4.2 on a Nexus device.

30 Part I: Building a Better Foundation
Starting with Android 4.2, Google hides the Developer menu by default, purely for security reasons: Showing
the Developer menu could create some serious security issues if it’s enabled by mistake. Here’s how you enable
the Developer options on an Android device with version 4.2 or later:
1. Go to the Settings application.
2. Scroll down the list of options and tap the About Phone option, located at the bottom of the list.
3. Locate the row with the label Build Number and tap the Build Number option seven times.
A notification saying “You’re Now a Developer” appears, and the Developer Options menu now appears in
the Settings list.
Understanding Developer Settings
In the Developer Options menu (see Figure 1-11), you will find many choices that may be confusing at first.
Although they’re all useful in certain situations, I cover those that I believe are most useful for application
developers.
Figure 1-11 The Developer Options menu on a Nexus 4
device running Android 4 .2
Chapter 1: Fine-Tuning Your Development Environment 31
The first option you want to enable is Stay Awake, which causes your device to keep the screen on while it’s
charging—of course, the USB cable needs to be connected to your laptop. This way, you don’t have to unlock
your device whenever you want to deploy and run the application you’re developing, which saves a lot of
frustration.
A bit further down the list is the Debugging option, which contains a number of useful options that you need
to understand. The first option you want to enable is USB Debugging. Without this option, you won’t be able
to connect the device to your development environment using the adb tool. If you’ll be working with Google
Maps or the Location API, enable Allow Mock Locations too, so that you can test different location parameters
without having to travel all over the world.
Under Input are two settings (Show Touches and Pointer Location) that you’ll find useful when writing
applications that rely on advanced touch input, such as gestures and multi-touch interfaces.
The Drawing option contains several settings options that allow you to get visual feedback on how the user
interface is laid out and how fast and often a redraw occurs. You can also set scaling parameters for animations
and transitions as well as disable them completely for debugging purposes. One setting that is new with
Android 4.2 is the possibility to simulate a secondary screen. With the introduction of multiple displays in
Android 4.2, this feature makes it easy to develop multi-screen applications without having to connect your
device to a real secondary screen. Instead, the Android system will draw an overlay on top of the standard user
interface that simulates this second display.
Under Monitoring, you find some options that can prove invaluable for ensuring that your device runs
smoothly. Most developers are usually equipped with the latest version of high-end smartphones. Normal
users, however, may use older devices with less powerful CPUs and memory. An application that runs fine on
your high-end device can become sluggish and even encounter the dreaded Application Not Responding (ANR)
message if you’re not careful. The options under Monitoring in the Development Options menu can help you
spot these problems early on. By checking Strict Mode Enabled, the screen on your device will flash when you’re
performing a long operation on the main thread. Show CPU Usage is useful for tracking how much more the
CPU is working when your application is running, which you can use for comparison with other applications
on the same device to see if you’re doing better or worse than they are. Comparing the performance of your
application with other similar and popular apps is a good practice.
In the final section, named Apps, there are three options that are also useful for simulating the behavior
of devices with less CPU and memory. The Don’t Keep Activities option makes sure that your Activities are
restarted from scratch every time they’re launched. Normal behavior for Android is to keep Activities alive for
as long as possible so that they can be launched faster. The system will completely remove (that is, destroy)
Activities only when the device runs low on memory. By checking this option, you can simulate how your app
will behave on a device with much less available memory. You can further simulate this kind of behavior by
changing the Background Process Limit option, which forces background operations to stop much earlier.
Finally, checking Show All ANRs is recommended for all developers, because it will become much more obvious
when an application crashes in the background. Normally, ANRs aren’t shown unless the current foreground
application causes it to show.
32 Part I: Building a Better Foundation
Summary
In this chapter, I covered the details of the Android SDK, some of the hidden features of the adb tool, how to
stress test your application with the Monkey tool, how to use the ProGuard tool for obfuscating your code, and
how the new build system based on Gradle works. I continued with more details on how to setup an Android
Library Project or how to integrate a third-party library for your Android application.
Because the use of Git as a Source Code Management system for software development is quite widespread
today, I also described how you can combine Git with various Services in order to make it easier for a team to
work together.
The new IDE for developing Android applications, called Android Studio, contains a number of advanced
features that many developers have rarely used. By understanding and mastering the refactoring features in this
IDE, you can simplify complex tasks when you need to re-structure your code. It also helps to simplify existing
code without the risk of introducing new bugs.
Finally, I outlined some of the more important details about the developer options settings in Android. It’s
important to have a full understanding of how these work and how they can assist in development, debugging,
and testing. Just remember to switch them all off and test your application without them to ensure that
everything works as intended on a normal user’s device.
Developing software is more than simply writing code, regardless what kind of application or service you’re
developing. For Android, mastering the tools is as important as the quality of your code, because when the tools
are used to their fullest extent, the writing of the code becomes much easier and less error prone.
Further Resources
Books
Loeliger, Jon, and Matthew McCullough. Version Control with Git. O’Reilly Media, Inc., 2012.
Websites
Android development resources from the official Android Developer site: http://developer.
android.com
The Gradle build system: http://www.gradle.org
Chapter 2
Efficient Java Code
for Android
Today there are three versions of the Java platform, Java ME (Micro Edition, for certain mobile phones), Java SE
(Standard Edition, for desktops), and Java EE (Enterprise Edition, for server-side applications). When talking about Java
in general, I am usually referring to Java SE because this is the version that contains a virtual machine and a compiler.
Java code is compiled to an intermediate format called byte-code. This byte-code is then parsed by a virtual
machine on the target computer that can quickly translate it to the native format required for that particular
hardware and operating system.
Besides providing a “Write Once, Run Anywhere” advantage for developers, Java has automatic memory
management through a garbage collector (GC), reducing the need for you, as a developer, to de-allocate
memory from unused objects in your code. Although this feature is very useful and greatly reduces the risk of
introducing memory bugs in your code, because the garbage collection process needs to execute continuously,
it adds an overhead when running.
I start this chapter by doing a high-level comparison of the differences between Java SE and the Java used for
Android development. I focus on the Java SE language construct that you may be used to and how it works on
Android. Then I focus on how to optimize Java code for Android, how to optimize memory allocations, and how
to handle multithreading properly.
Comparing Android’s Dalvik Java to Java SE
Although developers were able to write applications for mobile devices using the Java programming language
long before Android, it was a severely limited version of Java called Java ME (Micro Edition). Java ME also
differed among different device manufacturers, making it almost impossible to write an application that would
work on any phone supporting Java ME. Also, the distribution of apps was very complicated because no well-
supported online stores existed at that time.
The launch of Android gave developers the option to build very capable applications for smartphones by
writing code using the Java programming language and using the same API they were used to in the standard
Java domain. However, although Android developers still use the compiler from Java SE to compile their
applications, you can find many differences between the Java that James Gosling developed and the way Java
works on your Android device.
The VM (virtual machine) that runs on an Android device is called Dalvik. It was originally developed by Dan
Bornstein at Google and provided a virtual machine suitable for CPU and memory-constrained devices. There
are several differences between Java SE and Dalvik Java, mostly regarding the virtual machine. Although Java
SE uses a stack machine design, Dalvik was designed as a register-based machine. The Android SDK has a tool
34 Part I: Building a Better Foundation
called dx that converts the Java SE stack machine byte-code to Dalvik register-based machine byte-code. The
conversion step is done automatically by your IDE so that you don’t need to bother about it.
The exact definition and technical difference between a stack-based machine and a register-based machine is
beyond the scope of this book. Android uses a register-based machine for historical reasons. Although a register-
based machine can be up to 32% faster than a stack-based machine, this is true only for virtual machines that are
interpreting the byte-code at execution (that is, interpreted virtual machines). Up until Android version 2.2 (also
known as Froyo), the Dalvik VM was purely interpreted. With the Froyo version of Android came the introduction of
a JIT compiler (Just In Time), something that Java SE had benefitted from for a long time.
JIT compilation, also known as dynamic translation, takes the byte-code and translates it into native code prior
to execution (see Figure 2-1), which has two major benefits. First, it eliminates much of the overhead associated
with pure interpreted VMs; second, it can perform optimizations to the native code that wouldn’t be possible
with statically compiled code. For instance, the JIT compiler may choose the most appropriate optimizations for
the CPU it is currently running. It’s also possible for a JIT compiler to analyze how the code is running to perform
further optimizations based on the application’s input.
Figure 2-1 Translation steps for Android Java and Java SE
Chapter 2: Efficient Java Code for Android 35
As promising as this sounds, Android’s Dalvik JIT compiler has a long journey ahead before it reaches the same
level of maturity as the JIT compiler in Java SE. Still, the presence of a JIT in Dalvik provides great performance
benefits for Android, and it’s continuously being improved.
Another difference between the Java SE VM and the Dalvik VM is that the latter is optimized for running in
multiple instances on the same machine. This is handled by a process started at boot called zygote that creates
the first Dalvik instance that will be the parent of all other instances. Once an application starts, the zygote
process receives a request for a new VM instance and forks a new process that is assigned to the newly started
application, as shown in Figure 2-2. This design may seem impractical if you’re used to working with Java SE,
but it has a major advantage because it protects you from multiple application crashes in cases where one
application has a runtime failure that will crash the Dalvik VM.
Figure 2-2 Launching of new Dalvik VM instances in Android
In addition to running with a different virtual machine than the one Java SE uses, Android has a different
implementation of the APIs. All the APIs in Android that belong to the java or javax packages come from
Apache Harmony, an open-source project aiming for reimplementation of the Java SE stack. (The Apache Harmony
project has been retired since November 2011 and is no longer being actively developed.) In terms of developing,
these APIs are identical to the ones that are found in Java SE, but some differences do exist. (For instance, Google
has made major upgrades to the HttpUrlConnection class that is not present in the Java SE version.)
Also, not all of the Java SE APIs are available on Android because they’re irrelevant for this platform. For instance, the
Swing/AWT packages have been completely removed because Android uses a different UI framework. Other APIs
that have been removed are RMI, CORBA, ImageIO, and JMX. These have either been replaced by an Android specific
version (in the android package space) or simply don’t have an equivalent in Android for practical reasons.
36 Part I: Building a Better Foundation
Optimizing Java Code for Android
Java SE has evolved over the years with new features that simplify writing complicated code structures. Many
of the features make it easier for developers, and you need to understand when and how to use them properly.
Also, because Java SE has been used mostly for server-side development (using the Java Enterprise Edition
APIs), Java code has been optimized to meet server-side requirements. Annotations and support for scripting
languages in the Java SE virtual machine are examples of optimizations focused on server-side development.
Although powerful tools when building your back end, these kinds of features serve little purpose and can even
be fatal when writing client-side code as done in an Android application. Java developers have gotten used to
unlimited amounts of RAM and CPU, whereas Android development requires close attention to performance
and allocations. Simply put, you need a slightly different approach when writing code for Android as compared
to developing back end solutions in Java.
However, some recommendations have changed since Android was first released. Some modern Java
constructs once avoided on Android are now recommended, mostly because of the modern JIT compiler for
Android that removes many of the performance bottlenecks these constructs used to cause.
This section deals with the aspects of Java code that you need to understand when writing Android
applications. While the details of the Java programming language are outside the scope of this book; instead,
I focus on what is important for Android development. Still, it’s important to understand that most of the rules
and recommendations that apply to Java SE apply to Android and the Dalvik VM.
Type-Safe Enum on Android
With Java SE 5.0 came many new features in the Java programming language that made life easier for Java
developers. One of the most anticipated features was the introduction of type-safe enumerations. Enumerations
are used to represent a number of choices in code that belong to a common group. In earlier versions of Java,
multiple integer constants were used to solve this. Although this works technically, it suffers from being quite
error-prone. Take a look at the following code:
public class Machine {
public static final int STOPPED = 10;
public static final int INITIALIZING = 20;
public static final int STARTING = 30;
public static final int RUNNING = 40;
public static final int STOPPING = 50;
public static final int CRASHED = 60;
private int mState;
public Machine() {
mState = STOPPED;
}
public int getState() {
return mState;
}
public void setState(int state) {
mState = state;
}
}
Chapter 2: Efficient Java Code for Android 37
The problem is that although the constants are the values you expect in the setter, nothing is preventing the
method setState() from receiving a different value. If you add a check in the setter, you need to handle the
error in case you get an unexpected value. What you want is a compile-time check that prevents you from ever
assigning an illegal value. Type-safe Java enum solves this problem, as shown here:
public class Machine {
public enum State {
STOPPED, INITIALIZING, STARTING, RUNNING, STOPPING, CRASHED
}
private State mState;
public Machine() {
mState = State.STOPPED;
}
public State getState() {
return mState;
}
public void setState(State state) {
mState = state;
}
}
Notice the new inner enum class added where you declare different states as type-safe values. This solves the
problem with unexpected values at compile time, so the code will be much less error-prone.
Before the Dalvik VM had a JIT compiler that optimized the code, using type-safe enum was discouraged on
Android because the memory and performance penalties associated with this design were greater than when
using integer constants. This is why so many integer constants are in the older parts of the Android APIs. These
days, with a capable JIT compiler and an ever-improving Dalvik VM, you don’t have to worry about that issue
and are encouraged to use type-safe enum in your application code.
However, there are still situations where integer constants are preferable. With basic types like the Java int, you
won’t increase the amount of work for the GC. Also, many existing APIs in the Android SDK still rely on basic
types as parameters—for example, the Handler class described in the “Multithreading on Android” section
later in this chapter—in these cases, you don’t have much choice.
Enhanced For-Loop on Android
Java SE 5.0 also introduced the enhanced for-loop that provides a generic an abbreviated expression for looping
over collections and arrays. First, compare the following five methods:
void loopOne(String[] names) {
int size = names.length;
for (int i = 0; i < size; i++) {
printName(names[i]);
}
}
38 Part I: Building a Better Foundation
void loopTwo(String[] names) {
for (String name : names) {
printName(name);
}
}
void loopThree(Collection<String> names) {
for (String name : names) {
printName(name);
}
}
void loopFour(Collection<String> names) {
Iterator<String> iterator = names.iterator();
while (iterator.hasNext()) {
printName(iterator.next());
}
}
// Avoid using enhanced for-loops for ArrayList
void loopFive(ArrayList<String> names) {
int size = names.size();
for (int i = 0; i < size; i++) {
printName(names.get(i));
}
}
These methods show four different ways of looping through collections and arrays. The first two methods have
the same performance, so it’s safe to use the enhanced for-loop on arrays if you’re just going to read the entries.
For Collection objects, you get the same performance when using the enhanced for-loop as when you
manually retrieve an Iterator for traversal. The only time you should do a manual for-loop is when you have
an ArrayList object.
In the cases where you not only need the value of each entry but also the position, be sure to use either an array
or an ArrayList because all other Collection classes are much slower in these situations.
In general, if you need high-quality performance when reading sets of data that rarely change, use a regular
array. However, arrays have a fixed size and will affect performance when adding data, so consider all factors
when writing your code.
Queues, Synchronization, and Locks
Frequently, an application will produce data in one thread and consume them in another. A common example
is when you’re reading data from the network on one thread and want to display the data to the user on a
different thread (the main thread where UI operations occur). This pattern is usually called the consumer/
producer pattern, and in their object-oriented programming courses, programmers may spend several hours
implementing this in their algorithm. In this section, I’ll show some of the ready-made classes that make it easier
to implement this behavior.
Chapter 2: Efficient Java Code for Android 39
Smarter Queues
Many Java developers still choose to implement queues in their code using LinkedList and
synchronized blocks, although there are ready-made classes that do so and require much less code. You
can find the classes for performing concurrent programming in the java.util.concurrent package. In
addition, you can find classes for semaphores, locks, and atomic operations on single variables. Consider the
following code where a thread-safe queue using a standard LinkedList is implemented:
public class ThreadSafeQueue {
private LinkedList<String> mList = new LinkedList<String>();
private final Object mLock = new Object();
public void offer(String value) {
synchronized (mLock) {
mList.offer(value);
mLock.notifyAll();
}
}
public synchronized String poll() {
synchronized (mLock) {
while(mList.isEmpty()) {
try {
mLock.wait();
} catch (InterruptedException e) {
// Ignore for brevity
}
}
return mList.poll();
}
}
}
Although this code is correct and would probably merit a full score on an exam, it’s simply a waste of your time
to implement and test it. Instead, you can replace all the preceding code with the following line:
LinkedBlockingQueue<String> blockingQueue =
new LinkedBlockingQueue<String>();
This one line gives you the same type of blocking queue as the previous example and even provides additional
thread-safe operations. The java.util.concurrent package has a number of alternative queues and
deuce classes as well as concurrent map classes, so in general, I suggest using them rather than using lengthier
code similar to my earlier example.
Smarter Locks
The synchronized keyword in Java provides a powerful feature that allows you to make a method
or call-block thread safe. Although easy to use, it is also easy to apply it too widely, which can have very
negative impact on performance. When you need to differentiate between reading and writing data, the
synchronized keyword is not the most efficient. Luckily, a utility class in the java.util.concurrent.
locks package provides exactly that support.
40 Part I: Building a Better Foundation
public class ReadWriteLockDemo {
private final ReentrantReadWriteLock mLock;
private String mName;
private int mAge;
private String mAddress;
public ReadWriteLockDemo() {
mLock = new ReentrantReadWriteLock();
}
public void setPersonData(String name, int age, String address) {
ReentrantReadWriteLock.WriteLock writeLock = mLock.writeLock();
try {
writeLock.lock();
mName = name;
mAge = age;
mAddress = address;
} finally {
writeLock.unlock();
}
}
public String getName() {
ReentrantReadWriteLock.ReadLock readLock = mLock.readLock();
try {
readLock.lock();
return mName;
} finally {
readLock.unlock();
}
}
// Repeated for mAge and mAddress…
}
The preceding code exemplifies where to use a ReentrantReadWriteLock that allows read-only access
from multiple concurrent threads while making sure that only one thread at a time can write to the same data.
Using synchronized in your code is still a valid way of handling locks, but always consider whether a
ReentrantReadWriteLock could be a more efficient solution.
Memory Management and Allocations
The automatic memory management in Java has effectively eliminated many of the most common bugs in
software development. When you no longer have to remember to release every allocation of a new object in
your code, you save time that you can use to improve the features and overall quality of software.
But this feature doesn’t come for free because you now have an automatic garbage collector that runs in
parallel with your application. The GC will run continuously and check whether any memory allocations can be
reclaimed. This behavior means that the threads in your application will compete for CPU time with the GC, so
it’s crucial to make sure that GC calls don’t take too long whenever it is running.
Chapter 2: Efficient Java Code for Android 41
Also, automatic memory management does not remove the possibility for memory leaks. If you keep references
to objects that are no longer needed, the GC will not collect them, and they will waste memory. If objects
are being allocated continuously but are never being released, you’ll eventually run into an OutOfMemory
exception, and your application will crash. So, try to avoid keeping references to objects in the main Android
components; otherwise, they may never be “garbage collected” during the application’s lifetime.
Reducing Object Allocations
On Java and Android, the most common problem with automatic memory management is when you are
allocating unnecessary objects that keep the GC working more than it should. Consider a case in which a simple
class represents a pair of integers:
public final class Pair {
public int firstValue;
public int secondValue;
public Pair(int firstValue, int secondValue) {
this.firstValue = firstValue;
this.secondValue = secondValue;
}
}
Now, say that you receive an array of integers in your application that you divide into pairs and then send to the
method sendPair. Here is an example of when memory allocation is done badly:
public void badObjectAllocationExample(int[] pairs) {
if(pairs.length % 2 != 0) {
throw new IllegalArgumentException(“Bad array size!”);
}
for(int i = 0; i < pairs.length; i+=2) {
Pair pair = new Pair(pairs[i], pairs[i+1]);
sendPair(pair);
}
}
Although this is a very crude example of how to generate Pair objects (and potentially cause a crash if the
length of the array is not an even size), it demonstrates a surprisingly common mistake: allocating objects
inside a loop. The GC will have a lot of work to do inside the previous loop above and will most likely cause the
application UI to stutter from CPU exhaustion. If you know that the sendPair method won’t keep a reference
to the Pair object after it returns, your solution is simply to move the creation of the Pair object outside the
loop and reuse the object, as shown as follows:
public void betterObjectAllocationExample(int[] pairs) {
if(pairs.length % 2 != 0) {
throw new IllegalArgumentException (“Bad array size!”);
}
Point thePair = new Point(0,0);
for (int i = 0; i < pairs.length; i+=2) {
thePair.set(pairs [i], pairs [i+1]);
sendPair(thePair);
}
}
42 Part I: Building a Better Foundation
In this new version of the method, you ensure that the object is reused during the entire run of the method.
There will be only one GC call once the method returns. Remember, when allocating objects, avoid doing so
inside a loop when possible.
Sometimes, however, you can’t avoid creating objects inside a loop, so you also need a way of handling those
situations. The solution here is to allocate objects on demand using a static factory method. (Joshua Bloch
describes this method in detail in Item 1 of his book Effective Java. )
This approach is commonly used in the Android framework and APIs and allows you to use a behind-the-scenes
object cache that is populated on demand. The only drawback is that you need to manually recycle the objects,
or the cache will always be empty.
Based on your previous example, you start by refactoring the Pair class so that you have a simple pool for
reusing objects.
public final class Pair {
public int firstValue;
public int secondValue;
// Reference to next object in the pool
private Pair next;
// The lock used for synchronization
private static final Object sPoolSync = new Object();
// The first available object in the pool
private static Pair sPool;
private static int sPoolSize = 0;
private static final int MAX_POOL_SIZE = 50;
/**
* Only allow new objects from obtain()
*/
private Pair() { }
/**
* Return recycled object or new if pool is empty
*/
public static Pair obtain() {
synchronized (sPoolSync) {
if (sPool != null) {
Pair m = sPool;
sPool = m.next;
m.next = null;
sPoolSize--;
return m;
}
}
return new Pair();
}
Chapter 2: Efficient Java Code for Android 43
/**
* Recycle this object. You must release all references to
* this instance after calling this method.
*/
public void recycle() {
synchronized (sPoolSync) {
if (sPoolSize < MAX_POOL_SIZE) {
next = sPool;
sPool = this;
sPoolSize++;
}
}
}
}
Note that a number of fields are added, both static and non-static. You use these fields to implement a
traditional linked list of Pair objects. Objects of this class are created only through the obtain method.
You prevent new objects from outside this class by making the constructor private. The obtain method first
checks whether the pool contains any existing objects and removes the first element in the list and returns it. If
the pool is empty, it simply creates a new object. To put the object back into the pool, you call recycle once
you’re done. At that point, it is very important that you don’t touch that object again.
With this modification of the Pair class, your previous method with the loop also needs some changes.
public void bestObjectAllocationExample(int[] pairs) {
if(pairs.length % 2 != 0) throw new IllegalArgumentException (“Bad
array size!”);
for (int i = 0; i < pairs.length; i+=2) {
Pair pair = Pair.obtain();
pair.firstValue = pairs[i];
pair.secondValue = pairs[i+1];
sendPair(pair);
pair.recycle();
}
}
The first time this method runs, you create a new instance of Pair, which will then be reused for every new
iteration. However, the next time you run this method, no new object is created. Also, because the obtain
and recycle methods are thread-safe, this method is safe to execute in multiple concurrent threads. The only
drawback is that you have to remember to call recycle manually, but this is a small price to pay considering
you’ve postponed all GC calls for the Pair class until the application exits.
The example with the Pair class is very trivial, but it illustrates a pattern that is highly encouraging if you have
a class that would otherwise be created frequently in your code. This design may look familiar because it’s in
several places in the Android source code and APIs. Commonly used classes such as Message, MotionEvent,
and Parcel all implement this pattern in order to reduce unnecessary GC calls. The example with the
preceding Pair class is basically a copy of the Message class implementation. When using this approach,
remember to call recycle once you’re done with an object that implements this, or the pool will be empty all
the time.
44 Part I: Building a Better Foundation
Multithreading on Android
One of the most difficult parts of programming is when you have to write code that executes on multiple
threads. It’s a requirement for modern applications because you can’t have everything executing in a serial
order on one single thread. An Android application starts with a thread called main, also known as the UI thread
(in this book, I use main and UI thread interchangeably). Unless you start another thread or implicitly call a
function that starts a new thread, everything you do in an Android application will execute on the main thread.
This means that if your code performs an operation on the main thread (say, running code in the onResume
method) that will take a significant amount of time, all drawing and input events will be blocked until that
operation is completed. So, the first thing to remember when you start writing your application code: Make sure
that any code you execute won’t ever block the main thread.
But how do you know if a method is executing on the main thread? The official Android documentation
states: “By default, all components of the same application run in the same process and thread (called the ‘main’
thread)." More specifically, all the callbacks (basically, all the onX methods) in the Android components
(Activity, BroadcastReceiver, Service, and Application) are executed on the same thread. The
onStartCommand method of a Service is thus running on the same thread as the onResume of your
Activity. Remember this when you design your code because blocking one of these methods will cause the
system to “kill” your application.
The main thread in Android will run as long as your application’s process is alive. It is kept alive during the
application life cycle by the Looper class. This class creates a loop inside the current thread that queries a
message queue (using the MessageQueue class). The query to this queue will block until a new message has
arrived, which ensures that the thread sleeps when there’s nothing to do. All execution on the main thread is
done by sending messages to this queue, either directly through a Handler object or indirectly through some
part of the Android API (for instance, the runOnUiThread method). You can retrieve the Looper for the main
thread of your application through Context.getMainLooper().
What is safe to execute on the main thread and what should be moved to a different thread? To be very strict,
only the methods that must be executed on the main thread should be executed there. Everything else should
go on a separate thread. For practical reasons, you can bend this rule in some cases where the operation
you perform will never take a long time. If you make sure that any file, database, or network operations are
performed on a separate thread, you are usually safe. Also, for certain applications and games, you will perform
calculations at regular intervals that don’t directly have anything to do with the UI, and these should also
execute on a separate thread. However, it’s also important to ensure that you don’t have too many threads
running at the same time because a performance penalty is involved when the CPU switches from one thread
to another. In later chapters in this book, I give more specifics on when and when not to put your code on a
separate thread.
How do you declare and manage your threads when writing Android code? In the following section I show you
several ways to spawn new threads, and I explain each of these methods in detail, including their pros and cons.
Thread
This is the base class for all threads in Android. It is the same class as found in Java SE, and it behaves the same
way. If you want to execute something inside a thread, you can either make a specialization (that is, a new class
that extends Thread) or create a class implementing the Runnable interface that you pass to the constructor
of Thread. This example uses the latter option.
Chapter 2: Efficient Java Code for Android 45
In this example, you need to iterate over an array of Objects in order to “upload” data to a server (the actual
code for uploading is not part of this example). You need to execute this operation on a separate thread;
otherwise, it will block the user interface. Also, the operation needs to update its progress by increasing a
ProgressBar. The following code shows an implementation of Runnable that resolves this issue:
public class MyThread implements Runnable {
private Object[] mInput;
private Activity mActivity;
private int mProgress = 0;
public MyThread(Activity activity, Object ... input) {
mActivity = activity;
mInput = input;
}
@Override
public void run() {
mProgress = 0;
Runnable runnable = new Runnable() {
public void run() {
mActivity.findViewById(R.id.progressBar).
setVisibility(View.VISIBLE);
((ProgressBar) mActivity.
findViewById(R.id.progressBar)).setProgress(0);
}
};
mActivity.runOnUiThread(runnable);
// Loop through and process mInput
for (Object input : mInput) {
// Post the input to a server (fake it with a sleep)
SystemClock.sleep(50);
runnable = new Runnable() {
public void run() {
((ProgressBar) mActivity.
findViewById(R.id.progressBar)).
setMax(++mProgress);
((ProgressBar) mActivity.
findViewById(R.id.progressBar)).
setProgress(mInput.length);
}
};
mActivity.runOnUiThread(runnable);
}
runnable = new Runnable() {
public void run() {
mActivity.findViewById(R.id.progressBar).
setVisibility(View.INVISIBLE);
}
)
46 Part I: Building a Better Foundation
};
mActivity.runOnUiThread(runnable);
}
}
As you can see in the preceding example, you need to create a new Runnable every time you want to update
the UI. This makes the code messy and will also cause unnecessary object allocations that need to be garbage
collected, which is always a bad thing. The Runnable is needed in order to post UI updates back to the main
thread through the runOnUiThread method.
There’s another problem with this solution: Because you can call start on an instance of Thread only once,
you must create a new Thread object every time you need to perform this operation. A new thread is an
expensive thing to create again and again, so there is definitively room for improvement here. All together, this
is not a very flexible method, and I discourage the direct use of the Thread class.
AsyncTask
This class is probably one of the more popular classes in Android because it is so simple to use. It allows you
to define a task that will run on its own thread and provide callbacks for the different stages of the task. The
callbacks are also designed to remove the need for using the runOnUiThread method to update the UI while
it’s running, which makes it very appropriate for indicating the progress of a long-running operation. Here is an
AsyncTask that does the same thing as in the Thread example:
public class MyAsyncTask extends AsyncTask<String, Integer, Integer> {
private Activity mActivity;
public MyAsyncTask(Activity activity) {
mActivity = activity;
}
@Override
protected void onPreExecute() {
super.onPreExecute();
// This will run on the main thread
mActivity.findViewById(R.id.progressBar).
setVisibility(View.VISIBLE);
((ProgressBar) mActivity.findViewById(R.id.progressBar)).
setProgress(0);
}
@Override
protected Integer doInBackground(String... inputs) {
// This will run NOT run on the main thread
int progress = 0;
for (String input : inputs) {
// Post the input to a server (fake it with a sleep)
SystemClock.sleep(50);
publishProgress(++progress, inputs.length);
}
Chapter 2: Efficient Java Code for Android 47
return progress;
}
@Override
protected void onProgressUpdate(Integer... values) {
// This will run on the main thread
((ProgressBar) mActivity.findViewById(R.id.progressBar)).
setMax(values[1]);
((ProgressBar) mActivity.findViewById(R.id.progressBar)).
setProgress(values[0]);
}
@Override
protected void onPostExecute(Integer i) {
super.onPostExecute(i);
// This will run on the main thread
mActivity.findViewById(R.id.progressBar).
setVisibility(View.INVISIBLE);
}
}
In the preceding example, you see the implementation of four callbacks with a comment regarding which
thread they will execute on. As you can see, onPreExecute, onProgressUpdate, and onPostExecute
are all executed on the main thread, so it is safe to update the UI from these. publishProgress is also called
for each input to trigger the onProgressUpdate callback so that you can update a progress bar.
This class makes it much easier to perform long-running operations on a different thread and still be able to
communicate easily with the main thread when needed. The only problem with AsyncTask is that you can
use each instance of this class only once, which means that you have to call new MyAsyncTask() every time
you want to perform this operation. Although this class is not a heavyweight—the actual thread is managed
by an ExecutorService behind the scenes—it is not suitable for operations that you perform frequently
because you would quickly gather up objects that need to be garbage collected and eventually cause your
application’s UI to stutter.
In addition, you cannot schedule the time for the execution of this operation or perform the operation at a
certain interval. The AsyncTask class is suitable for things like file downloads or similar situations that will
happen relatively infrequently or by user interaction. Nevertheless, because it’s so easy to implement, this is
likely to be the class you will use at first in your application.
Handler
When you need a more fine-grained control for executing operations on a separate thread, you have a great
utility at your disposal in the Handler class. This class allows you to schedule operations with exact precision,
and you can reuse it as many times as you want. The thread that executes the operations loops until you
explicitly terminate it; the class Looper takes care of this behind the scenes. You will rarely need to set up your
own Looper ; instead, you can create it through the wrapper called HandlerThread. The following example
shows how to create a new Handler in your Activity.
48 Part I: Building a Better Foundation
public class SampleActivity extends Activity implements Handler.Callback
{
private Handler mHandler;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// Start a new thread with a Looper
HandlerThread handlerThread
= new HandlerThread(“BackgroundThread”);
handlerThread.start();
// Create your new Handler
mHandler = new Handler(handlerThread.getLooper(), this);
}
@Override
protected void onDestroy() {
super.onDestroy();
// Shut down the Looper thread
mHandler.getLooper().quit();
}
@Override
public boolean handleMessage(Message message) {
// Process incoming messages here...
// Recycle your message object
message.recycle();
return true;
}
}
With your new Handler object, you can now safely schedule operations with exact precision. The usual way
of working with a Handler is by sending Message objects, which are simple, cheap, and reusable objects
for passing data and arguments to your background thread. A Message object is usually defined by its public
integer field name what that works as a flag that can be used in a switch-case statement in the callback
handleMessage. There are also two integer fields named arg1 and arg2 that are suitable for low-cost
arguments, as well as a field name obj for storing a single arbitrary object reference. If needed, you can also
add a set of more complex data using the setData method with a standard Bundle object. You can send your
messages to the handler using a number of methods. The three most common ones are demonstrated here:
public void sendMessageDemo(Object data) {
// Create a new Message with data as a parameter
// and send it for execution on the handler immediately
Message.obtain(mHandler, SYNC_DATA, data).sendToTarget();
// Send a simple empty message on your handler immediately
mHandler.sendEmptyMessage(SYNC_DATA);
// Send a simple empty message to be executed 30 seconds from now
mHandler.sendEmptyMessageAtTime(SYNC_DATA,
THIRTY_SECONDS_IN_MILLISECONDS);
Chapter 2: Efficient Java Code for Android 49
// Send a message with both arguments fields and
// the obj set to be executed in two minutes.
int recipient = getRecipientId();
int priority = 5;
Message msg = mHandler.obtainMessage(SYNC_DATA, recipient,
priority, data);
mHandler.sendMessageDelayed(msg, TWO_MINUTES_IN_MILLISECONDS);
}
The first two examples show that you can create and send messages through both the Message class and the
Handler object. In the third and fourth example, you see how to schedule the message for processing with
millisecond precision.
When the Message is processed from the message queue, it will be sent, on the looping thread, to the callback
you’ve implemented. You can use the same callback for multiple Handler objects, which makes it useful as a
proxy-like method for dealing with the messages in your application. You can even share the callback between
Activities and Services. The most optimal way of implementing your callback is by keeping all the
constants representing the what value of a Message in the same class that implements the callback and then
use a standard switch-case statement to handle each message type. In the preceding example, I implemented
the callback on the Activity, but it can often be useful to have a separate class for this that you pass your
application’s Context to so that it can be used in all parts of your application. Here is an example of a typical
callback:
// Constants used for the what field in a Message
public static final int SYNC_DATA = 10;
public static final int PING_SERVER = 20;
@Override
public boolean handleMessage(Message message) {
switch (message.what) {
case SYNC_DATA:
// Perform long-running network I/O operation
syncDataWithServer(message.obj);
break;
case PING_SERVER:
// Ping your server. This should be called at regular intervals
pingServer();
break;
}
// Recycle your message object to save memory
message.recycle();
return true;
}
The handleMessage callback in this example has only two operations implemented, SYNC_DATA and
PING_SERVER. The first one will probably be triggered by a user event—for example, when a file is saved or
new data is ready to be posted to a server. The second one is supposed to execute at regular intervals. However,
there is no method on the Handler class for sending messages at an interval, so you need to implement that
behavior.
50 Part I: Building a Better Foundation