Skip to content

Commit 5e3033d

Browse files
feat(testapp): Update test app and add library version display (#398)
* feat(testapp): Update test app and add library version display - Declared V1 and V2 activities in manifest and added a custom XML theme. - Added a task to extract the resolved library version and wired it to resources. - Displayed the version on MainActivity and applied a custom Compose theme to V2. - Added a unit test for the setActivityTitle API in V2. - Updated the library version to "+" in libs.versions.toml. Written by Antigravity * add fallback for missing file * test(oss-licenses): Isolate V2 tests to avoid static state pollution * feat(testapp): Add XML theme fallback demo and test
1 parent 7519228 commit 5e3033d

File tree

9 files changed

+195
-17
lines changed

9 files changed

+195
-17
lines changed

oss-licenses-plugin/testapp/app/build.gradle.kts

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,18 @@ androidComponents {
7878
// We explicitly enable them for all variants to ensure both Debug and Release coverage.
7979
variantBuilder.hostTests[HostTestBuilder.UNIT_TEST_TYPE]?.enable = true
8080
}
81+
82+
onVariants { variant ->
83+
val generateTask = tasks.register<GenerateVersionTask>("generateVersionResource_${variant.name}") {
84+
libraryDependenciesReport.set(variant.artifacts.get(com.android.build.api.artifact.SingleArtifact.METADATA_LIBRARY_DEPENDENCIES_REPORT))
85+
outputDir.set(layout.buildDirectory.dir("generated/oss_res/${variant.name}"))
86+
}
87+
88+
variant.sources.res?.addGeneratedSourceDirectory(
89+
generateTask,
90+
GenerateVersionTask::outputDir
91+
)
92+
}
8193
}
8294

