Skip to content

Commit 0e0282a

Browse files
authored
Third party example for android native: endless-tunnel (#5053)
Following the work on #5013 I've added a third party example for Android native. I included an `androidRun` command as a testing motivation . (which we can connect to run and subsequently to IDE BSP run in the future) The example increases confidence on building android native apps with mill and it is another milestone for Mill's android support . https://github.com/user-attachments/assets/a442a185-4b45-4342-9d78-3c1fe726873b
1 parent 670035f commit 0e0282a

File tree

4 files changed

+116
-2
lines changed

4 files changed

+116
-2
lines changed

.github/workflows/run-tests.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,11 @@ jobs:
181181
install-android-sdk: true
182182
install-sbt: false
183183

184+
- java-version: 17
185+
millargs: "'example.thirdparty[android-endless-tunnel].local.server'"
186+
install-android-sdk: true
187+
install-sbt: false
188+
184189
- java-version: 17
185190
millargs: "'{example,integration}.migrating.__.local.server'"
186191
install-android-sdk: false

example/package.mill

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -316,7 +316,8 @@ $txt
316316
"gatling" -> ("gatling/gatling", "3870fda86e6bca005fbd53108c60a65db36279b6"),
317317
"arrow" -> ("arrow-kt/arrow", "bc9bf92cc98e01c21bdd2bf8640cf7db0f97204a"),
318318
"ollama-js" -> ("ollama/ollama-js", "99293abe2c7c27ce7e76e8b4a98cae948f00058d"),
319-
"androidtodo" -> ("android/architecture-samples", "b3437ab428f6fd91804b28801650d590ff52971c")
319+
"androidtodo" -> ("android/architecture-samples", "b3437ab428f6fd91804b28801650d590ff52971c"),
320+
"android-endless-tunnel" -> ("android/ndk-samples", "46ac919196faf1efcfe8018a0dcc79d4f8fbeca7")
320321
)
321322
object thirdparty extends Cross[ThirdPartyModule](build.listIn(moduleDir / "thirdparty"))
322323
trait ThirdPartyModule extends ExampleCrossModule {
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
// This is how endless-tunnel from android ndk-sample can be built with mill.
2+
// The original code is in https://github.com/android/ndk-samples/tree/main/endless-tunnel
3+
4+
package build
5+
6+
import mill._, androidlib._, scalalib._
7+
8+
object androidSdkModule0 extends AndroidSdkModule {
9+
def buildToolsVersion = "35.0.0"
10+
}
11+
12+
object `endless-tunnel` extends mill.define.Module {
13+
object app extends AndroidNativeAppModule {
14+
15+
def androidSdkModule = mill.define.ModuleRef(androidSdkModule0)
16+
17+
def androidMinSdk = 19
18+
19+
def androidCompileSdk = 35
20+
21+
def androidApplicationId = "com.google.sample.tunnel"
22+
23+
def androidApplicationNamespace = "com.google.sample.tunnel"
24+
25+
override def androidNativeLibName: T[String] = "libgame"
26+
27+
/**
28+
* Configuration for ReleaseKey
29+
* WARNING: Replace these default values with secure and private credentials before using in production.
30+
* Never use these defaults in a production environment as they are not secure.
31+
* This is just for testing purposes.
32+
*/
33+
def androidReleaseKeyAlias: T[Option[String]] = Task {
34+
Some("releaseKey")
35+
}
36+
37+
def androidReleaseKeyPass: T[Option[String]] = Task {
38+
Some("MillBuildTool")
39+
}
40+
41+
def androidReleaseKeyStorePass: T[Option[String]] = Task {
42+
Some("MillBuildTool")
43+
}
44+
45+
override def androidVirtualDeviceIdentifier: String = "cpp-test"
46+
47+
override def androidCMakeExtraArgs: T[Seq[String]] =
48+
super.androidCMakeExtraArgs() ++ Seq("-DANDROID_STL=c++_static")
49+
50+
}
51+
}
52+
53+
/** Usage
54+
55+
> ./mill show endless-tunnel.app.androidApk
56+
".../out/endless-tunnel/app/androidApk.dest/app.apk"
57+
58+
> ./mill show endless-tunnel.app.createAndroidVirtualDevice
59+
...Name: cpp-test, DeviceId: medium_phone...
60+
61+
> ./mill show endless-tunnel.app.startAndroidEmulator
62+
63+
> ./mill show endless-tunnel.app.androidInstall
64+
...All files should be loaded. Notifying the device...
65+
66+
> ./mill show endless-tunnel.app.androidRun --activity android.app.NativeActivity
67+
[
68+
"Starting: Intent { cmp=com.google.sample.tunnel/android.app.NativeActivity }",
69+
"Status: ok",
70+
"LaunchState: COLD",
71+
"Activity: com.google.sample.tunnel/android.app.NativeActivity",
72+
"TotalTime: ...",
73+
"WaitTime: ...",
74+
"Complete"
75+
]
76+
77+
> ./mill show endless-tunnel.app.stopAndroidEmulator
78+
79+
> ./mill show endless-tunnel.app.deleteAndroidVirtualDevice
80+
81+
*/

libs/androidlib/src/mill/androidlib/AndroidAppModule.scala

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -666,7 +666,7 @@ trait AndroidAppModule extends AndroidModule { outer =>
666666
androidInstallTask()
667667
}
668668

669-
def androidInstallTask = Task.Anon {
669+
def androidInstallTask: Task[String] = Task.Anon {
670670
val emulator = runningEmulator()
671671

672672
os.call(
@@ -676,6 +676,33 @@ trait AndroidAppModule extends AndroidModule { outer =>
676676
emulator
677677
}
678678

679+
/**
680+
* Run your application by providing the activity.
681+
*
682+
* E.g. `com.package.name.ActivityName`
683+
*
684+
* See also [[https://developer.android.com/tools/adb#am]] and [[https://developer.android.com/tools/adb#IntentSpec]]
685+
* @param activity
686+
* @return
687+
*/
688+
def androidRun(activity: String): Command[Vector[String]] = Task.Command(exclusive = true) {
689+
val emulator = runningEmulator()
690+
691+
os.call(
692+
(
693+
androidSdkModule().adbPath().path,
694+
"-s",
695+
emulator,
696+
"shell",
697+
"am",
698+
"start",
699+
"-n",
700+
s"${androidApplicationNamespace}/${activity}",
701+
"-W"
702+
)
703+
).out.lines()
704+
}
705+
679706
/**
680707
* Default os.Path to the keystore file, derived from `androidReleaseKeyName()`.
681708
* Users can customize the keystore file name to change this path.

0 commit comments

Comments
 (0)