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

Introduction. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1

Who This Book Is For . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1

What This Book Covers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2

How This Book Is Structured . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2

What You Need to Use This Book . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .5

Source Code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .5

Errata . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .5

Part I Building a Better Foundation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7

Chapter 1 Fine-Tuning Your Development Environment .. . . . . . . . . . . . . . . . . . 9

Operating Systems for Android Development . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .9

Advanced Android SDK Tools . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .9

The adb Tool . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10

Stress-Testing an Application’s UI with Monkey . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13

The Gradle Build System for Android . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14

Optimize and Obfuscate with ProGuard . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17

Android Library Projects and Third-Party Libraries . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .17

Precompiled JAR Libraries . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18

Setting Up a Library Project . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18

Version Control and Source Code Management . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .19

Mastering Your IDE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .22

Debugging Android Applications . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22

Static Code Analysis with lint . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24

Refactoring Your Code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27

Developer Options on Android Devices . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .29

Understanding Developer Settings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30

Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .32

Further Resources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .32

Books . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32

Websites . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32

viii Contents

Chapter 2 Efficient Java Code for Android .. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33

Comparing Android’s Dalvik Java to Java SE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .33

Optimizing Java Code for Android . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .36

Type-Safe Enum on Android . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36

Enhanced For-Loop on Android . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37

Queues, Synchronization, and Locks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38

Memory Management and Allocations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .40

Reducing Object Allocations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41

Multithreading on Android . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .44

Thread . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44

AsyncTask . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46

Handler . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47

Picking the Right Solution for Threads . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52

Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .52

Further Resources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .53

Documentation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53

Books . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53

Online Sources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53

Part II Getting the Most Out of Components . . . . . . . . . . . . . . . . . . . . . . . . . . 55

Chapter 3 Components, Manifests, and Resources . . . . . . . . . . . . . . . . . . . . . . . 57

Android Components . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .57

The Activity Component . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58

The Service Component . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58

The BroadcastReceiver Component . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58

The ContentProvider Component . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59

The Application Component . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59

Application Architecture . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61

The Android Application Manifest . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .62

The Manifest Element . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62

Google Play Filters and Permissions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 64

The Application Element . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65

Component Elements and Attributes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 66

Intent Filtering . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68

Resources and Assets. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .69

Advanced String Resources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 70

Localization . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71

Using Resource Qualifiers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72

Using Assets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74

Contents ix

Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .74

Further Resources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .75

Documentation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75

Chapter 4 Android User Experience and Interface Design .. . . . . . . . . . . . . . . . 77

User Stories . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .77

Understanding the User with Personas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 78

Android UI Design . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .79

Navigation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79

Prototyping User Interfaces . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79

Android UI Elements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .81

Text in Android Applications . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .81

Font Matters . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81

Text Layout . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 82

Dimensions and Sizes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .82

Recommended Dimensions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 83

Icon Sizes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 83

Text Size . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84

Colors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .84

Color Blindness . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 85

Images and Icons . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .85

Canonical Perspective . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 86

Geons . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 86

Recognizing Faces . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87

Usability . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .87

Visual Cues . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 88

Rewarding the User . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .88

Gamification . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 89

Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .90

Further Resources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .91

Books . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 91

Websites . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 91

Chapter 5 Android User Interface Operations . . . . . . . . . . . . . . . . . . . . . . . . . . . . 93

Activities and Fragments . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .93

Using Multiple Screens . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .95

Designing Custom Views . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .97

View Life Cycle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 97

Piano Keyboard Widget . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 98

x Contents

Multi-Touching . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103

PointerCoordinates . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 106

Rotate Gesture . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 106

OpenGL ES . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 108

Scene Graphs and Graphics Engines . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 109

Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 109

Further Resources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 110

Books . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 110

Websites . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 110

Chapter 6 Services and Background Tasks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 111

When and How to Use a Service . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 111

Service Types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 112

Understanding the Service Lifecycle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 112

Service Creation and Destruction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 112

