Colophon

Android for iOS Developers: Java™ Edition 2018

ISBN: 978-3-906926-11-7

© Copyright 2016-2018 by Adrian Kosmaczewski – All Rights Reserved.

logo

AKOSMA Training Adrian Kosmaczewski

Ringkengässchen 11 – 8200 Schaffhausen – Switzerland

This document is geared towards providing exact and reliable information in regards to the topic and issue covered. The publication is sold with the idea that the publisher is not required to render accounting, officially permitted, or otherwise, qualified services. If advice is necessary, legal or professional, a practiced individual in the profession should be ordered.

In no way is it legal to reproduce, duplicate, or transmit any part of this document in either electronic means or in printed format. Recording of this publication is strictly prohibited and any storage of this document is not allowed unless with written permission from the publisher. All rights reserved.

The information provided herein is stated to be truthful and consistent, in that any liability, in terms of inattention or otherwise, by any usage or abuse of any policies, processes, or directions contained within is the solitary and utter responsibility of the recipient reader. Under no circumstances will any legal responsibility or blame gbe held against the publisher for any reparation, damages, or monetary loss due to the information herein, either directly or indirectly.

Respective authors own all copyrights not held by the publisher.

The information herein is offered for informational purposes solely, and is universal as so. The presentation of the information is without contract or any type of guarantee assurance.

The trademarks that are used are without any consent, and the publication of the trademark is without permission or backing by the trademark owner. All trademarks and brands within this book are for clarifying purposes only and are owned by the owners themselves, not affiliated with this document. Android is a trademark of Google Inc. iOS is a trademark or registered trademark of Cisco in the U.S. and other countries and is used under license by Apple Inc. Java is a trademark of Oracle Corporation and/or its affiliates.

The Android robot is reproduced or modified from work created and shared by Google and used according to terms described in the Creative Commons 3.0 Attribution License.

Written and published in Switzerland. Created with the eBook Template Toolchain by Adrian Kosmaczewski based on Asciidoctor and PlantUML.

Abstract

This book provides a quick introduction of Android for iOS developers using the Java™ programming language. It targets iOS developers with medium or advanced level, having shipped some iOS applications already in either Objective-C and Swift.

Dedication

To Laura.

Preface

The world of mobile development is a ground in constant motion. However, for the past five years, Android and iOS have both reached the level of dominant players in the field, moving other platforms out of sight. Due to the complexity of these systems, developers tend to concentrate their efforts in just one platform; however businesses must target both platforms to remain competitive in the mobile market.

This book provides an iOS developer’s perspective on Android, using the Java™ programming language, highlighting the similarities and the major differences between both platforms. The author hopes that these lines will help other developers to jump to the fascinating world of Android using their hard earned iOS knowledge.

Target Audience

This book is intended as a step-by-step guide to guide developers well versed in the arts of iOS into the realm of Android mobile application development.

How To Read This Book

The author assumes that the reader has never written Android applications before; at most, maybe, the reader has played with an Android device at some point, but nothing else. If you are already familiar with Android Studio and Java, you can skip directly to chapter 2, and start creating apps right away.

If you are not familiar with the Android developer tools, it is strongly recommended to read this book linearly, and to build the sample applications one after the other. This will help you build your skills step by step.

You can use this book as reference, later during your development work, using the provided source code as a basis for your own projects. The book can work as a "cookbook" text, providing specific help about some common (and not-so-common) tasks.

Requirements

This book assumes that the reader is using a Mac – after all, the reader is supposed to be an iOS developer!

It also assumes working programming knowledge in Objective-C or Swift, and of the most common iOS frameworks, such as Foundation, UIKit, Core Location, Core Data and others.

Most importantly, it is also assumed that the reader already knows Java; if not, please be aware that you might have a hard time understanding the code snippets shown in this book. The Bibliography section at the end of the book provides a few useful titles for starting your exploration of Java. In particular I’d recommend reading Bloch’s own "Effective Java" to help you take your Java skills to the next level.

