Skip to content

Commit

Permalink
Fixes:#3550; Add hello-world Android Kotlin example using Mill
Browse files Browse the repository at this point in the history
  • Loading branch information
himanshumahajan138 committed Oct 7, 2024
1 parent cff9993 commit de65f0e
Show file tree
Hide file tree
Showing 7 changed files with 416 additions and 0 deletions.
1 change: 1 addition & 0 deletions docs/modules/ROOT/nav.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
* xref:kotlinlib/publishing.adoc[]
* xref:kotlinlib/build-examples.adoc[]
* xref:kotlinlib/web-examples.adoc[]
* xref:kotlinlib/android-examples.adoc[]
.Build Tool Comparisons
* xref:comparisons/maven.adoc[]
Expand Down
50 changes: 50 additions & 0 deletions docs/modules/ROOT/pages/kotlinlib/android-examples.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
= (Experimental) Android Builds
:page-aliases: android_app_kotlin_examples.adoc

++++
<script>
gtag('config', 'AW-16649289906');
</script>
++++

This page provides an example of using Mill as a build tool for Android applications.
This workflow is still pretty rough and nowhere near production ready, but can serve as
a starting point for further experimentation and development.

== Relevant Modules

These are the main Mill Modules that are relevant for building Android apps:

* {mill-doc-url}/api/latest/mill/scalalib/AndroidSdkModule.html[`mill.scalalib.AndroidSdkModule`]: Handles Android SDK management and tools.
* {mill-doc-url}/api/latest/mill/kotlinlib/android/AndroidAppModule.html[`mill.kotlinlib.android.AndroidAppModule`]: Provides a framework for building Android applications.
* {mill-doc-url}/api/latest/mill/kotlinlib/KotlinModule.html[`mill.kotlinlib.KotlinModule`]: General Kotlin build tasks like compiling Kotlin code and creating JAR files.

== Simple Android Hello World Application

include::partial$example/kotlinlib/android/1-hello-world.adoc[]

This example demonstrates how to create a basic "Hello World" Android application
using the Mill build tool. It outlines the minimum setup required to compile Kotlin code,
package it into an APK, and run the app on an Android device.

== Understanding `AndroidSdkModule` and `AndroidAppModule`

The two main modules you need to understand when building Android apps with Mill
are `AndroidSdkModule` and `AndroidAppModule`.

`AndroidSdkModule`:

* This module manages the installation and configuration of the Android SDK, which includes
tools like `aapt`, `d8`, `zipalign`, and `apksigner`. These tools are used
for compiling, packaging, and signing Android applications.

`AndroidAppModule`:
This module provides the step-by-step workflow for building an Android app. It handles
everything from compiling the code to generating a signed APK for distribution.

1. **Compiling Kotlin code**: The module compiles your Kotlin code into `.class` files, which is the first step in creating an Android app.
2. **Packaging into JAR**: It then packages the compiled `.class` files into a JAR file, which is necessary before converting to Android's format.
3. **Converting to DEX format**: The JAR file is converted into DEX format, which is the executable format for Android applications.
4. **Creating an APK**: The DEX files and Android resources (like layouts and strings) are packaged together into an APK file, which is the installable file for Android devices.
5. **Optimizing with zipalign**: The APK is optimized using `zipalign` to ensure better performance on Android devices.
6. **Signing the APK**: Finally, the APK is signed with a digital signature, allowing it to be distributed and installed on Android devices.
13 changes: 13 additions & 0 deletions example/kotlinlib/android/1-hello-world/app/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.helloworld.app">
<uses-sdk android:minSdkVersion="9"/>
<uses-sdk android:targetSdkVersion="35"/>
<application android:label="Hello World" android:debuggable="true">
<activity android:name=".MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
</application>
</manifest>
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package com.helloworld.app

import android.app.Activity
import android.os.Bundle
import android.widget.TextView
import android.view.Gravity
import android.view.ViewGroup.LayoutParams

class MainActivity : Activity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)

// Create a new TextView
val textView = TextView(this)

// Set the text to "Hello, World!"
textView.text = "Hello, World!"

// Set text size
textView.textSize = 32f

// Center the text within the view
textView.gravity = Gravity.CENTER

// Set layout parameters (width and height)
textView.layoutParams = LayoutParams(
LayoutParams.MATCH_PARENT,
LayoutParams.MATCH_PARENT
)

// Set the content view to display the TextView
setContentView(textView)
}
}
58 changes: 58 additions & 0 deletions example/kotlinlib/android/1-hello-world/build.mill
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
// This section sets up a basic Android project using Mill.
// We utilize `AndroidAppModule` and `AndroidSdkModule` to streamline the process of
// building an Android application with minimal configuration.
//
// By extending `AndroidAppModule`, we inherit all Android-related tasks such as
// resource generation, APK building, DEX conversion, and APK signing.
// Additionally, `AndroidSdkModule` is embedded, making SDK management seamless.

//// SNIPPET:BUILD
package build

import mill._
import kotlinlib._
import mill.kotlinlib.android.AndroidAppModule
import mill.javalib.android.AndroidSdkModule

// Create and configure an Android SDK module to manage Android SDK paths and tools.
object androidSdkModule0 extends AndroidSdkModule{
def buildToolsVersion = "35.0.0"
}

// Actual android application
object app extends AndroidAppModule {

def kotlinVersion = "2.0.0"
def androidSdkModule = mill.define.ModuleRef(androidSdkModule0)
}

////SNIPPET:END


/** Usage

> ./mill show app.androidApk
".../out/app/androidApk.dest/app.apk"

*/

// This command triggers the build process, which installs the Android Setup, compiles the kotlin
// code, generates Android resources, converts kotlin bytecode to DEX format, packages everything
// into an APK, optimizes the APK using `zipalign`, and finally signs it.
//
// This Mill build configuration is designed to build a simple "Hello World" Android application.
// By extending `AndroidAppModule`, we leverage its predefined Android build tasks, ensuring that
// all necessary steps (resource generation, APK creation, and signing) are executed automatically.
//
// ### Project Structure:
// The project follows the standard Android app layout. Below is a typical project folder structure:
//
// ----
// .
// ├── build.mill
// ├── AndroidManifest.xml
// └── src/main/kotlin
// └── com/helloworld/app
// └── MainActivity.kt
// ----
//
1 change: 1 addition & 0 deletions example/package.mill
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ object `package` extends RootModule with Module {
object web extends Cross[ExampleCrossModule](build.listIn(millSourcePath / "web"))
}
object kotlinlib extends Module {
object android extends Cross[ExampleCrossModuleJava](build.listIn(millSourcePath / "android"))
object basic extends Cross[ExampleCrossModuleKotlin](build.listIn(millSourcePath / "basic"))
object module extends Cross[ExampleCrossModuleKotlin](build.listIn(millSourcePath / "module"))
object dependencies extends Cross[ExampleCrossModuleKotlin](build.listIn(millSourcePath / "dependencies"))
Expand Down
Loading

0 comments on commit de65f0e

Please sign in to comment.