Starting Services . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 113

Binding Services . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 114

Staying Alive . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 116

Stopping Services . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 117

Running in the Background . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 120

IntentService . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 120

Parallel Execution . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 121

Communicating with Services . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 123

Asynchronous Messaging with Intents . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 123

Locally Bound Services . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 125

Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 128

Further Resources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 129

Blog . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 129

Chapter 7 Android IPC . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 131

The Binder Explained . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 131

Binder Address . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 132

Binder Transactions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 133

Parcel . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 134

Link to Death . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 136

Designing APIs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 137

AIDL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 137

Messenger . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 142

Wrapping APIs with Library Projects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 145

Contents xi

Securing Remote APIs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 148

Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 149

Further Resources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 149

Websites . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 149

Chapter 8 Mastering BroadcastReceivers and Configuration Changes .. . . 151

BroadcastReceivers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 152

Local BroadcastReceivers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 153

Normal and Ordered Broadcasts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 154

Sticky Broadcasts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 156

Directed Broadcasts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 157

Enabling and Disabling Receivers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 157

System Broadcast Intents . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 158

Device Configuration Changes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 162

Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 163

Further Resources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 163

Documentation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 163

Chapter 9 Data Storage and Serialization Techniques . . . . . . . . . . . . . . . . . . . 165

Persistence Options for Android . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 165

Storing Data in Preference Files . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 166

User Options and Settings UI . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 169

High-Performance ContentProviders . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 171

Android Database Design . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 171

Creating and Upgrading Databases . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 172

Implementing Query Methods . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 174

Database Transactions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 176

Storing Binary Data in ContentProvider . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 177

Serializing Data for Persistence . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 179

JavaScript Object Notation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 179

Advanced JSON Handling with Gson . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 181

Google Protocol Buffers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 184

Application Data Backup . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 187

Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 188

Further Resources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 188

Documentation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 188

Websites . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 189

xii Contents

Chapter 10 Writing Automated Tests .. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 191

Android Testing Principles . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 191

What to Test . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 192

Basic Unit Testing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 192

Testing Activities . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 194

Testing Services . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 196

Testing ContentProviders . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 198

Running Tests . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 201

Continuous Integration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 202

Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 203

Further Resources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 203

Android Testing Guidelines . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 203

Books . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 203

Websites . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 203

Part III Pushing the Limits . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .205

Chapter 11 Advanced Audio, Video, and Camera Applications. . . . . . . . . . 207

Advanced Audio Applications . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 207

Low-Latency Audio . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 207

OpenSL ES for Android . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 210

Text-to-Speech (TTS) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 214

Speech Recognition . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 216

Video Processing with OpenGL ES 2.0 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 218

Camera Processing with OpenGL ES 2.0 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 222

Encoding Media . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 224

Recording an OpenGL Scene . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 224

Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 229

Further Resources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 229

Documentation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 229

Chapter 12 Secure Android Applications . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 231

Android Security Concepts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 231

Signatures and Keys . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 231

Android Permissions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 232

Protecting User Data . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 233

Verifying Calling Applications . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 234

Contents xiii

Client-Side Data Encryption . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 235

Android Crypto API . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 236

Generating a Key . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 236

Encrypting Data . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 236

Decrypting Data . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 237

Working with Encrypted Data . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 237

Android Key Chain Management . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 239

Device Management API . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 244

Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 247

Further Resources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 247

Books . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 247

Documentation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 248

Websites . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 248

Chapter 13 Maps, Location, and Activity APIs. . . . . . . . . . . . . . . . . . . . . . . . . . . 249

Fused Location Manager . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 249

Google Maps v2 Integration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 250

Working with Google Maps . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 253

Markers on Maps . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 254

Drawing Circles . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 255

Drawing Polygons . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 256

Useful Location API Utilities . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 257

Geocoding . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 258

Using the LocationClient . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 258

Geofencing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 260

Activity Recognition . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 262

Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 265

Further Resources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 265

Documentation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 265

Websites . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 265

