If you're looking to develop an Android app you might be led to Android Studio. It's the IDE recommended and developed by Google for the express purpose of Android development. It does what it needs to, but if you look at the system requirements you will see some alarming numbers. If you're using an older system, or simply don't want to use AndroidStudio, this is the guide for you.
We won't be using many apt packages due to permissions issues and incompatible versions. That being said:
$ sudo apt install openjdk-17-jdk sdkmanager kotlin
You will now need to download Gradle. Follow the guide here https://gradle.org/install/ and then edit your .bashrc
to add:
export PATH="$PATH:/opt/gradle/gradle-<VERSION>/bin/"
Fill the <VERSION>
with the Gradle version you installed, in my case 8.2.1.
You'll need to pick where you want the SDK to go. It should be readable and writable by your user, otherwise sdkmanager won't be able to modify its settings files and can't accept its licenses. Let's assume your username is user
and we'll install to ~/android-sdk
. Add the following to your .bashrc
:
export ANDROID_HOME=~/android-sdk
Then, in a new Bash shell (to refresh .bashrc
), install the SDK:
$ mkdir ~/android-sdk
$ sdkmanager --sdk_root=/home/user/android-sdk "platform-tools" "build-tools;33.0.2" "platforms;android-33" "cmdline-tools;latest"
If you see it wanting to install to /opt then open a new Bash shell.
Accept the license agreements:
$ sdkmanager --licenses
Initialize a Gradle project in an empty directory:
$ mkdir example
$ cd example
$ 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: Scala
6: Swift
Enter selection (default: Java) [1..6] 4
Generate multiple subprojects for application? (default: no) [yes, no] no
Select build script DSL:
1: Kotlin
2: Groovy
Enter selection (default: Kotlin) [1..2] 1
Project name (default: example):
Source package (default: example):
Enter target version of Java (min. 7) (default: 17):
Generate build using new APIs and behavior (some features may change in the next minor release)? (default: no) [yes, no]
> Task :init
To learn more about Gradle by exploring our Samples at https://docs.gradle.org/8.2.1/samples/sample_building_kotlin_applications.html
BUILD SUCCESSFUL in 22s
2 actionable tasks: 2 executed
You can overwrite the .gitignore file with:
# Ignore Gradle project-specific cache directory
.gradle
# Ignore Gradle build output directory
build
#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
.navigation
captures/
output.json
#NDK
obj/
.externalNativeBuild
Make sure to run gradle build
and gradle run
to ensure the Hello world!
example works. If not, you might have misconfigured packages.
Make sure to check for the newest versions of Android Build Gradle (https://developer.android.com/build/releases/gradle-plugin) and Kotlin Gradle (https://kotlinlang.org/docs/gradle-configure-project.html). The values in this example are up to date as of August 2023. In the root of your project directory add or overwrite build.gradle.kts
with:
buildscript {
repositories {
mavenCentral()
google()
}
dependencies {
classpath("com.android.tools.build:gradle:8.1.0")
classpath(kotlin("gradle-plugin", version = "1.9.0"))
}
}
allprojects {
repositories {
mavenCentral()
google()
}
}
Add or overwrite app/build.gradle.kts
with:
plugins {
id("com.android.application")
kotlin("android")
kotlin("kapt")
}
android {
compileSdk = 30
namespace = "example.example"
buildFeatures {
viewBinding = true
}
defaultConfig {
applicationId = "example.example"
minSdk = 15
targetSdk = 31
versionCode = 1
versionName = "1.0"
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
}
kotlinOptions {
jvmTarget = "17"
}
}
dependencies {
implementation(fileTree(mapOf("dir" to "libs", "include" to listOf("*.jar"))))
implementation(kotlin("stdlib"))
}
Add or overwrite app/src/main/AndroidManifest.xml
with:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<application
android:allowBackup="true"
android:supportsRtl="true">
<activity android:exported="true" android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
Add or overwrite app/src/main/kotlin/example/MainActivity.kt
(make sure it's .kt
) with:
package example.example
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)
}
}
A test file will have been autogenerated, delete it (app/src/test/kotlin/example/AppTest.kt
), also delete the default main file (app/src/main/kotlin/example/App.kt
).
You should now be able to run gradle assembleDebug
to make a debug build and gradle assemble
for a release build.
Note: for a real app, change the example
and example.example
fields in the configuration to the actual names/reverse domains of your app and organization.
Note: Waydroid requires about 1 GB of free RAM in order to start. If you notice it failing to start, make sure you have enough RAM. You may need to close some programs.
We'll use Waydroid in a Weston window to test the app. This is an alternative to avdmanager that uses LineageOS and is better integrated with Linux. Get the Waydroid repository set up according to https://docs.waydro.id/usage/install-on-desktops:
$ sudo apt install curl ca-certificates
$ curl https://repo.waydro.id | sudo bash
And install the necessary packages:
$ sudo apt install waydroid weston iptables
Initialize Waydroid:
$ sudo waydroid init
Note: If you are running in a virtual machine or if you have an Nvidia GPU, enable software rendering according to https://docs.waydro.id/faq/get-waydroid-to-work-through-a-vm
Then start up a Weston window:
$ weston -B x11-backend.so -s waydroidweston
Click the terminal icon in the upper left hand corner, and launch Waydroid (it will report a failure to start the clipboard manager):
$ waydroid show-full-ui
Once it loads, go back to the terminal that's in your project directory and install the apk (either the debug or the release):
$ waydroid app install app/build/outputs/apk/debug/app-debug.apk
$ waydroid app install app/build/outputs/apk/release/app-release-unsigned.apk # this will not actually install anything, as it is unsigned
You can then open it from the launcher in Waydroid, you should see a blank app window with Hello, world
in the upper left hand corner.
You can close Waydroid using:
$ waydroid session stop
This guide is based on a prior guide written by Nicolas Goy/The Missing Bit: https://www.kuon.ch/post/2020-01-12-android-app/