The Missing Bit

Setting up an android app from scratch without IDE

I am starting Kotlin development for Android, and as for all my developments, I'd like to use vim and command line. There are many reasons motivating me to ues a bare setup without an IDE like controlling everything, using my current toolchain and learning.

This post will describe how to make a Hello World Android application using only a text editor and command line tools.

Preparing the Gradle project

Android applications are built using Gradle. Gradle is a build tool similar to Maven or Ant. The first step is then to create the project structure. For this, Gradle provides an init command.

After installing gradle and kotlin on your platform.

On ArchLinux:

pacman -S gradle kotlin android-tools android-udev

You must also install some android SDK, on Archlinux, you must install the following AUR:

  • android-sdk
  • android-sdk-platform-tools
  • android-sdk-build-tools
  • android-platform

You can install specific version if you want, search AUR repository to see what is available. For the following project, be sure to have the following versions:

  • android-sdk-build-tools-28.0.3

If you are not on ArchLinux, you must use the android tool, sdkmanager to install the SDK.

Also, be sure to have your environment var ANDROID_HOME set to the proper path. On Archlinux with the above package it should be set to /opt/android-sdk. You can add android tools to your path for easier invocation, on Archlinux the paths to add to PATH are:

  • /opt/android-sdk/platform-tools/
  • /opt/android-sdk/tools/bin/
  • /opt/android-sdk/emulator/

When the dependencies are installed, create the project.

$ mkdir myproject
$ cd myproject
$ gradle init

Select type of project to generate:
  1: basic
  2: application
  3: library
  4: Gradle plugin
Enter selection (default: basic) [1..4] 2

Select implementation language:
  1: C++
  2: Groovy
  3: Java
  4: Kotlin
  5: Swift
Enter selection (default: Java) [1..5] 4

Select build script DSL:
  1: Groovy
  2: Kotlin
Enter selection (default: Kotlin) [1..2] 2

Project name (default: myproject):

Source package (default: myproject):


BUILD SUCCESSFUL in 20s
2 actionable tasks: 2 executed

This creates a project structure, the first things to do is to edit the .gitignore file to look like this:

#built application files
*.apk
*.ap_

# files for the dex VM
*.dex

# Java class files
*.class

# generated files
bin/
gen/

# Local configuration file (sdk path, etc)
local.properties

# Windows thumbnail db
Thumbs.db

# OSX files
.DS_Store

# Android Studio
*.iml
.idea
build/
.navigation
captures/
output.json

# Gradle cache
.gradle

#NDK
obj/
.externalNativeBuild

At this point, the project is configured to build a plain Java application. It is to be noted that the DSL used for Gradle configuration is Kotlin.

The app can be compiled with gradle build and run with gradle run. After runing gradle run you should see Helllo world printed.

Of course we want to generate an Android app, we will do this in the next section.

Configuring Gradle for Android

A lot of changes are required to actually create an Android application out of the created template.

The app module must be created and configured:

$ mkdir -p app/src/main/kotlin/<myproject>
$ echo 'include(":app")' >> settings.gradle.kts

edit build.gradle.kts and put the following content in it:

buildscript {
    repositories {
        jcenter()
        google()
    }

    dependencies {
        classpath("com.android.tools.build:gradle:3.5.2")
        classpath(kotlin("gradle-plugin", version = "1.3.61"))
    }
}

allprojects {
    repositories {
        jcenter()
        google()
    }
}

Check latest version of the build tools (3.5.2 here): https://developer.android.com/studio/releases/gradle-plugin.

Check the latest version of the kotlin gradle plugin (1.3.61 here): https://kotlinlang.org/docs/reference/using-gradle.html#plugin-and-versions.

A few files must be created by hand:

app/build.gradle.kts

plugins {
    id("com.android.application")
    kotlin("android")
    kotlin("android.extensions")
    kotlin("kapt")
}

android {
    compileSdkVersion(29)
    defaultConfig {
        applicationId = "com.<myproject>"
        minSdkVersion(15)
        targetSdkVersion(29)
        versionCode = 1
        versionName = "1.0"
    }
}


dependencies {
    implementation(fileTree(mapOf("dir" to "libs", "include" to listOf("*.jar"))))
    implementation(kotlin("stdlib"))
}

app/src/main/AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.<myproject>">

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

app/src/main/kotlin/<myproject>/MainActivity.kt


package com.<myproject>

import android.app.Activity
import android.os.Bundle
import android.widget.TextView
import android.view.Window

class MainActivity : Activity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        this.requestWindowFeature(Window.FEATURE_NO_TITLE)
        var textView = TextView(this)
        textView.setText("Hello world")
        setContentView(textView)
    }
}

Also, you can remove the src directory:

$ rm -fr src

After doing all this, your file tree should look like this:

.
├── app
   ├── build.gradle.kts
   └── src
       └── main
           ├── AndroidManifest.xml
           └── kotlin
               └── <myproject>
                   └── MainActivity.kt
├── build.gradle.kts
├── gradle
   └── wrapper
       ├── gradle-wrapper.jar
       └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
└── settings.gradle.kts

You should be able to build your .apk with: gradle assembleDebug

Run the minimal Android app

To run the app on linux, we need to create an Android virtual device (avd). First we must install a system image. You can use sdkmanager for this, but on Archlinux you can simply install the AUR android-x86-64-system-image-29.

Then create a virtual device with:

$ avdmanager create avd --force \
  --name main \
  --abi default/x86_64 \
  --package 'system-images;android-29;default;x86_64'

Launch the emulator with:

$ emulator -avd main

Once the emulator is running, you can install the app on it with adb:

$ adb -e install app/build/outputs/apk/debug/app-debug.apk

Run the app with:

$ adb shell am start -n com.<myproject>/com.<myproject>.MainActivity

You should see a small text saying Hello world.

Conclusion

Creating and running an app without android studio is quite complicated, but I am very satisfied, because I know have a good understanding of all components.

I will continue to work to create a good setup for continuous app developement and share my finding on this blog.