Chapter 14 Native Code and JNI .. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 267

A Note on CPU Architecture . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 267

Writing Android Applications in C . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 268

Android NDK Build Scripts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 268

Native Activities . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 269

Working with JNI . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 270

Calling Native Functions from Java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 271

Calling a Java Method from Native . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 273

xiv Contents

Android Native APIs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 276

The C Library . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 276

Native Android Logging . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 277

Native OpenGL ES 2 .0 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 277

Native Audio with OpenSL ES . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 277

Porting a Native Library to Android . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 278

Building a Native Library . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 278

Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 284

Further Resources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 285

Android Developers Site . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 285

Oracle Websites . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 285

Chapter 15 The Hidden Android APIs .. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 287

Official and Hidden APIs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 287

Discovering Hidden APIs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 288

Safely Calling Hidden APIs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 290

Extracting Hidden APIs from a Device . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 291

Calling Hidden APIs Using Reflections . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 293

Examples of Hidden APIs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 294

Receiving and Reading SMS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 294

Wi-Fi Tethering . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 296

Hidden Settings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 297

Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 298

Further Resources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 298

Websites . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 298

Chapter 16 Hacking the Android Platform. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 299

Unlocking Your Device . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 300

Flashing Factory Images . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 301

Unlocking Non-Google Nexus Devices . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 302

Community-Supported Firmwares . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 302

The Android Source Code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 302

Setting Up the Build Environment . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 303

Building and Flashing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 303

Writing System Applications . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 305

Platform Certificates . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 305

Writing Signature-Signed Applications . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 306

Contents xv

Hacking the Android Platform . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 308

Setting Up Your IDE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 308

Android Projects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 309

Android Linux Kernel . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 310

Adding a System Service . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 310

Speeding Up the Platform Development Cycle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 314

Contributing to AOSP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 315

Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 317

Further Resources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 317

Websites . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 317

Chapter 17 Networking, Web Service, and Remote APIs .. . . . . . . . . . . . . . . . 319

Android Networking . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 319

HttpUrlConnection . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 320

Volley . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 324

OkHttp and SPDY . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 326

Web Sockets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 327

Integrating Web Services . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 331

Google Static Maps v2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 331

Foursquare API Using OAuth2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 332

Facebook SDK for Android . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 337

Finding Online Web Services and APIs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 341

Network and Power Consumption . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 342

General Guidelines . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 343

Power Efficient Network Polling . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 343

Server-Side Push . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 344

Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 347

Further Resources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 347

Documentation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 347

Websites . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 347

Chapter 18 Communicating with Remote Devices. . . . . . . . . . . . . . . . . . . . . . 349

Android’s Connectivity Technologies . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 349

Android USB . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 350

Bluetooth Low Energy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 352

Android Wi-Fi . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 356

Network Service Discovery . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 356

WiFi Direct . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 357

xvi Contents

On-Device Web Services . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 361

RESTful with Restlet . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 362

Web Socket Server . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 365

Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 367

Further Resources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 368

Websites . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 368

Chapter 19 Google Play Services. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 369

Authorization . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 369

Google Drive Application Data . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 372

Google Cloud Endpoints . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 376

Google Cloud Messaging . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 379

GCM Client . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 379

Google Play Game Services . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 383

Data Messaging . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 386

Messaging Strategy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 386

Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 388

Further Resources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 388

Websites . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 388

Chapter 20 Distributing Applications on Google Play Store .. . . . . . . . . . . . . 389

In-app Billing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 390

Consuming Products . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 392

In-app Subscriptions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 393

Ads in Android Applications . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 393

Targeting Ads . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 395

Ad Colors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 396

Interstitial Ads . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 396

Application Licensing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 397

APK Expansion Files . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 398

Creating Expansion Files . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 399

Downloading Expansion Files . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 399

Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 401

Further Resources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 401

Websites . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 401

Index .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .403

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/

ptl/androidprogramming.

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/

tools/help/adb.html.

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/

qi.html.

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/

gerrit.

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