In terms of software requirements, this book assumes that the latest version of Android Studio (3.0.1 at the time of publishing) is installed in the development machine, as well as Homebrew.

Source Code

The code bundled with the book has been prepared and tested with the latest version of Android Studio; make sure to download and install it in your system before starting.

All applications use the same baseline (or minSdkVersion): API 21, also known as Lollipop 5.0. This version of Android was released in November 2014, and at the time of this writing, 80% of all Android devices in the wild run a version equal or older to Lollipop. This should hopefully give this book the wide possible reach as well as a solid foundation for the future of the platform. Similarly, all code projects target the latest Android version available at the time of publication, API 27, Oreo 8.1 (targetSdkVersion and compileSdkVersion in the module Gradle files.)

Every time that the text of the book references some sample code, a "Follow Along" callout section will appear with the path of the project, which you can open on Android Studio to run the project directly on your device or the emulator:

Follow along

The code of this section is located in the Graphics/Draw folder.

Each application is as simple as possible, but not simpler. All the applications are working examples, tested at least in four environments:

  • The official Android Emulator.

  • The Genymotion Android Emulator.

  • A OnePlus 3 Android smartphone.

  • A Samsung Galaxy Tab S2 tablet.

Given the large variety of the Android device market, it is possible that some bits and pieces of the source code will not work in some devices; I remember having trouble with some Android devices during my career, so I would not be surprised if some of you encounter difficulties. I will not be able to provide support for your particular device, but I have made every possible effort so that the code works in the environments enumerated above.

Structure

This book is structured around code. The chapters are meant to be read with Android Studio open, in the order they have been written; I have reused bits and pieces of knowledge from previous chapters in many others, so you should be better served by reading them in order.

To help readers get up and running as fast as possible, every chapter features a section called "TL;DR" at its very beginning, including a handy summary of the most important similarities and differences between Android and iOS. You can use the tables in this section as a reference, and if you find them useful you can print a copy of the Appendix C, which contains all the TL;DR tables together in the same place.

The source code included in the book points directly to the projects available in the code zip file, which contains all the sample applications showcased in the pages of this book.

Thanks

I would like to thank all the readers of the first edition of this book; your support is what made this second edition possible! In particular I would like to mention Luca Torella, Patrick Balestra and Nick K., who sent me lots of feedback and errata via e-mail and Twitter. And a very, very special shoutout to Florent Pillet who not only provided lots of feedback and errata, but actually gave me the idea of creating a Kotlin version for this second edition. Thanks a lot!

About the Author

Adrian Kosmaczewski is a writer, a software developer and a trainer. He is the author of many books about mobile software development, and has shipped mobile, web and desktop apps for iOS, Android, Mac OS X, Windows and Linux since 1996. Adrian holds a Master in Information Technology from the University of Liverpool.

When not coding or teaching, Adrian likes to spend time with his wife Claudia, his cat Max and his Olivetti Lettera 22 typewriter.

Part 1: Introduction

Getting Started

This first part of the book will guide the reader in the world of Android app development. We will first learn how to install and use Android Studio, we are going to get familiar with the tools and ecosystem, not only to create applications but to be able to debug them effectively.

1. Toolchain

Each platform vendor tries – and, to a large extent, succeeds at – locking third-party developers into their own ecosystem. This is true of many software platforms, and neither iOS nor Android are the exception to this rule.

One of the biggest efforts for iOS developers new to the Android ecosystem is getting used to a new set of tools, paradigms, workflows and even new keyboard shortcuts all over the place. This chapter will present an introduction to the various tools used in the everyday life of a seasoned Android developer.

1.1. TL;DR

As an introduction, these are the most important differences that distinguish the iOS developer experience from that of Android.

Table 1. Android vs. iOS Toolkits
Android iOS

IDE

Android Studio

Xcode

Profiling

Android Device Monitor

Instruments

Preview

Android Emulator

iOS Simulator

Blocks in previous versions

Retrolambda

PLBlocks

Programming Language

