Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixes: #3550 ; Add hello-world Android Java Example using Mill #3659

Merged
merged 9 commits into from
Oct 5, 2024
1 change: 1 addition & 0 deletions docs/modules/ROOT/nav.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
.xref:javalib/intro.adoc[]
* xref:javalib/installation-ide.adoc[]
* xref:javalib/builtin-commands.adoc[]
* xref:javalib/android-examples.adoc[]
* xref:javalib/module-config.adoc[]
* xref:javalib/dependencies.adoc[]
* xref:javalib/testing.adoc[]
Expand Down
63 changes: 63 additions & 0 deletions docs/modules/ROOT/pages/javalib/android-examples.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
= Android Build Examples
:page-aliases: android_app_examples.adoc

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

This page provides examples of using Mill as a build tool for Android applications.
Each example highlights a specific aspect of Mill, allowing you to configure, test, and build Android apps efficiently.
By the end of this guide, you will understand how Mill can manage Android project structures, compile modules, and handle APK packaging.

For detailed information, refer to Mill's https://com-lihaoyi.github.io/mill[official documentation],
and the https://developer.android.com/studio[Android Developer Guide].

== 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/javalib/android/AndroidAppModule.html[`mill.javalib.android.AndroidAppModule`]: Provides a framework for building Android applications.
* {mill-doc-url}/api/latest/mill/scalalib/JavaModule.html[`mill.scalalib.JavaModule`]: General Java build tasks like compiling Java code and creating JAR files.

== Simple Android Hello World Application

include::partial$example/javalib/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 Java 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 crucial 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 Java code**: The module compiles your Java 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.

== Testing Your Application

You can perform manual testing on your Android APK to ensure it functions as expected. The Mill team is working on automating testing procedures for Android applications, which will be shared in future updates.

== Why Use Mill for Android Development?

Mill provides several advantages over other build tools, including:

* **Efficiency**: Mill's build process is fast and optimized for minimal configuration, which speeds up the Android app creation process.

* **Modularity**: Mill allows you to easily extend and customize your builds by leveraging its modular design.

* **Scalability**: Mill can scale well for larger projects while maintaining simplicity in configuration.

By using Mill, you can streamline your Android app development, saving time and reducing complexity.
69 changes: 69 additions & 0 deletions example/javalib/android/1-hello-world/build.mill
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
// 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 mill.javalib.android.{AndroidAppModule, AndroidSdkModule}

object `package` extends RootModule with AndroidAppModule {

// Create and configure an Android SDK module to manage Android SDK paths and tools.
object androidSdkModule extends AndroidSdkModule

}

////SNIPPET:END


/** Usage

> ./mill androidApk

*/

// This command triggers the build process, which installs the Android Setup, compiles the Java
// code, generates Android resources, converts Java 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
// └── src
// └── main
// ├── AndroidManifest.xml
// └── java
// └── com
// └── helloworld
// └── app
// └── MainActivity.java
// ----
//
// ### Mill Modules Overview:
//
// This project relies on three main modules:
//
// 1. **`AndroidSdkModule`**: This module manages all Android SDK interactions, including
// tools like `aapt` for resource packaging, `d8` for bytecode conversion, and `apksigner` for signing APKs.
//
// 2. **`JavaModule`**: This provides Java compilation tasks, including class file generation
// and creating JAR files, which are later converted to DEX format for Android.
//
// 3. **`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.
//
// The combination of these modules allows us to automate the entire build process,
// from compiling Java code to producing a signed APK ready for distribution.
13 changes: 13 additions & 0 deletions example/javalib/android/1-hello-world/src/main/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,36 @@
package com.helloworld.app;

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


public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

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

// Set the text to "Hello, World!"
textView.setText("Hello, World!");

// Set text size
textView.setTextSize(32);

// Center the text within the view
textView.setGravity(Gravity.CENTER);

// Set layout parameters (width and height)
textView.setLayoutParams(new LayoutParams(
LayoutParams.MATCH_PARENT,
LayoutParams.MATCH_PARENT));

// Set the content view to display the TextView
setContentView(textView);
}
}
1 change: 1 addition & 0 deletions example/package.mill
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ object `package` extends RootModule with Module {
.collect { case m: ExampleCrossModule => m }

object javalib extends Module {
object android extends Cross[ExampleCrossModuleJava](build.listIn(millSourcePath / "android"))
object basic extends Cross[ExampleCrossModuleJava](build.listIn(millSourcePath / "basic"))
object module extends Cross[ExampleCrossModuleJava](build.listIn(millSourcePath / "module"))
object dependencies extends Cross[ExampleCrossModuleJava](build.listIn(millSourcePath / "dependencies"))
Expand Down
Loading
Loading