Android Crash Course for Beginners - pt. 1

Overview

The goal of this crash course is to make you comfortable working on an existing Android codebase. While no previous Android experience is required, I assume some familiarity with:

Background Knowledge

To make sure we have all the background information required, I’ll start at the very bottom of the knowledge tree and quickly work our way up.

Computers process instructions on their central processing units, CPUs. Through magic1, they read these instructions from memory and execute them. These instructions may be something like “add 2 numbers”, “store this number in memory”, etc.

The CPU’s instructions look like this:

01000110
01001001
01001010

That’s not very readable. At all. To actually write programs as humans we introduce our first abstraction, assembly:

From StackExchange

That text on the left (e.g. mov ecx, ebx) corresponds directly to a sequence of 0’s and 1’s (e.g. 100101011001). A mini program takes our “text” file with these semi-readable instructions and converts them to machine language.

This is still really awful to program in. Even worse, different CPUs have different sets of instructions they can use! It would be really nice to have a program that takes easy-to-write code and converts them to the relevant machine instructions. This is what languages like C, C++ and Rust do: you write code and a compiler transforms it into the instruction set your CPU understands. If you have multiple CPUs you’re making programs for, it can create different instruction set files.

Unfortunately, there is another layer in between your code and, say, displaying a window on your monitor: the Operating System (OS). Different Operating Systems like Windows or MacOS have different ways of interpreting machine linstructions. What if there was a way to code just one, high-level, generic command (e.g. createWindow()) and have it Just WorkTM?

Enter Virtual Machines. These are programs that take their own special kind of machine instruction, called bytecode, and convert it on-the-fly to the underlying machine’s instruction set. This means instead of compiling your code to a bunch of different instruction sets, you compile it to one bytecode file and have the virtual machine run it for you! At the cost of a little performance, we get code that’s write once, run anywhere.

This is, at the very base level, how Android works: You write code in a high-level language (either Java or Kotlin) that compiles to bytecode. This bytecode is then run on a virtual machine running on your phone and executed!

If you’re familiar with Java, then you know that I just described how Java works with the JVM, or the Java Virtual Machine. Android has its own (very similar) version of the JVM called Dalvik2. You can read more about Dalvik bytecode, which has the file extension .dex, in this StackOverflow answer.

That’s how code gets compiled to be usable on an Android device. What you actually download from Google Play is a .APK file, which is your Dalvik bytecode along with all your app’s assets (e.g. images). For more information on APK files, click here.

Gradle

We now have enough knowledge to start understanding an Android Repo. The scariest part of the repo are those related to Gradle, the build tool that orchestrates how your code gets turned alchemy-like into APK files. It becomes much less scary when you realize that Gradle is just a shortcut for running the build/compile/deploy commands every time.

I highly recommend reading through Gradle’s introduction documentation. It’s well written and easy to follow. Here’s a summary:

include ':app' // in the settings.gradle file

For more information about Gradle’s structure, check out Google’s documentation on the subject.

Project Overview

Taking a high level look at the repo, there’s a lot of files and folders! Luckily, we’ve gone through a bunch of them by understanding Gradle. Here are some other ones you might encounter:

How an Android App Runs

We know that Gradle directs the process of converting your code & assets into a .APK file. What does that look like?

It turns out, a .APK file is just a ZIP file with specific files/directories! As described in the link above or the Wikipedia article, the file directory structure inside a .APK file looks like this:

If you’re familiar with Java or C code, you know that you need a main method that tells the app where to start. However, an Android App is more like a loose collection of separate processes/screens that we call Activities (I’ll go more in depth in a future post). What happens in Android to detect “main” methods is (essentially) the following:

Note: this is an oversimplification, since Android doesn’t directly run dex code and instead runs the ART machine-compiled version. That being said, going to this level of detail is more than sufficient to understand the inner workings of Android apps.

That second step explains why you would need to put the Activity class in AndroidManifest.xml: if they’re not declared there, the system can’t find it!

Code Compilation

There aren’t too many resources out there explaining the compilation step (that I had time to get through, anyway), but from what I understand it goes something like:

  1. The AAPT (Asset Packaging Tool) compiles Layout XML stuff into R.java, a list of resource ids

  2. kotlinc converts Kotlin code into .class files

  3. D8 converts .class files into one .dex file

  4. The .APK is signed, built, and loaded onto a testing device

For more information this Medium post has some good jumping-off points.

Conclusion

Almost everything you need to know after this relates specifically to Android development and how to make the apps. Hopefully, you’re much more comfortable with how Android works and the general file structure of this repo. I unfortunately can’t fit everything I want to in one post, so I will leave the development crash course page for another day. If you have any questions or suggestions on how to improve this article, please comment down below!


  1. To understand the magic, take CS 240↩︎

  2. Dalvik was actually discontinued sometime in the 2010s and replaced with a much faster version called the Android Runtime (ART). That being said, the depth of knowledge required to understand going from your code to deploying on the app store stops as Dalvik. ↩︎