Java

Swift or Objective-C

Command Line

gradlew – ant

xcodebuild

Going beyond

Rooting

Jailbreaking

Application metadata

AndroidManifest.xml

Info.plist

Dependency Manager

Gradle

CocoaPods – Carthage

Distribution

APK

IPA

Debugger

ADB + DDMS

LLDB

Logger

LogCat

NSLog() or print()

View Debugging

Hierarchy viewer

Xcode view debugging

Static Analysis

Android Lint

Clang Static Analyzer

Classic programming language

Java

Objective-C

Hype programming language

Kotlin – Groovy – Scala – Clojure

Swift

1.2. Java

Until 2017, Android applications were primarily written in Java, a language that shares a lot of features and commonalities with Objective-C and Swift. After all, many Java engineers working for Sun in the nineties came from NeXT, the computer company founded by Steve Jobs that ultimately merged with Apple in 1996, bringing the Objective-C language to the Apple ecosystem.

Both Java and Objective-C share lots of commonalities, such as protocols (called "interfaces" in the realm of Java) or primitive boxing types such as NSNumber (represented by the family of Number subclasses in Java.) They also represents two opposite views in terms of compile-time checks; Objective-C delegates most method and type resolutions to runtime, while Java performs rather strict type checking. In this respect, Swift is much more close to Java than Objective-C will ever be.

Learning Java from Scratch

This book will not provide the reader with an exhaustive introduction to the Java programming language. The Bibliography at the end of this book provides some useful titles for the reader to learn more about it.

Java has the following characteristics:

  • Single inheritance.

  • Strongly and statically typed.

  • No header files like Objective-C.

  • Objects instantiated in a garbage-collected heap; primitive values on the stack.

  • Classes, interfaces, fields and methods are "package private" by default.

  • The Object class is the base class for all objects in Java.

  • "Interfaces" are similar to Objective-C and Swift protocols, that is, constructs equivalent to abstract classes with pure virtual methods.

  • Java has no similar concept to that of Objective-C categories or Swift extensions, that is, it is impossible to extend classes other than by inheritance.

  • Full namespace support.

  • The closest equivalent for Objective-C’s id or Swift Any types is to use cast to Object.

  • Methods can be overloaded, unlike Objective-C but like Swift and other languages.

Of all the items above, the most important is the "Strongly and statically typed" one. This means that method calls in Java are bound at compile time, instead of being dispatched dynamically at runtime like in Objective-C. In spite of this, Java resolves polymorphic methods at runtime using a "vtable," just like in C++ or C#.

Android and Java 8

Android currently only supports version 1.7 of the Java Programming Language. Version 8, which introduced many new features such as lambdas, is not yet completely supported by Android, and at the time of this writing, there has been no official announcement about its availability in the near future.

Comparing Java to Objective-C and Swift

The table "Comparison of Java 1.7, Objective-C 2.0 and Swift 4" provides a comparison between these three languages.

Table 2. Comparison of Java 1.7, Objective-C 2.0 and Swift 4
Java 1.7 Objective-C 2.0 Swift 4

Inheritance

Simple, with interfaces

Simple, with protocols

Simple, with protocols and protocol extensions

Semicolons

Mandatory

Mandatory

Optional

Class definition

class

@interface & @implementation

class

Interfaces

implements interface

conforms to @protocol

conforms to protocol

Including code

import (symbols)

#import (files)

import (symbols)

Class extensions

no

Categories

Extensions

Dynamic typing

no

id

Any

Private field suffix

m (Java standard)

_ (underscore)

_ (underscore)

Memory management

Garbage collection

Manual or Automatic Reference Counting

Automatic Reference Counting

Generics

yes (type erasure)

yes (type erasure)

yes

Method pointers

no

@selector

#selector

Callbacks

Listeners via anonymous classes

Delegate objects and blocks

Delegate objects and functions

Pointers

no

yes

Via library classes

Root class

Object

NSObject / NSProxy / …

NSObject / NSProxy / …

Visibility

