Colophon
© Copyright 2016-2017 by Adrian Kosmaczewski – All Rights Reserved.
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. iOS is a trademark of Apple.
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.
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. It targets iOS developers with medium or advanced level, having shipped some iOS applications already in either Objective-C and Swift.
Dedication
To my friend Daniel Steinberg.
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, 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, she or he has played with an Android device at some point, but nothing else. If you are already familiar with Android, 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.
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] 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 copy of Android Studio 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: API 16, also known as Jelly Bean 4.1. This version of Android was released in July 2012, and at the time of this writing, 97.3% of all Android devices in the wild run a version equal or older to Jelly Bean. This should hopefully give this book the widest possible reach.
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 |
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 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 guarantee that the code should work 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 applications
available in the code
folder, which contains all the sample applications
bundled as part of this training.
Part 1: Introduction
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.
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 |
|
|
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
Android applications are 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 SwiftAny
types is to use cast toObject
. -
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. If your application targets Android 7 (API 24) or later, and if your project uses Android Studio 2.1 or later, then you can install "Jack", a new Java compiler which makes some Java 8 features available in Android, such as:
Jack is still an experimental feature which can have conflicts with other tools in the toolchain, so it might be wise to wait until it is officially and fully supported. |
The table "Comparison of Java 1.7, Objective-C 2.0 and Swift 3" provides a comparison between these three languages.
Java 1.7 | Objective-C 2.0 | Swift 3 | |
---|---|---|---|
Inheritance |
Simple, with interfaces |
Simple, with protocols |
Simple, with protocols and protocol extensions |
Semicolons |
Mandatory |
Mandatory |
Optional |
Class definition |
|
|
|
Interfaces |
implements |
conforms to |
conforms to |
Including code |
|
|
|
Class extensions |
no |
Categories |
Extensions |
Dynamic typing |
no |
|
|
Private field suffix |
|
|
|
Memory management |
Garbage collection |
Manual or Automatic Reference Counting |
Automatic Reference Counting |
Generics |
yes (type erasure) |
yes (type erasure) |
yes |
Method pointers |
no |
|
|
Callbacks |
Listeners via anonymous classes |
Delegate objects and blocks |
Delegate objects and functions |
Pointers |
no |
yes |
Via library classes |
Root class |
|
|
|
Visibility |
|
|
|
Exception handling |
|
|
|
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, and in anticipation of future versions of Java, Android Studio automatically displays the following shorter syntax for anonymous class callbacks, which mimicks 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:
-
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.
-
Not all valid Java APIs for a standard JVM exist under ART; in particular most of the
javax.
packages are unavailable in Android. -
DEX files are smaller than their equivalent JARs.
-
ART uses a register-based architecture, instead of the standard JVM stack-based architecture, in order to increase performance.
-
ART uses non-JVM standard bytecode instructions, and a different inter-process protocol.
-
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.
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 December 2016.
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 |
0.1% |
Gingerbread |
2.3 - 2.3.7 |
December 6, 2010 |
9 - 10 |
Discontinued |
1.3% |
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 |
1.3% |
Jelly Bean |
4.1 - 4.3.1 |
July 9, 2012 |
16 - 18 |
Discontinued |
13.7% |
KitKat |
4.4 - 4.4.4 |
October 31, 2013 |
19 |
Security updates only |
25.2% |
Lollipop |
5.0 - 5.1.1 |
November 12, 2014 |
21 - 22 |
Supported |
34.1% |
Marshmallow |
6.0 - 6.0.1 |
October 5, 2015 |
23 |
Supported |
24% |
Nougat |
7.0 - 7.1.1 |
August 22, 2016 |
24 - 25 |
Supported |
0.3% |
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:
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)
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
|
If you click on the name of a class in Android Studio while holding down the Cmd 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 |
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.
Another important element in the stack trace above is Zygote; this piece of software, named after a fertilized living cell, is the application launcher of the Android operating system. To ensure fast application startup, Zygote loads a copy of the ART virtual machine and when a new application launches, forks this VM to sandbox the process in it. If you want to know more about Zygote, this answer in Stack Overflow provides an excellent summary.
1.4. 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 2.2.2; version 2.2 was a major milestone released September 19th, 2016. 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.
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.
Once Android Studio is ready to go, it will display some tips and tricks every day – something you can easily dismiss if you want, as shown in Android Studio Tips.
Android SDK Environment
Once Android Studio is installed, it is strongly recommended to configure the
environment of your system to point to the folder where the Android SDK
resides. In my system, I have added an # Path for the Android SDK export PATH=~/Library/Android/sdk/platform-tools:~/Library/Android/sdk/tools:"${PATH}" # For Android stuff export ANDROID_HOME=~/Library/Android/sdk |
Creating a New Project
To create a new project in Android Studio , just select the menu:File[New > New Project] menu item, and follow the instructions as shown in the following screenshots.
After running the project wizard, Android Studio should show you a windows similar to the one featured in image New project in Android Studio.
Invoking Android Studio Actions
Instead of clicking your way around in menus, you might want to learn the handy Cmd+Shift+A shortcut; this command allows you to invoke any operation available in the IDE without leaving your hands from the keyboard. |
Command Line Tool
Android Studio allows developers to install a command line utility, useful to open projects directly from a terminal session. Select the Creating a launcher script for Android Studio.
menu entry and select the output folder for the script, as shown in imageOnce installed, just type studio .
at the root of a folder containing an
Android Studio project, and a new windows with the current project will
appear on your screen.
Many of the external tools required to build Android applications are available directly from the Tools/Android Menu in Android Studio.
menu in Android Studio, as shown in imageWe are now going to learn more about each of these pieces individually.
1.5. Kotlin
At the beginning of this chapter I mentioned that Java is the only programming language supported by Google for Android development. The ecosystem, however, includes many other possibilities; at the end of this book, the appendix "Third Party Android Developer Tools" contains a list of other environments and programming languages available to create Android applications. As you will see there, there are lots of different possibilities out there.
In this section we are going to explore one of those options: Kotlin. This programming language was created by the same engineers that created IntelliJ IDEA and Android Studio, and it is uncannily similar to Swift in many ways. Kotlin might be an interesting choice for Swift developers looking to write Android applications using a safe, fast and modern programming language.
Using Kotlin in your Android project requires adding a small library used at runtime for interoperability with Java; this library increases the size of the final application in around one megabyte.
We are going to create a small application using Kotlin, to show how easy it is to integrate and how similar it is to Swift.
Kotlin is available as a plugin for Android Studio. You can manage plugins in Android Studio by opening the Browsing plugin repositories"
menu, as shown in figure "Once the Kotlin plugin is installed, you should restart Android Studio for
it to be loaded in memory. After relaunching, create a simple Android
application and open the MainActivity
class. Select the
menu entry and watch Android
Studio transform the standard Java code of your project into Kotlin.
The listing "Simple activity in Kotlin" shows the resulting code in a very simple application, with a lambda set as the event callback for button clicks.
package training.akosma.kotlin
import android.support.v7.app.AppCompatActivity
import android.os.Bundle
import kotlinx.android.synthetic.main.activity_main.*
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
button.setOnClickListener {
textView.text = "Button clicked!"
}
}
}
Kotlin not only has a syntax that looks a lot like that of Swift, it shares many features with Apple’s new language:
-
Optionals
-
Lambdas
-
Functional programming features
-
Ranges
-
Pattern matching
-
Class extensions
Kotlin compiles its code to native Android bytecode, which means that setting the small overhead of the runtime library aside, an application created with Kotlin behaves and is distributed exactly like one created with Java.
1.6. SDK Manager
As the name implies, the SDK Manager allows the developer to install, manage and uninstall different versions of the Android Software Development Kit (SDK) in the local workstation. Figure Android SDK Manager shows the default state after launching Android Studio and installing the latest available version of Android at the time of this writing, 7.1.1 (also known as Nougat.)