Android development is commonly done using Android Studio or some other IDE environment. This short tutorial takes a different perspective of Android programming, and discusses ways in which developing, compiling, installing and debugging Android applications can be achieved on the command line.

Filed under

This document describes the usage of common tools used for Android development on the command line, particularly Android (android), Android Debug Bridge (adb) and how they can be used to create an Android application project and how to install and debug an Android app using the command line.

After reading this document, you should be familiar in using the common tools for Android development stated above in creating, installing and debugging Android apps.

Prerequisites

To properly follow this material, you must have the following in place:

(1) You have installed the latest Java Development Kit (JDK) from Oracle. (java.com/download)

(2) You must have installed Android SDK. If you have not done so yet, you can download the Android SDK here: developer.android.com/sdk

(The Android SDK can be downloaded separately as a stand alone installer, or as part of the bigger Android Studio installer)

The Android SDK and the associated commands work roughly exactly the same way on Windows, Mac OS X and Linux. Therefore, the instructions given here should be applicable regardless of your operating system.

The "android" command

If you have the Android SDK in place, you can locate the "android" command inside the tools directory. To try it, open up your command line, and issue the following kind of command (obviously replacing the beginning with the complete path to the actual directory where you have installed the SDK files):

<your android sdk directory>/tools/android

Then press ENTER. By default, the Android SDK Manager will be displayed:

The Android SDK Manager lets you download and install, uninstall, and update necessary packages (SDK tools and platforms) that you need to develop an Android app. Full information about this GUI tool can be found on the Android developer site:

Going back to the command line, to list some of the things that can be done with the android tool, try this:

<your android sdk directory>/tools/android -h

or

<your android sdk directory>/tools/android --help

You should see commands with corresponding descriptions like the following below:

Usage: android [global options] action [action options]

Global options:

  -s --silent     : Silent mode, shows errors only.
  -v --verbose    : Verbose mode, shows errors, warnings and all messages.
     --clear-cache: Clear the SDK Manager repository manifest cache.
  -h --help       : Help on a specific command.

Valid actions are composed of a verb and an optional direct object:

- sdk                    : Displays the SDK Manager window.
- avd                    : Displays the AVD Manager window.
- list                   : Lists existing targets or virtual devices.
- list avd               : Lists existing Android Virtual Devices.
- list target            : Lists existing targets.
- list device            : Lists existing devices.
- list sdk               : Lists remote SDK repository.
- create avd             : Creates a new Android Virtual Device.
- move avd               : Moves or renames an Android Virtual Device.
- delete avd             : Deletes an Android Virtual Device.
- update avd             : Updates an Android Virtual Device to match the folders
                           of a new SDK.
- create project         : Creates a new Android project.
- update project         : Updates an Android project (must already have an
                           AndroidManifest.xml).
- create test-project    : Creates a new Android project for a test package.
- update test-project    : Updates the Android project for a test package (must
                           already have an AndroidManifest.xml).
- create lib-project     : Creates a new Android library project.
- update lib-project     : Updates an Android library project (must already have
                           an AndroidManifest.xml).
- create uitest-project  : Creates a new UI test project.
- update adb             : Updates adb to support the USB devices declared in the
                           SDK add-ons.
- update sdk             : Updates the SDK by suggesting new platforms to install
                           if available.

List Targets

To display the list of available Android target(s) / SDK versions that are available on the current system, try this:

<your android sdk directory>/tools/android list targets

You should see available targets like the following:

Available Android targets:
id: 1 or "android-23"
     Name: Android 6.0
     Type: Platform
     API level: 23
     Revision: 2
     Skins: HVGA, QVGA, WQVGA400, WQVGA432, WSVGA, WVGA800 (default), WVGA854, WXGA720, WXGA800, WXGA800-7in
 Tag/ABIs : default/armeabi-v7a, default/x86_64

(Followed by other targets, if available)

Take note of the "id" line in this list, as that is the value that you can use in other places to refer to the specific version of an Android SDK target.

List Devices

To display a list of available Android device(s) that are currently configured, try this:

<your android sdk directory>/tools/android list devices

You should see available device definitions like the following:

Available devices definitions:
id: 1 or "Galaxy Nexus"
    Name: Galaxy Nexus
    OEM : Google

(Followed by other devices, if available)

The Android Emulator

The Android Emulator emulates a complete Android device in software on a desktop computer. Therefore, to do Android development, you will not necessarily need to have an actual physical device at your disposal. You can locate the Android emulator tool as part of the Android SDK here:

