From 646b4292574b7042fc167bc6157235b7a6157a14 Mon Sep 17 00:00:00 2001 From: Vasilis Nicolaou Date: Tue, 27 May 2025 11:24:42 +0300 Subject: [PATCH] Android: Standardize the use of application id and namespace --- example/thirdparty/androidtodo/build.mill | 6 +-- .../mill/androidlib/AndroidAppModule.scala | 37 +++++++++---------- .../src/mill/androidlib/AndroidModule.scala | 14 ++----- .../mill/androidlib/AndroidSdkModule.scala | 2 +- 4 files changed, 24 insertions(+), 35 deletions(-) diff --git a/example/thirdparty/androidtodo/build.mill b/example/thirdparty/androidtodo/build.mill index 6a185cb028e..13c6a256bac 100644 --- a/example/thirdparty/androidtodo/build.mill +++ b/example/thirdparty/androidtodo/build.mill @@ -26,7 +26,7 @@ object app extends AndroidAppKotlinModule with AndroidBuildConfig with AndroidHi def androidApplicationNamespace = "com.example.android.architecture.blueprints.todoapp" // TODO change this to com.example.android.architecture.blueprints.main when mill supports build variants - def androidApplicationId = "com.example.android.architecture.blueprints.todoapp" + def androidApplicationId = "com.example.android.architecture.blueprints.main" def androidSdkModule = mill.define.ModuleRef(androidSdkModule0) @@ -177,10 +177,10 @@ object `shared-test` extends AndroidKotlinModule with AndroidHiltSupport { > ./mill show app.androidRun --activity com.example.android.architecture.blueprints.todoapp.TodoActivity [ - "Starting: Intent { cmp=com.example.android.architecture.blueprints.todoapp/.TodoActivity }", + "Starting: Intent { cmp=com.example.android.architecture.blueprints.main/com.example.android.architecture.blueprints.todoapp.TodoActivity }", "Status: ok", "LaunchState: COLD", - "Activity: com.example.android.architecture.blueprints.todoapp/.TodoActivity", + "Activity: com.example.android.architecture.blueprints.main/com.example.android.architecture.blueprints.todoapp.TodoActivity", "TotalTime: ...", "WaitTime: ...", "Complete" diff --git a/libs/androidlib/src/mill/androidlib/AndroidAppModule.scala b/libs/androidlib/src/mill/androidlib/AndroidAppModule.scala index 8a8bc555473..09d257e7459 100644 --- a/libs/androidlib/src/mill/androidlib/AndroidAppModule.scala +++ b/libs/androidlib/src/mill/androidlib/AndroidAppModule.scala @@ -60,10 +60,10 @@ trait AndroidAppModule extends AndroidModule { outer => protected val debugKeyPass = "mill-android" /** - * The namespace of the android application which is used - * to specify the fully qualified classpath of the activity. + * Every Android module has a namespace, + * which is used as the Kotlin or Java package name for its generated R and BuildConfig classes. * - * For instance, it is used as the package name in Android Manifest + * See more in [[https://developer.android.com/build/configure-app-module#set-namespace]] */ def androidApplicationNamespace: String @@ -74,10 +74,8 @@ trait AndroidAppModule extends AndroidModule { outer => override final def androidNamespace: String = androidApplicationNamespace /** - * Android Application Id which is typically package.main . - * Can be used for build variants. - * - * Build variant feature is not yet implemented! + * Android Application Id unique to every android application. + * See more in [[https://developer.android.com/build/configure-app-module#set-application-id]] */ def androidApplicationId: String @@ -92,19 +90,15 @@ trait AndroidAppModule extends AndroidModule { outer => * TODO dynamically add android:debuggable */ override def androidManifest: T[PathRef] = Task { - val manifestFromSourcePath = moduleDir / "src/main/AndroidManifest.xml" + val manifestFromSourcePath = androidManifestLocation().path val manifestElem = XML.loadFile(manifestFromSourcePath.toString()) // add the application package val manifestWithPackage = - manifestElem % Attribute(None, "package", Text(androidApplicationNamespace), Null) - - val manifestWithUsesSdk = manifestWithPackage.copy( - child = androidManifestUsesSdkSection() ++ manifestWithPackage.child - ) + manifestElem % Attribute(None, "package", Text(androidNamespace), Null) val generatedManifestPath = Task.dest / "AndroidManifest.xml" - os.write(generatedManifestPath, manifestWithUsesSdk.mkString) + os.write(generatedManifestPath, manifestWithPackage.mkString) PathRef(generatedManifestPath) } @@ -294,6 +288,10 @@ trait AndroidAppModule extends AndroidModule { outer => s"version_code=${androidVersionCode()}", "--property", s"version_name=${androidVersionName()}", + "--property", + s"package=${androidApplicationId}", + "--manifest-placeholders", + s"applicationId=${androidApplicationId}", "--out", mergedManifestPath.toString() ) ++ libManifests.flatMap(m => Seq("--libs", m.path.toString())), @@ -671,7 +669,7 @@ trait AndroidAppModule extends AndroidModule { outer => "am", "start", "-n", - s"${androidApplicationNamespace}/${activity}", + s"${androidApplicationId}/${activity}", "-W" ) ).out.lines() @@ -683,7 +681,7 @@ trait AndroidAppModule extends AndroidModule { outer => */ def androidReleaseKeyPath: T[Seq[PathRef]] = { val subPaths = androidReleaseKeyName.map(os.sub / _).toSeq - Task.Sources(subPaths: _*) + Task.Sources(subPaths*) } /* @@ -1057,7 +1055,7 @@ trait AndroidAppModule extends AndroidModule { outer => override def androidSdkModule: ModuleRef[AndroidSdkModule] = outer.androidSdkModule override def androidManifest: T[PathRef] = outer.androidManifest() - override def androidApplicationId: String = outer.androidApplicationId + override def androidApplicationId: String = s"${outer.androidApplicationId}.test" override def androidApplicationNamespace: String = s"${outer.androidApplicationNamespace}.test" @@ -1086,7 +1084,7 @@ trait AndroidAppModule extends AndroidModule { outer => override def resolutionParams: Task[ResolutionParams] = Task.Anon(outer.resolutionParams()) - override def androidApplicationId: String = s"${outer.androidApplicationId}" + override def androidApplicationId: String = s"${outer.androidApplicationId}.test" override def androidApplicationNamespace: String = s"${outer.androidApplicationNamespace}.test" override def androidReleaseKeyAlias: T[Option[String]] = outer.androidReleaseKeyAlias() @@ -1105,7 +1103,7 @@ trait AndroidAppModule extends AndroidModule { outer => private def androidInstrumentedTestsBaseManifest: Task[Elem] = Task.Anon { {androidManifestUsesSdkSection()} @@ -1129,7 +1127,6 @@ trait AndroidAppModule extends AndroidModule { outer => val destManifest = Task.dest / "AndroidManifest.xml" os.write(destManifest, manifestWithInstrumentation.toString) PathRef(destManifest) - } override def androidVirtualDeviceIdentifier: String = outer.androidVirtualDeviceIdentifier diff --git a/libs/androidlib/src/mill/androidlib/AndroidModule.scala b/libs/androidlib/src/mill/androidlib/AndroidModule.scala index 061c12050ca..2966656b6bc 100644 --- a/libs/androidlib/src/mill/androidlib/AndroidModule.scala +++ b/libs/androidlib/src/mill/androidlib/AndroidModule.scala @@ -47,18 +47,14 @@ trait AndroidModule extends JavaModule { */ def androidSdkModule: ModuleRef[AndroidSdkModule] - private def androidManifestUsesSdkSection: Task[Elem] = Task.Anon { - val minSdkVersion = androidMinSdk().toString - val targetSdkVersion = androidTargetSdk().toString - - } + def androidManifestLocation: T[PathRef] = Task.Source("src/main/AndroidManifest.xml") /** * Provides os.Path to an XML file containing configuration and metadata about your android application. * TODO dynamically add android:debuggable */ def androidManifest: T[PathRef] = Task { - val manifestFromSourcePath = moduleDir / "src/main/AndroidManifest.xml" + val manifestFromSourcePath = androidManifestLocation().path val manifestElem = XML.loadFile(manifestFromSourcePath.toString()) % Attribute(None, "xmlns:android", Text("http://schemas.android.com/apk/res/android"), Null) @@ -66,12 +62,8 @@ trait AndroidModule extends JavaModule { val manifestWithPackage = manifestElem % Attribute(None, "package", Text(androidNamespace), Null) - val manifestWithUsesSdk = manifestWithPackage.copy( - child = androidManifestUsesSdkSection() ++ manifestWithPackage.child - ) - val generatedManifestPath = Task.dest / "AndroidManifest.xml" - os.write(generatedManifestPath, manifestWithUsesSdk.mkString) + os.write(generatedManifestPath, manifestWithPackage.mkString) PathRef(generatedManifestPath) } diff --git a/libs/androidlib/src/mill/androidlib/AndroidSdkModule.scala b/libs/androidlib/src/mill/androidlib/AndroidSdkModule.scala index 1bb8cafbcaf..269c89f7e19 100644 --- a/libs/androidlib/src/mill/androidlib/AndroidSdkModule.scala +++ b/libs/androidlib/src/mill/androidlib/AndroidSdkModule.scala @@ -40,7 +40,7 @@ trait AndroidSdkModule extends Module { /** * Specifies the version of the Manifest Merger. */ - def manifestMergerVersion: T[String] = "31.7.3" + def manifestMergerVersion: T[String] = "31.10.0" /** * Specifies the version of the Android build tools to be used.