public / protected / package / private

@public / @protected / @private (only fields)

open / public / internal / fileprivate / private

Exception handling

try / catch / finally + Exception

@try / @catch / @finally + NSException

do / try / catch + Error

Namespaces

Packages

Through class prefixes

Implicit, via modules

Callbacks

One of the most visible differences between Java and Objective-C & Swift is the syntax for event callbacks. As mentioned above, Java 1.7 does not include lambdas, and as such it uses a feature called "Anonymous Classes" to inline the definition of event handlers and other kinds of callbacks in the code of your applications:

mButton.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        doSomething();
    }
});

In the snippet above, the code attaches an instance of a new "anonymous class" implementing the OnClickListener interface; all of them (the subclass and the instance) are just created "on the fly", without the need for the developer to create a separate file and to override the required methods there.

iOS developers who remember a time before Objective-C blocks might ask themselves what is the reason for not declaring the class in a separate file, plus an interface file filling the role of a "delegate protocol" between both objects. Rest assured, this approach would be absolutely valid and possible; and in many cases it might even be recommended. However, the anonymous class approach is more idiomatic in Android (that is, you more are likely to encounter it in other projects during your careeer) and it is also extremely convenient for small projects.

The Retrolambda Project

The open source project Retrolambda allows developers to use lambdas in Java 5, 6, and 7. For those who remember the early days of iOS development, PLBlocks used to offer a similar service; being able to use Objective-C blocks in iPhone OS 2.2+ and Mac OS X 10.5 applications.

As a convenience for the developer, Android Studio automatically displays the following shorter syntax for anonymous class callbacks, mimicking the look and feel of Java 1.8 lambdas, yielding a more readable and "future proof" experience:

mButton.setOnClickListener((v) -> {
        doSomething();
});

Getting used to this syntax is going to be very helpful in your path from iOS to Android. You can switch from one representation to the other by clicking on the small + sign in the gutter at the left side of the code editor.

Learning more about Java Lambdas

To learn more about lambdas and how they compare to anonymous classes, please refer to the official Java documentation by Oracle.

The Android Runtime

Another important fact about Android is that, by design, the Java applications compiled for the Android operating system are not compatible with a standard Java Virtual Machine – JVM – such as the ones available for Windows, macOS or Linux. This simple fact is often overlooked but it is very important to remember.

Android and the JVM

Compiled Android Java applications are not compatibles with the standard Java Virtual Machine by Oracle.

Android applications are compiled as DEX binaries (which stands for "Dalvik Executables") and run in a special virtual machine, optimized for mobile devices, formerly known as "Dalvik" and now most commonly referred to as the Android Runtime (ART.) Binaries targeting the ART have the following characteristics:

  1. Developers can include Java code bundled in binary form, such as JARs (Java Archives) in their applications; they can also include the source files in their projects, but all of this will be compiled as Android DEX binaries, which has a different binary structure.

  2. Not all valid Java APIs for a standard JVM exist under ART; in particular most of the javax. packages are unavailable in Android.

  3. DEX files are smaller than their equivalent JARs.

  4. ART uses a register-based architecture, instead of the standard JVM stack-based architecture, in order to increase performance.

  5. ART uses non-JVM standard bytecode instructions, and a different inter-process protocol.

  6. ART can run several Android applications in the same process if required.

From Android 2.2 "Froyo" to Android 5 "Lollipop", a just-in-time compiler (JIT) had been added to the Dalvik virtual, helping it increase the performance of the final code. ART, on the other hand, single handedly compiles all downloaded apps to native code upon installation, and provides much better garbage collection and debugging facilities than Dalvik.

Compilation

The diagram "Android Application Compilation" shows how close "APK" files are to the equivalent "IPA" files distributed by the Apple App Store. In both cases it consists of a compressed archive containing both the binary of the executable and all of its bundled resources, following a very particular folder structure.

diagram compilation
Figure 1. Android Application Compilation

Android Release History