<your android sdk directory>/tools/emulator

Creating an Android Virtual Device

To run an instance of the Android operating system inside the emulator, you will first need to create an Android Virtual Device. You can do this with the following kind of a command:

<your android sdk directory>/tools/android create avd
	--name <desired avd name>
	--target <target platform> ## from list of targets, can be ID or name
	--abi <processor type> ## optional, depending on the target

Sample:

<your android sdk directory>/tools/android create avd
	--name Lollipop
	--target 1
	--abi default/armeabi-v7a

Type the entire command on one line. Then press ENTER in the end. You should see something like this:

Created AVD 'Lollipop' based on Android 5.0.1, ARM (armeabi-v7a) processor,
with the following hardware config:
hw.accelerometer=yes
hw.audioInput=yes
hw.battery=yes
hw.cpu.model=cortex-a8
hw.dPad=no
hw.device.hash2=MD5:6930e145748b87e87d3f40cabd140a41
hw.device.manufacturer=Google
hw.device.name=Galaxy Nexus
hw.gps=yes
hw.keyboard=no
hw.lcd.density=320
hw.mainKeys=no
hw.ramSize=512
hw.sdCard=no
hw.sensors.orientation=yes
hw.sensors.proximity=yes
hw.trackBall=no
vm.heapSize=48

Cool! You have successfully created your Android Virtual Device.

Running your virtual device

To execute your new Android Virtual Device in an emulator, you can simply do this:

<your android sdk directory>/tools/emulator -avd <name of avd>

You should see and Android Emulator starting up and something like below in the terminal window:

emulator: WARNING: Increasing RAM size to 1GB
Creating filesystem with parameters:
    Size: 576716800
    Block size: 4096
    Blocks per group: 32768
    Inodes per group: 7040
    Inode size: 256
    Journal blocks: 2200
    Label: 
    Blocks: 140800
    Block groups: 5
    Reserved block group size: 39
Created filesystem with 11/35200 inodes and 4536/140800 blocks
resize2fs 1.42.13 (17-May-2015)
The filesystem is already 140800 (4k) blocks long.  Nothing to do!

The emulator itself should have opened in a new window, running a complete copy of the Android operating system.

Creating a new Android application

To create the initial source code for a new Android application, try this:

<your android sdk directory>/tools/android create project
	--target <target ID> ## from the list of targets
	--name <desired project name> ## optional
	--path <project directory>
	--activity <activity name> ## usually the MainActivity
	--package <java package name>
	--gradle
	--gradle-version <android gradle plugin version>

For example:

<your android sdk directory>/tools/android create project
	--target 5
	--name myApp
	--path SampleAndroidProject
	--activity MainActivity
	--package my.app
	--gradle
	--gradle-version 1.1.3

Again, the entire command would be written on one line. In the end, press ENTER. You should see something like this in your terminal window:

Created directory SampleAndroidProject/src/main/java
Created directory SampleAndroidProject/src/main/java/my/app
Added file ./src/main/java/my/app/MainActivity.java
Created directory SampleAndroidProject/src/androidTest/java
Created directory SampleAndroidProject/src/androidTest/java/my/app
Added file ./src/androidTest/java/my/app/MainActivityTest.java
Created directory SampleAndroidProject/src/main/res
Created directory SampleAndroidProject/src/main/res/values
Added file ./src/main/res/values/strings.xml
Created directory SampleAndroidProject/src/main/res/layout
Added file ./src/main/res/layout/main.xml
Created directory SampleAndroidProject/src/main/res/drawable-xhdpi
Created directory SampleAndroidProject/src/main/res/drawable-hdpi
Created directory SampleAndroidProject/src/main/res/drawable-mdpi
Created directory SampleAndroidProject/src/main/res/drawable-ldpi
Added file ./src/main/AndroidManifest.xml
Added file ./build.gradle
Created directory SampleAndroidProject/gradle/wrapper

Awesome! You have successfully created an Android project.

Project Directory Contents

After successfully creating a project, navigate to your project directory. You should have the following files and directories in place:

build.gradle
gradle/
gradlew
gradlew.bat
local.properties
src/

Adjust the created project

It appears that the project creation script is stuck in an older version of Gradle, which is no longer compatible with newer versions of the overall Android build system. To address the problem, we will need to edit the "gradle-wrapper.properties" file under the "wrapper" subdirectory of the "gradle" directory in the created project source. In that file, by default, you find a line like this:

distributionUrl=http\://services.gradle.org/distributions/gradle-1.12-all.zip

This can be changed to this:

distributionUrl=http\://services.gradle.org/distributions/gradle-2.2.1-all.zip

(essentially, we change gradle version from 1.12 to 2.2.1, as it should be).

Likewise, in the generated "build.gradle" file, you should change the line that says "runProguard false" to "minifyEnabled true" (apparently, the syntax for this was changed at a point during the Android build system development cycle, but the "android create project" script is yet to be updated accordingly).

Compiling an Android Project

Before you compile your project, you must be connected to the internet in order for the gradle wrapper script to download the appropriate gradle software components. Once ready, to compile your Android project, navigate to your project directory on your command line (change directory), and do this:

For Mac or Linux:

./gradlew build

For Windows:

gradlew.bat build

The "gradlew" script is a wrapper script that then downloads all the necessary components that are needed to run the complete Gradle build. Once any necessary downloading is completed, the wrapper continues to execute the actual build. In the end, you should find the final APK installer in the "build" -> "outputs" -> "apk" directory under your project directory:

$ ls build/outputs/apk/
SampleAndroidProject-debug-unaligned.apk
SampleAndroidProject-debug.apk
SampleAndroidProject-release-unsigned.apk

The installer to use is the second one in the list above (*-debug.apk).

The APK file

The Android Application Package, most commonly known as APK, is the installer and distribution file format for Android apps. Once your Gradle build has successfully completed, you should have an APK file that was generated from your source code.

The Android Debug Bridge

Android Debug Bridge (adb) is a command line tool used to communicate with a connected android device or emulator. It is commonly used for installation and debugging of apps during development.

You can locate the Android Debug Bridge executable (adb or adb.exe) here:

<your android sdk directory>/platform-tools/

For complete official information about Android Debug Bridge, refer to the link below:

Bear in mind that before you install and debug an app, you must have one of the following in place:

(1) Connected Android device

(2) Running Android Emulator

Select the appropriate device

If you have a device connected, or an emulator running, to check if it is connected, try this:

<your android sdk directory>/platform-tools/adb devices

This command will list all physical Android gadgets (tablets, phones, etc.) that you have connected to your development computer (via USB or otherwise), as well as any Android emulator instances that you may have running. If ever you plug in several devices, and/or run several emulators simultaneously, observing this list becomes increasingly important in selecting which one of them you would wish to interact with.

You should see something like the following:

List of devices attached
emulator-5554		device
J501A1ZR55043323	device

To select a specific Android instance (whether device or emulator) to use, you can use the -s parameter of adb to specify which device to use, followed by the device ID from the list above. For example:

<your android sdk directory>/platform-tools/adb -s emulator-5554 <operations-to-execute>

Installing an Android app

If this is your first time to install the particular app on the device or emulator, you can simply do this:

<your android sdk directory>/platform-tools/adb install <your APK file>

Then press ENTER and the following kind of information should be displayed in your terminal window:

5840 KB/s (7624580 bytes in 1.274s)
  pkg: /data/local/tmp/myapp.apk
Success

Congratulations. You have successfully installed your Android app. It should now appear in the application menu of the device or emulator.

Replacing or reinstalling an app

To replace a previously installed app, the -r parameter of adb can be used. Try this:

<your android sdk directory>/platform-tools/adb install -r <your APK file>

Take note that the -r parameter means to replace an existing application. So, doing this ..

<your android sdk directory>/platform-tools/adb install <your APK file>

.. would generate an error, as shown below, since you are trying to install the same version of the app without using the -r parameter.

1654 KB/s (7624580 bytes in 4.499s)
  pkg: /data/local/tmp/myapp.apk
Failure [INSTALL_FAILED_ALREADY_EXISTS]

Debugging with adb logcat

The logcat command of adb is used to display system messages of a running Android OS (whether device or emulator). This is extremely useful to find out what is happening to an application or a device. Any and all messages generated by the device are shown here, giving a wealth of information for any kind of troubleshooting requirements.

Try this:

<your android sdk directory>/platform-tools/adb logcat

You should see logs in your terminal window something like the following:

* daemon not running. starting it now on port 5037 *
adb I   473  7034 usb_osx.cpp:259] Found vid=0bb4 pid=0c02 serial=J501A1ZR55043323
adb I   473  7034 usb_osx.cpp:259] 
* daemon started successfully *
--------- beginning of /dev/log/system
D/ActivityThread(19921): SVC-BIND_SERVICE handled : 0 / BindServiceData{token=android.os.BinderProxy@423157e0 intent=Intent { pkg=com.google.android.gms cmp=com.google.android.gms/.auth.GetToken }}
D/ActivityThread(19921): SVC-Creating service: CreateServiceData{token=android.os.BinderProxy@422d8168 className=com.google.android.gms.auth.DefaultAuthDelegateService packageName=com.google.android.gms intent=null}
D/ActivityThread(19921): SVC-CREATE_SERVICE handled : 0 / CreateServiceData{token=android.os.BinderProxy@422d8168 className=com.google.android.gms.auth.DefaultAuthDelegateService packageName=com.google.android.gms intent=null}
D/ActivityThread(19921): SVC-BIND_SERVICE handled : 0 / BindServiceData{token=android.os.BinderProxy@422d8168 intent=Intent { pkg=com.google.android.gms cmp=com.google.android.gms/.auth.DefaultAuthDelegateService }}
D/ActivityThread(19921): SVC-UNBIND_SERVICE handled : 0 / BindServiceData{token=android.os.BinderProxy@422d8168 intent=Intent { pkg=com.google.android.gms cmp=com.google.android.gms/.auth.DefaultAuthDelegateService }}
D/ActivityThread(19921): SVC-Destroying service: com.google.android.gms.auth.DefaultAuthDelegateService@42372618
D/ActivityThread(19921): SVC-STOP_SERVICE handled : 0 / android.os.BinderProxy@422d8168
D/ActivityThread(19921): SVC-UNBIND_SERVICE handled : 0 / BindServiceData{token=android.os.BinderProxy@423157e0 intent=Intent { pkg=com.google.android.gms cmp=com.google.android.gms/.auth.GetToken }}

----- More logs ------

The logcat command of adb is commonly used by app developers and testers to trace the cause of crashes in an Android app during development.

Filtering logs

To filter logs using the logcat command of adb. You can do this:

<your android sdk directory>/platform-tools/adb logcat *:#

The asterisk (*) character means ALL logs and the hash (#) character is the filter, which can be one of the following:

V	Verbose  (default)
D	Debug
I	Info
W	Warn
E	Error
F	Fatal

For example, doing this ...

<your android sdk directory>/platform-tools/adb logcat *:W

... would result to something like the following:

--------- beginning of /dev/log/system
W/SocketClient(  156): write error (Broken pipe)
W/ActivityManager(  719): Unable to start service Intent { act=com.cleanmaster.api.RT_ACCESS cmp=com.cmcm.skey/com.cmcm.rtstub.RTApiService } U=0: not found
W/ActivityManager(  719): Unable to start service Intent { act=com.cleanmaster.api.RT_ACCESS cmp=com.cmcm.rtstub/.RTApiService } U=0: not found
--------- beginning of /dev/log/main
W/MediatekClassFactory( 3129): Tablet not exist!, Get obj from default class
E/        ( 3129): appName=com.cleanmaster.mguard:gamebox.web, acAppName=/system/bin/surfaceflinger
E/        ( 3129): 0

----- More logs -----

Note:

When filtering logs, a priority is followed from top to bottom. If *:W is used, Warnings are displayed first followed by Errors then Fatal logs. Like in the sample above. Thus, filtering with Verbose (default) will display the logs starting from Verbose down to Fatal.

Furthermore, you can also filter logs with a keyword. Try this (this only works on a Unix-like environment, such as Mac OS X or Linux):

<your android sdk directory>/platform-tools/adb logcat | grep -i <keyword>

For example, doing this ...

<your android sdk directory>/platform-tools/adb logcat | grep -i exception

... would result to something like the following:

W/System.err(  719): java.lang.SecurityException: WifiService: Neither user 10032 nor current process has android.permission.CHANGE_WIFI_STATE.
W/System.err( 3819): java.lang.NullPointerException
W/System.err(  719): java.lang.SecurityException: WifiService: Neither user 10324 nor current process has android.permission.CHANGE_WIFI_STATE.

The pipe (|) character means that logs from the logcat command of adb will be an input for grep (a command used to search for strings). The -i parameter of grep means ignore case.

Interrupting logcat

You can at any time interrupt the logcat command by pressing Ctrl+C in your terminal window. You should then have returned to your command line.

Congratulations!

You have completed this tutorial. You have successfully created an Android application purely on the command line.

#DevelopTheImpossible


Twitter Facebook LinkedIn Youtube Slideshare Github