Skip to content

Commit ce62087

Browse files
authored
Android: Standardize the use of application id and namespace (#5210)
This PR standardises the use of application id and namespace. It is also one of the pre-requisites of making hilt instrumented tests to work. The application id is a unique id for every android app , so the android manifest package depends on it. The android manifest package is also used whenever there's a relative path for Applications and activities so ```xml <manifest package="com.foo"> <application android:name=".TodoApplication"/> </manifest> ``` Becomes ```xml <manifest package="com.foo"> <application android:name="com.foo.TodoApplication"/> </manifest> ``` During manifest merging. Because this happens when the manifest is loaded (before everything is merged) we start with the manifest package being the android namespace. We then pass the package property to the merger to be the application id (the package for each up is unique). This is what appears to be happening in AGP as well. (It is also the reason why I was confused when reverse engineering the AGP behaviour and was alternating between namespace and application id) I've also cleaned up some of the xml manual modifications that are not needed anymore as are handled by the merger tool
1 parent 4216a39 commit ce62087

File tree

4 files changed

+24
-35
lines changed

4 files changed

+24
-35
lines changed

example/thirdparty/androidtodo/build.mill

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ object app extends AndroidAppKotlinModule with AndroidBuildConfig with AndroidHi
2626

2727
def androidApplicationNamespace = "com.example.android.architecture.blueprints.todoapp"
2828
// TODO change this to com.example.android.architecture.blueprints.main when mill supports build variants
29-
def androidApplicationId = "com.example.android.architecture.blueprints.todoapp"
29+
def androidApplicationId = "com.example.android.architecture.blueprints.main"
3030

3131
def androidSdkModule = mill.define.ModuleRef(androidSdkModule0)
3232

@@ -177,10 +177,10 @@ object `shared-test` extends AndroidKotlinModule with AndroidHiltSupport {
177177

178178
> ./mill show app.androidRun --activity com.example.android.architecture.blueprints.todoapp.TodoActivity
179179
[
180-
"Starting: Intent { cmp=com.example.android.architecture.blueprints.todoapp/.TodoActivity }",
180+
"Starting: Intent { cmp=com.example.android.architecture.blueprints.main/com.example.android.architecture.blueprints.todoapp.TodoActivity }",
181181
"Status: ok",
182182
"LaunchState: COLD",
183-
"Activity: com.example.android.architecture.blueprints.todoapp/.TodoActivity",
183+
"Activity: com.example.android.architecture.blueprints.main/com.example.android.architecture.blueprints.todoapp.TodoActivity",
184184
"TotalTime: ...",
185185
"WaitTime: ...",
186186
"Complete"

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

Lines changed: 17 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -60,10 +60,10 @@ trait AndroidAppModule extends AndroidModule { outer =>
6060
protected val debugKeyPass = "mill-android"
6161

6262
/**
63-
* The namespace of the android application which is used
64-
* to specify the fully qualified classpath of the activity.
63+
* Every Android module has a namespace,
64+
* which is used as the Kotlin or Java package name for its generated R and BuildConfig classes.
6565
*
66-
* For instance, it is used as the package name in Android Manifest
66+
* See more in [[https://developer.android.com/build/configure-app-module#set-namespace]]
6767
*/
6868
def androidApplicationNamespace: String
6969

@@ -74,10 +74,8 @@ trait AndroidAppModule extends AndroidModule { outer =>
7474
override final def androidNamespace: String = androidApplicationNamespace
7575

7676
/**
77-
* Android Application Id which is typically package.main .
78-
* Can be used for build variants.
79-
*
80-
* Build variant feature is not yet implemented!
77+
* Android Application Id unique to every android application.
78+
* See more in [[https://developer.android.com/build/configure-app-module#set-application-id]]
8179
*/
8280
def androidApplicationId: String
8381

@@ -92,19 +90,15 @@ trait AndroidAppModule extends AndroidModule { outer =>
9290
* TODO dynamically add android:debuggable
9391
*/
9492
override def androidManifest: T[PathRef] = Task {
95-
val manifestFromSourcePath = moduleDir / "src/main/AndroidManifest.xml"
93+
val manifestFromSourcePath = androidManifestLocation().path
9694

9795
val manifestElem = XML.loadFile(manifestFromSourcePath.toString())
9896
// add the application package
9997
val manifestWithPackage =
100-
manifestElem % Attribute(None, "package", Text(androidApplicationNamespace), Null)
101-
102-
val manifestWithUsesSdk = manifestWithPackage.copy(
103-
child = androidManifestUsesSdkSection() ++ manifestWithPackage.child
104-
)
98+
manifestElem % Attribute(None, "package", Text(androidNamespace), Null)
10599

106100
val generatedManifestPath = Task.dest / "AndroidManifest.xml"
107-
os.write(generatedManifestPath, manifestWithUsesSdk.mkString)
101+
os.write(generatedManifestPath, manifestWithPackage.mkString)
108102

109103
PathRef(generatedManifestPath)
110104
}
@@ -294,6 +288,10 @@ trait AndroidAppModule extends AndroidModule { outer =>
294288
s"version_code=${androidVersionCode()}",
295289
"--property",
296290
s"version_name=${androidVersionName()}",
291+
"--property",
292+
s"package=${androidApplicationId}",
293+
"--manifest-placeholders",
294+
s"applicationId=${androidApplicationId}",
297295
"--out",
298296
mergedManifestPath.toString()
299297
) ++ libManifests.flatMap(m => Seq("--libs", m.path.toString())),
@@ -671,7 +669,7 @@ trait AndroidAppModule extends AndroidModule { outer =>
671669
"am",
672670
"start",
673671
"-n",
674-
s"${androidApplicationNamespace}/${activity}",
672+
s"${androidApplicationId}/${activity}",
675673
"-W"
676674
)
677675
).out.lines()
@@ -683,7 +681,7 @@ trait AndroidAppModule extends AndroidModule { outer =>
683681
*/
684682
def androidReleaseKeyPath: T[Seq[PathRef]] = {
685683
val subPaths = androidReleaseKeyName.map(os.sub / _).toSeq
686-
Task.Sources(subPaths: _*)
684+
Task.Sources(subPaths*)
687685
}
688686

689687
/*
@@ -1057,7 +1055,7 @@ trait AndroidAppModule extends AndroidModule { outer =>
10571055
override def androidSdkModule: ModuleRef[AndroidSdkModule] = outer.androidSdkModule
10581056
override def androidManifest: T[PathRef] = outer.androidManifest()
10591057

1060-
override def androidApplicationId: String = outer.androidApplicationId
1058+
override def androidApplicationId: String = s"${outer.androidApplicationId}.test"
10611059

10621060
override def androidApplicationNamespace: String = s"${outer.androidApplicationNamespace}.test"
10631061

@@ -1086,7 +1084,7 @@ trait AndroidAppModule extends AndroidModule { outer =>
10861084

10871085
override def resolutionParams: Task[ResolutionParams] = Task.Anon(outer.resolutionParams())
10881086

1089-
override def androidApplicationId: String = s"${outer.androidApplicationId}"
1087+
override def androidApplicationId: String = s"${outer.androidApplicationId}.test"
10901088
override def androidApplicationNamespace: String = s"${outer.androidApplicationNamespace}.test"
10911089

10921090
override def androidReleaseKeyAlias: T[Option[String]] = outer.androidReleaseKeyAlias()
@@ -1105,7 +1103,7 @@ trait AndroidAppModule extends AndroidModule { outer =>
11051103

11061104
private def androidInstrumentedTestsBaseManifest: Task[Elem] = Task.Anon {
11071105
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package={
1108-
androidApplicationNamespace
1106+
androidApplicationId
11091107
}>
11101108
{androidManifestUsesSdkSection()}
11111109
</manifest>
@@ -1129,7 +1127,6 @@ trait AndroidAppModule extends AndroidModule { outer =>
11291127
val destManifest = Task.dest / "AndroidManifest.xml"
11301128
os.write(destManifest, manifestWithInstrumentation.toString)
11311129
PathRef(destManifest)
1132-
11331130
}
11341131

11351132
override def androidVirtualDeviceIdentifier: String = outer.androidVirtualDeviceIdentifier

libs/androidlib/src/mill/androidlib/AndroidModule.scala

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -47,31 +47,23 @@ trait AndroidModule extends JavaModule {
4747
*/
4848
def androidSdkModule: ModuleRef[AndroidSdkModule]
4949

50-
private def androidManifestUsesSdkSection: Task[Elem] = Task.Anon {
51-
val minSdkVersion = androidMinSdk().toString
52-
val targetSdkVersion = androidTargetSdk().toString
53-
<uses-sdk android:minSdkVersion={minSdkVersion} />
54-
}
50+
def androidManifestLocation: T[PathRef] = Task.Source("src/main/AndroidManifest.xml")
5551

5652
/**
5753
* Provides os.Path to an XML file containing configuration and metadata about your android application.
5854
* TODO dynamically add android:debuggable
5955
*/
6056
def androidManifest: T[PathRef] = Task {
61-
val manifestFromSourcePath = moduleDir / "src/main/AndroidManifest.xml"
57+
val manifestFromSourcePath = androidManifestLocation().path
6258

6359
val manifestElem = XML.loadFile(manifestFromSourcePath.toString()) %
6460
Attribute(None, "xmlns:android", Text("http://schemas.android.com/apk/res/android"), Null)
6561
// add the application package
6662
val manifestWithPackage =
6763
manifestElem % Attribute(None, "package", Text(androidNamespace), Null)
6864

69-
val manifestWithUsesSdk = manifestWithPackage.copy(
70-
child = androidManifestUsesSdkSection() ++ manifestWithPackage.child
71-
)
72-
7365
val generatedManifestPath = Task.dest / "AndroidManifest.xml"
74-
os.write(generatedManifestPath, manifestWithUsesSdk.mkString)
66+
os.write(generatedManifestPath, manifestWithPackage.mkString)
7567

7668
PathRef(generatedManifestPath)
7769
}

libs/androidlib/src/mill/androidlib/AndroidSdkModule.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ trait AndroidSdkModule extends Module {
4040
/**
4141
* Specifies the version of the Manifest Merger.
4242
*/
43-
def manifestMergerVersion: T[String] = "31.7.3"
43+
def manifestMergerVersion: T[String] = "31.10.0"
4444

4545
/**
4646
* Specifies the version of the Android build tools to be used.

0 commit comments

Comments
 (0)