The following table shows the history of Android releases, borrowed from Wikipedia, combined with information from the Android developer dashboard. This information is valid as of August 2017.

Table 3. Android Version History And Market Share
Code Name Version Number Release Date API Level Support status %

Alpha

1.0

September 23, 2008

1

Discontinued

Beta

1.1

February 9, 2009

2

Discontinued

Cupcake

1.5

April 27, 2009

3

Discontinued

Donut

1.6

September 15, 2009

4

Discontinued

Eclair

2.0 - 2.1

October 26, 2009

5 - 7

Discontinued

Froyo

2.2 - 2.2.3

May 20, 2010

8

Discontinued

Gingerbread

2.3 - 2.3.7

December 6, 2010

9 - 10

Discontinued

0.4%

Honeycomb

3.0 - 3.2.6

February 22, 2011

11 - 13

Discontinued

Ice Cream Sandwich

4.0 - 4.0.4

October 18, 2011

14 - 15

Discontinued

0.5%

Jelly Bean

4.1 - 4.3.1

July 9, 2012

16 - 18

Discontinued

5.9%

KitKat

4.4 - 4.4.4

October 31, 2013

19 - 20

Discontinued

13.4%

Lollipop

5.0 - 5.1.1

November 12, 2014

21 - 22

Supported

26.3%

Marshmallow

6.0 - 6.0.1

October 5, 2015

23

Supported

29.7%

Nougat

7.0 - 7.1.2

August 22, 2016

24 - 25

Supported

23.3%

Oreo

8.0 - 8.1

August 21, 2017

26 - 27

Supported

0.5%

As mentioned in the preface, the code samples that are bundled with this book support Lollipop (API 21) as their minimum requirement. This is because at the time of this writing, 80% of all Android devices in circulation run a version of Android equal or bigger to Lollipop.

1.3. Android Application Startup

When a user taps on the icon of an Android application a whole series of events happen in the device. Many of these events are very similar to those in iOS, and it turns out that, quite unsurprisingly, both operating systems use a very similar architecture, but with quite different class structures backing them.

Let us create a small project in Android Studio. In that project, add a subclass of the android.app.Application class, and register that class as the main application class in your AndroidManifest.xml file. Add two breakpoints in the source code, one in the Application.onCreate() method, and another in the MainActivity.onCreate() method.

The stack traces when hitting both breakpoints is shown below:

Application.onCreate()
training.akosma.startup.StartupApplication.onCreate(StartupApplication.java:8)
com.android.tools.fd.runtime.BootstrapApplication.onCreate(BootstrapApplication.java:370)
android.app.Instrumentation.callApplicationOnCreate(Instrumentation.java:1012)
android.app.ActivityThread.handleBindApplication(ActivityThread.java:4553)
android.app.ActivityThread.access$1500(ActivityThread.java:151)
android.app.ActivityThread$H.handleMessage(ActivityThread.java:1364)
android.os.Handler.dispatchMessage(Handler.java:102)
android.os.Looper.loop(Looper.java:135)
android.app.ActivityThread.main(ActivityThread.java:5254)
java.lang.reflect.Method.invoke(Method.java:-1)
java.lang.reflect.Method.invoke(Method.java:372)
com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:903)
com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698)
MainActivity.onCreate()
training.akosma.startup.MainActivity.onCreate(MainActivity.java:10)
android.app.Activity.performCreate(Activity.java:5990)
android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1106)
android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2278)
android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2387)
android.app.ActivityThread.access$800(ActivityThread.java:151)
android.app.ActivityThread$H.handleMessage(ActivityThread.java:1303)
android.os.Handler.dispatchMessage(Handler.java:102)
android.os.Looper.loop(Looper.java:135)
android.app.ActivityThread.main(ActivityThread.java:5254)
java.lang.reflect.Method.invoke(Method.java:-1)
java.lang.reflect.Method.invoke(Method.java:372)
com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:903)
com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698)