8395
kotlin {
@@ -106,3 +118,38 @@ dependencies {
106118
testImplementation(libs.androidx.compose.ui.test.junit4)
107119
debugImplementation(libs.androidx.compose.ui.test.manifest)
108120
}
121+
122+
abstract class GenerateVersionTask : DefaultTask() {
123+
@get:org.gradle.api.tasks.InputFile
124+
@get:org.gradle.api.tasks.Optional
125+
abstract val libraryDependenciesReport: org.gradle.api.file.RegularFileProperty
126+
127+
@get:org.gradle.api.tasks.OutputDirectory
128+
abstract val outputDir: org.gradle.api.file.DirectoryProperty
129+
130+
@org.gradle.api.tasks.TaskAction
131+
fun doAction() {
132+
val versionFile = outputDir.get().file("raw/version.txt").asFile
133+
versionFile.parentFile.mkdirs()
134+
135+
if (!libraryDependenciesReport.isPresent) {
136+
versionFile.writeText("UNKNOWN")
137+
return
138+
}
139+
140+
val reportFile = libraryDependenciesReport.get().asFile
141+
val appDependencies = reportFile.inputStream().use {
142+
com.android.tools.build.libraries.metadata.AppDependencies.parseFrom(it)
143+
}
144+
145+
val ossLicensesLibrary = appDependencies.libraryList.find {
146+
it.libraryOneofCase.name == "MAVEN_LIBRARY" &&
147+
it.mavenLibrary.groupId == "com.google.android.gms" &&
148+
it.mavenLibrary.artifactId == "play-services-oss-licenses"
149+
}
150+
151+
val version = ossLicensesLibrary?.mavenLibrary?.version ?: "UNKNOWN"
152+
versionFile.writeText(version)
153+
println("Generated version.txt with version: $version")
154+
}
155+
}

oss-licenses-plugin/testapp/app/src/main/AndroidManifest.xml

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
<?xml version="1.0" encoding="utf-8"?>
2-
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
2+
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
3+
xmlns:tools="http://schemas.android.com/tools">
34
<application
45
android:allowBackup="true"
56
android:label="OSS Licenses Test App"
@@ -13,5 +14,15 @@
1314
<category android:name="android.intent.category.LAUNCHER" />
1415
</intent-filter>
1516
</activity>
17+
<activity
18+
android:name="com.google.android.gms.oss.licenses.v2.OssLicensesMenuActivity"
19+
android:theme="@style/Theme.CustomOssThemeV2"
20+
tools:replace="android:theme"
21+
android:exported="true" />
22+
<activity
23+
android:name="com.google.android.gms.oss.licenses.OssLicensesMenuActivity"
24+
android:theme="@style/Theme.CustomOssTheme"
25+
tools:replace="android:theme"
26+
android:exported="true" />
1627
</application>
1728
</manifest>

oss-licenses-plugin/testapp/app/src/main/java/com/google/android/gms/oss/licenses/testapp/MainActivity.kt

Lines changed: 37 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ import androidx.compose.material3.Text
3131
import androidx.compose.ui.Alignment
3232
import androidx.compose.ui.Modifier
3333
import androidx.compose.ui.unit.dp
34+
import androidx.compose.material3.lightColorScheme
35+
import androidx.compose.ui.graphics.Color
3436
import com.google.android.gms.oss.licenses.OssLicensesMenuActivity as V1Activity
3537
import com.google.android.gms.oss.licenses.v2.OssLicensesMenuActivity as V2Activity
3638

@@ -44,15 +46,47 @@ class MainActivity : ComponentActivity() {
4446
verticalArrangement = Arrangement.Center,
4547
horizontalAlignment = Alignment.CenterHorizontally,
4648
) {
49+
Text("Library Version: ${getLibraryVersion()}")
50+
Spacer(modifier = Modifier.height(16.dp))
4751
Button(onClick = { startActivity(Intent(this@MainActivity, V1Activity::class.java)) }) {
48-
Text("Launch V1 Licenses")
52+
Text("Launch V1 (XML Theme)")
53+
}
54+
Spacer(modifier = Modifier.height(16.dp))
55+
Button(onClick = {
56+
val customColors = lightColorScheme(
57+
background = Color(0xFFE0F7FA), // Light Cyan
58+
surface = Color(0xFFE0F7FA), // Light Cyan for TopAppBar
59+
onBackground = Color.Black,
60+
onSurface = Color.Black
61+
)
62+
V2Activity.setTheme(customColors, customColors, null)
63+
V2Activity.setActivityTitle("Custom Title from App")
64+
startActivity(Intent(this@MainActivity, V2Activity::class.java))
65+
}) {
66+
Text("Launch V2 (Compose Theme)")
4967
}
5068
Spacer(modifier = Modifier.height(16.dp))
51-
Button(onClick = { startActivity(Intent(this@MainActivity, V2Activity::class.java)) }) {
52-
Text("Launch V2 Licenses")
69+
Button(onClick = {
70+
V2Activity.setTheme(null, null, null)
71+
V2Activity.setActivityTitle("Title from XML Theme")
72+
startActivity(Intent(this@MainActivity, V2Activity::class.java))
73+
}) {
74+
Text("Launch V2 (XML Theme)")
5375
}
5476
}
5577
}
5678
}
5779
}
80+
81+
private fun getLibraryVersion(): String {
82+
val id = resources.getIdentifier("version", "raw", packageName)
83+
if (id == 0) return "UNKNOWN"
84+
return try {
85+
resources.openRawResource(id).use { inputStream ->
86+
inputStream.bufferedReader().use { it.readText() }
87+
}
88+
} catch (e: Exception) {
89+
"UNKNOWN"
90+
}
91+
}
5892
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<resources>
3+
<style name="Theme.CustomOssTheme" parent="Theme.AppCompat.Light">
4+
<item name="android:windowBackground">#E0F7FA</item> <!-- Light Cyan -->
5+
<item name="colorPrimary">#E0F7FA</item> <!-- Light Cyan for Action Bar -->
6+
<item name="colorPrimaryDark">#B2EBF2</item> <!-- Darker Cyan for Status Bar if needed -->
7+
</style>
8+
<style name="Theme.CustomOssThemeV2" parent="Theme.AppCompat.Light">
9+
<item name="android:windowBackground">#FCE4EC</item> <!-- Light Pink -->
10+
<item name="colorPrimary">#FCE4EC</item>
11+
<item name="colorPrimaryDark">#F8BBD0</item>
12+
</style>
13+
</resources>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
/*
2+
* Copyright 2026 Google LLC
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.google.android.gms.oss.licenses.testapp
18+
19+
import android.content.Intent
20+
import androidx.compose.ui.test.junit4.createEmptyComposeRule
21+
import androidx.compose.ui.test.onNodeWithText
22+
import androidx.test.core.app.ActivityScenario
23+
import androidx.test.core.app.ApplicationProvider
24+
import androidx.test.ext.junit.runners.AndroidJUnit4
25+
import com.google.android.gms.oss.licenses.v2.OssLicensesMenuActivity
26+
import org.junit.Rule
27+
import org.junit.Test
28+
import org.junit.runner.RunWith
29+
30+
@RunWith(AndroidJUnit4::class)
31+
class OssLicensesV2CustomTitleTest {
32+
33+
@get:Rule val composeTestRule = createEmptyComposeRule()
34+
35+
@Test
36+
fun testV2ActivityCustomTitleViaIntent() {
37+
val customTitle = "My Custom Licenses Title"
38+
val intent =
39+
Intent(ApplicationProvider.getApplicationContext(), OssLicensesMenuActivity::class.java)
40+
.apply { putExtra("title", customTitle) }
41+
42+
ActivityScenario.launch<OssLicensesMenuActivity>(intent).use {
43+
composeTestRule.onNodeWithText(customTitle).assertExists()
44+
}
45+
}
46+
}

oss-licenses-plugin/testapp/app/src/testRelease/java/com/google/android/gms/oss/licenses/testapp/OssLicensesV2Test.kt

Lines changed: 30 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,10 @@ import androidx.compose.ui.test.performClick
2323
import androidx.test.core.app.ActivityScenario
2424
import androidx.test.core.app.ApplicationProvider
2525
import androidx.test.ext.junit.runners.AndroidJUnit4
26+
import android.graphics.Color
27+
import android.util.TypedValue
2628
import com.google.android.gms.oss.licenses.v2.OssLicensesMenuActivity
29+
import org.junit.Assert.assertEquals
2730
import org.junit.Assert.assertTrue
2831
import org.junit.Ignore
2932
import org.junit.Rule
@@ -83,16 +86,35 @@ class OssLicensesV2Test {
8386
}
8487
}
8588

89+
90+
8691
@Test
87-
fun testV2ActivityCustomTitleViaIntent() {
88-
val customTitle = "My Custom Licenses Title"
89-
val intent =
90-
Intent(ApplicationProvider.getApplicationContext(), OssLicensesMenuActivity::class.java)
91-
.apply { putExtra("title", customTitle) }
92-
93-
ActivityScenario.launch<OssLicensesMenuActivity>(intent).use {
94-
// The v2 library does not update activity.title, it only displays it in the Compose UI.
92+
fun testV2ActivitySetActivityTitle() {
93+
val customTitle = "Test Title via API"
94+
OssLicensesMenuActivity.setActivityTitle(customTitle)
95+
96+
ActivityScenario.launch(OssLicensesMenuActivity::class.java).use {
9597
composeTestRule.onNodeWithText(customTitle).assertExists()
9698
}
9799
}
100+
101+
@Test
102+
fun testV2ActivityUsesXmlThemeFallback() {
103+
// Ensure no programmatic theme is set
104+
OssLicensesMenuActivity.setTheme(null, null, null)
105+
106+
ActivityScenario.launch(OssLicensesMenuActivity::class.java).use { scenario ->
107+
scenario.onActivity { activity ->
108+
val typedValue = TypedValue()
109+
val theme = activity.theme
110+
val success = theme.resolveAttribute(android.R.attr.windowBackground, typedValue, true)
111+
112+
assertTrue("Failed to resolve windowBackground attribute", success)
113+
114+
// The expected color is #FCE4EC (Light Pink) defined in Theme.CustomOssThemeV2
115+
val expectedColor = Color.parseColor("#FCE4EC")
116+
assertEquals("Theme background color mismatch", expectedColor, typedValue.data)
117+
}
118+
}
119+
}
98120
}

oss-licenses-plugin/testapp/gradle.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ org.gradle.configuration-cache.problems=fail
2323
org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8
2424

2525
# Plugin specific flags
26-
# This property silences warnings about vulnerable protobuf generated types
26+
# This property silences warnings about vulnerable protobuf generated types
2727
# in older versions of AGP/Gradle.
2828
com.google.protobuf.use_unsafe_pre22_gencode=true
2929

oss-licenses-plugin/testapp/gradle/libs.versions.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ junit = "4.13.2"
1111
kotlin = "2.1.10"
1212
minSdk = "24"
1313
oss-licenses-plugin = "+"
14-
oss-licenses-library = "17.4.0"
14+
oss-licenses-library = "+" # Always use the latest available
1515
robolectric = "4.16.1"
1616
targetSdk = "36"
1717

oss-licenses-plugin/testapp/settings.gradle.kts

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -60,19 +60,24 @@ plugins {
6060
dependencyResolutionManagement {
6161
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
6262
repositories {
63-
// Allow overriding the 'play-services-oss-licenses' runtime library with a local version.
64-
// Usage: ./gradlew :app:test -PlibraryRepoPath=/path/to/your/mavenrepo
63+
// // Allow overriding the 'play-services-oss-licenses' runtime library with a local version.
64+
// // Usage: ./gradlew :app:test -PlibraryRepoPath=/path/to/your/mavenrepo
6565
val libraryRepo = providers.gradleProperty("libraryRepoPath").orNull
6666
if (libraryRepo != null) {
6767
println("Registering libraryRepoPath: $libraryRepo")
6868
exclusiveContent {
69-
forRepository { maven { url = uri(libraryRepo) } }
69+
forRepository {
70+
maven {
71+
url = uri(file(libraryRepo))
72+
}
73+
}
7074
filter {
7175
includeModule("com.google.android.gms", "play-services-oss-licenses")
7276
}
7377
}
7478
}
7579

80+
7681
google()
7782
mavenCentral()
7883
}

0 commit comments

Comments
 (0)