There are several interesting bits of information in the stack traces above. First of all, the android.os.Looper class, which as the name suggests provides the main run loop of the application. Most GUI toolkits include a similar construction, created at application runtime, holding an event queue and routing events from the operating system to the different activities and components of the application.

Looper == NSRunLoop

For all practical purposes, iOS developers will recognize that the android.os.Looper class is the equivalent of the NSRunLoop class in Cocoa. If you want to learn more about Looper, please check the official Android documentation by Google.

If you click on the name of a class in Android Studio while holding down the key, the IDE will open the corresponding class file; if you do not have the Android source code available in your local workstation the IDE will simply decompile the code from the local SDK and show a stub implementation of the corresponding class, with most of its methods.

By doing this repeatedly, from both the MainActivity and the Application subclass you created previously, you are going to arrive to the android.content.Context class, which is arguably the most important class in the Android SDK. The Context class includes many different methods, ranging from file management to database creation to inter-process communication, and it also holds a reference to the underlying Looper class.

Equivalent in iOS

There is no similar equivalent of android.content.Context in iOS, however one could argue that NSResponder fulfills a similar role, since many different classes such as UIViewController, UIView and even UIApplication are all subclasses of NSResponder. However, Context is a very different beast from NSResponder!

The diagram "The android.content.Context class" shows a simplified class hierarchy of the Activity and Application classes and its relationship with the Looper class.

diagram context class
Figure 2. The android.content.Context class

1.4. Zygote

One of the biggest problems with any Java Virtual Machine (JVM) is the long startup time. In the case of Android, this problem is even bigger, given the limited resources of many devices in the market. Moreover, since every application has to run its own copy of the JVM to ensure privacy and security through sandboxing, the price to pay would be too steep.

Zygote is the name of a process that Android runs as soon as the operating system stops booting. Its objective is to launch a copy of the Android Runtime (ART), which is Android’s version of the JVM, so that it is ready to use by every application in the system.

As soon as the user taps on the icon of an application to launch it, Android will ask Zygote to "fork" a copy of the JVM process, so that each application runs in its own sandbox, without conflicting with other processes. Zygote also preloads a certain number of libraries and resources that are usually required by most Android applications to run properly. All of this substantially speeds up the launching time of applications.

More about Zygote

If you want to know more about Zygote, this answer in Stack Overflow provides an excellent summary.

1.5. Android Studio

Android Studio is a free IDE provided by Google to develop Android applications. It replaced the venerable Eclipse Android Developer Tools, historically the first official IDE for Android software development for many years. It was announced for the first time in May 2013 at the Google I/O conference. The first stable release was in December 2014. It is available for Windows, macOS and Linux, and is now considered the official IDE for Android development.

End-of-life of the Eclipse Android Developer Tools

Google has announced in November 2nd, 2016 the official end of support and development of the Eclipse Android Developer Tools, which are completely superceded by Android Studio 2.2.

Android Studio is powered by IntelliJ IDEA, a popular IDE for Java development for the past 15 years. It has a solid reputation, and is particularly appreciated by its advanced support for refactoring, code generation and project navigation features.

Android Studio is available from the Android Studio website. The current version at the time of this writing is 3.0.1. Android Studio is, by far, the most important piece in the daily workflow of an Android Developer, and includes many different features targeted to simplify the development of Android apps, which like all software development can be quite a complex endeavour sometimes.

Android Studio Splashscreen
Figure 3. Android Studio Splashscreen

Once downloaded and launched, Android Studio will launch a configuration wizard, as shown in Android Studio Setup Wizard – Step 1.

Most developers will choose the standard settings, as shown in image Android Studio Setup Wizard – Step 2.

Finally, Android Studio will automatically download all the elements required for it to work properly, as shown in image Android Studio Setup Wizard – Step 3.

Android Studio Migrating Preferences
Figure 4. Android Studio Migrating Preferences
Android Studio Setup Wizard – Step 1
Figure 5. Android Studio Setup Wizard – Step 1
Android Studio Setup Wizard – Step 2
Figure 6. Android Studio Setup Wizard – Step 2