Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 4 additions & 6 deletions .releaserc
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,12 @@ plugins:
- - "@google/semantic-release-replace-plugin"
- replacements:
- files:
- "./Maps3DSamples/ApiDemos/kotlin-app/build.gradle.kts"
- "./Maps3DSamples/advanced/app/build.gradle.kts"
from: "versionName = \".*\""
to: "versionName = \"${nextRelease.version}\""
- "./build.gradle.kts"
from: "version = \".*\""
to: "version = \"${nextRelease.version}\""
- - "@semantic-release/git"
- assets:
- "Maps3DSamples/ApiDemos/kotlin-app/build.gradle.kts"
- "Maps3DSamples/advanced/app/build.gradle.kts"
- "build.gradle.kts"
- - "@semantic-release/github"
- assets:
- "./advanced-kotlin-debug.apk"
Expand Down
1 change: 1 addition & 0 deletions Maps3DSamples/ApiDemos/java-app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ dependencies {
implementation(libs.androidx.ui.tooling.preview)
implementation(libs.androidx.material3)
implementation(libs.play.services.base) // "com.google.android.gms:play-services-base:18.10.0"
implementation(project(":library"))
implementation(project(":Maps3DSamples:ApiDemos:common"))

testImplementation(libs.junit) // "junit:junit:4.13.2"
Expand Down
3 changes: 2 additions & 1 deletion Maps3DSamples/ApiDemos/kotlin-app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ android {
minSdk = libs.versions.minSdk.get().toInt()
targetSdk = libs.versions.targetSdk.get().toInt()
versionCode = 1
versionName = "1.13.0"
versionName = project.version.toString()

testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"

Expand Down Expand Up @@ -104,6 +104,7 @@ dependencies {
debugImplementation(libs.androidx.ui.test.manifest)

implementation(libs.play.services.base) // "com.google.android.gms:play-services-base:18.10.0"
implementation(project(":library"))
implementation(project(":Maps3DSamples:ApiDemos:common"))
}

Expand Down
1 change: 1 addition & 0 deletions Maps3DSamples/ComposeDemos/app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ android {
dependencies {
coreLibraryDesugaring(libs.desugar.jdk.libs)

implementation(project(":library"))
implementation(project(":maps3d-compose"))
implementation(project(":Maps3DSamples:ApiDemos:common"))

Expand Down
4 changes: 2 additions & 2 deletions Maps3DSamples/advanced/app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ android {
minSdk = libs.versions.minSdk.get().toInt()
targetSdk = libs.versions.targetSdk.get().toInt()
versionCode = 1
versionName = "1.13.0"
versionName = project.version.toString()

testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"

Expand Down Expand Up @@ -75,7 +75,7 @@ android {
}

dependencies {

implementation(project(":library"))
implementation(libs.androidx.core.ktx)
implementation(libs.androidx.lifecycle.runtime.ktx)
implementation(libs.androidx.activity.compose)
Expand Down
2 changes: 2 additions & 0 deletions PlacesUIKit3D/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,8 @@ android {
// The `dependencies` block is where we declare all the external libraries the app needs.
// These are fetched from repositories like Maven Central and Google's Maven repository.
dependencies {
implementation(project(":library"))

// --- Core AndroidX & UI Libraries ---
// These are foundational libraries for building modern Android apps.
implementation(libs.androidx.core.ktx)
Expand Down
18 changes: 18 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,24 @@ under [releases](https://github.com/googlemaps/android-maps3d-samples/releases)

If you are upgrading from an older version of the SDK, please refer to the [Migration Guide](MIGRATION_GUIDE.md) for details on breaking changes and how to update your codebase.

## Internal usage attribution ID

This library calls the `addInternalUsageAttributionId` method, which helps Google understand which libraries and samples are helpful to developers and is optional. Instructions for opting out of the identifier are provided below.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a samples repo, so a developer copying one of the samples will not get the :library module. What about rephrasing it slightly?

Suggested change
This library calls the `addInternalUsageAttributionId` method, which helps Google understand which libraries and samples are helpful to developers and is optional. Instructions for opting out of the identifier are provided below.
These samples call the `addInternalUsageAttributionId` method, which helps Google understand which libraries and samples are helpful to developers and is optional. Instructions for opting out of the identifier are provided below.


If you wish to disable this, you can do so by removing the initializer in your `AndroidManifest.xml` using the `tools:node="remove"` attribute:

```xml
<provider
android:name="androidx.startup.InitializationProvider"
android:authorities="${applicationId}.androidx-startup"
android:exported="false"
tools:node="merge">
<meta-data
android:name="com.example.maps3dsamples.library.utils.attribution.AttributionIdInitializer"
tools:node="remove" />
</provider>
```

## Contributing

Contributions are welcome and encouraged! If you'd like to contribute, send us a [pull request] and refer to our [code of conduct] and [contributing guide].
Expand Down
6 changes: 6 additions & 0 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,12 @@ plugins {
alias(libs.plugins.spotless) apply false
}

allprojects {
// {x-release-please-start-version}

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This repo is released with semantic-release (see .releaserc), not release-please, so these markers are not doing anything. The .releaserc replacement already covers the version = line. Could we remove them?

version = "1.13.0"
// {x-release-please-end}
}

subprojects {
tasks.withType<Test>().configureEach {
jvmArgs("--add-opens=java.base/jdk.internal.access=ALL-UNNAMED")
Expand Down
6 changes: 6 additions & 0 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@ mapsUtils = "6.0.0"
androidx-core-ktx = "1.8.9"
androidxArchCoreTesting = "2.2.0"
kotlinxCoroutines = "1.8.0"
mockk = "1.14.11"
startup-runtime = "1.2.0"
playServicesMaps = "20.0.0"

[libraries]
androidx-arch-core-testing = { group = "androidx.arch.core", name = "core-testing", version.ref = "androidxArchCoreTesting" }
Expand Down Expand Up @@ -86,6 +89,9 @@ ktor-serialization-kotlinx-json = { module = "io.ktor:ktor-serialization-kotlinx
android-maps-utils = { module = "com.google.maps.android:android-maps-utils", version.ref = "mapsUtils" }
android-maps-utils-core = { module = "com.google.maps.android:android-maps-utils-core", version.ref = "mapsUtils" }
androidx-material-icons-extended = { module = "androidx.compose.material:material-icons-extended" }
mockk = { module = "io.mockk:mockk", version.ref = "mockk" }
startup-runtime = { module = "androidx.startup:startup-runtime", version.ref = "startup-runtime" }
play-services-maps = { group = "com.google.android.gms", name = "play-services-maps", version.ref = "playServicesMaps" }

[plugins]
android-application = { id = "com.android.application", version.ref = "agp" }
Expand Down
1 change: 1 addition & 0 deletions library/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/build
114 changes: 114 additions & 0 deletions library/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
/*
* Copyright 2026 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

import org.jetbrains.kotlin.gradle.dsl.JvmTarget

plugins {
alias(libs.plugins.android.library)
alias(libs.plugins.kotlin.android)
alias(libs.plugins.spotless)
}

configure<com.diffplug.gradle.spotless.SpotlessExtension> {
kotlin {
target("**/*.kt")
ktlint().editorConfigOverride(
mapOf(
"indent_size" to "4",
"ktlint_function_naming_ignore_when_annotated_with" to "Composable",
"ktlint_standard_max-line-length" to "disabled",
),
)
trimTrailingWhitespace()
endWithNewline()
}
}

android {
namespace = "com.example.maps3dsamples.library"
compileSdk = libs.versions.compileSdk.get().toInt()

defaultConfig {
minSdk = libs.versions.minSdk.get().toInt()
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
consumerProguardFiles("consumer-rules.pro")
}

compileOptions {
sourceCompatibility = JavaVersion.VERSION_11
targetCompatibility = JavaVersion.VERSION_11
}

kotlin {
compilerOptions {
jvmTarget.set(JvmTarget.JVM_11)
}
}
}

dependencies {
implementation(libs.play.services.maps)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Related to the comment above: this pulls play-services-maps into all 8 sample apps only for this call. If the 3D SDK does not read the ID, should we drop it?

implementation(libs.startup.runtime)
testImplementation(libs.junit)
testImplementation(libs.robolectric)
testImplementation(libs.mockk)
testImplementation(libs.androidx.core)
}

abstract class GenerateArtifactIdTask : DefaultTask() {
@get:OutputDirectory
abstract val outputDir: DirectoryProperty

@get:Input
abstract val version: Property<String>

@TaskAction
fun generate() {
val dir = outputDir.get().asFile
val packageName = "com.example.maps3dsamples.library.utils.meta"
val packagePath = packageName.replace('.', '/')
val outputFile = File(dir, "$packagePath/ArtifactId.kt")

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: the generated object is AttributionId, so the file name could match:

Suggested change
val outputFile = File(dir, "$packagePath/ArtifactId.kt")
val outputFile = File(dir, "$packagePath/AttributionId.kt")

outputFile.parentFile.mkdirs()
val attributionId = "gmp_git_androidmaps3dsamples_v${version.get()}"
outputFile.writeText(
"""
package $packageName

/**
* Automatically generated object containing the library's attribution ID.
* This is used to track library usage for analytics.
*/
public object AttributionId {
public const val VALUE: String = "$attributionId"
}
""".trimIndent(),
)
}
}

val generateArtifactIdFile = tasks.register<GenerateArtifactIdTask>("generateArtifactIdFile") {
outputDir.set(layout.buildDirectory.dir("generated/source/artifactId"))
version.set(project.version.toString())
}

androidComponents {
onVariants { variant ->
variant.sources.java?.addGeneratedSourceDirectory(
generateArtifactIdFile,
GenerateArtifactIdTask::outputDir,
)
}
}
1 change: 1 addition & 0 deletions library/consumer-rules.pro
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# Consumer ProGuard rules for attribution ID initializer
31 changes: 31 additions & 0 deletions library/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2026 Google LLC

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<application>
<provider
android:name="androidx.startup.InitializationProvider"
android:authorities="${applicationId}.androidx-startup"
android:exported="false"
tools:node="merge">

<meta-data
android:name="com.example.maps3dsamples.library.utils.attribution.AttributionIdInitializer"
android:value="androidx.startup" />
</provider>
</application>
</manifest>
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/*
* Copyright 2026 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.example.maps3dsamples.library.utils.attribution

import android.content.Context
import androidx.annotation.Keep
import androidx.startup.Initializer
import com.example.maps3dsamples.library.utils.meta.AttributionId
import com.google.android.gms.maps.MapsApiSettings

/**
* Adds a usage attribution ID to the initializer, which helps Google understand which libraries
* and samples are helpful to developers, such as usage of this library.
* To opt out of sending the usage attribution ID, please remove this initializer from your manifest.
*/
@Keep

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: androidx.startup already ships the keep rules for Initializer implementations, so the @Keep and the empty consumer-rules.pro are not needed.

internal class AttributionIdInitializer : Initializer<Unit> {
override fun create(context: Context) {
MapsApiSettings.addInternalUsageAttributionId(

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @LoyalAbbas . Just to understand it: MapsApiSettings belongs to the 2D Maps SDK, and none of the samples in this repo creates a 2D map (they only use play-services-maps3d). Is the attribution ID also picked up by the Maps 3D SDK? I could not find an equivalent API in play-services-maps3d, so I suspect the ID is never sent.

// context =
context,
// internalUsageAttributionId =
AttributionId.VALUE,
)
}

override fun dependencies(): List<Class<out Initializer<*>>> = emptyList()
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
/*
* Copyright 2026 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.example.maps3dsamples.library.utils.attribution

import android.content.Context
import androidx.test.core.app.ApplicationProvider
import com.example.maps3dsamples.library.utils.meta.AttributionId
import com.google.android.gms.maps.MapsApiSettings
import io.mockk.every
import io.mockk.just
import io.mockk.mockkStatic
import io.mockk.runs
import io.mockk.unmockkStatic
import io.mockk.verify
import org.junit.After
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.robolectric.RobolectricTestRunner

@RunWith(RobolectricTestRunner::class)
class AttributionIdInitializerTest {
@Before
fun setUp() {
mockkStatic(MapsApiSettings::class)
every { MapsApiSettings.addInternalUsageAttributionId(any(), any()) } just runs
}

@After
fun tearDown() {
unmockkStatic(MapsApiSettings::class)
}

@Test
fun `create adds internal usage attribution id`() {
val context = ApplicationProvider.getApplicationContext<Context>()
val initializer = AttributionIdInitializer()

initializer.create(context)

verify {
MapsApiSettings.addInternalUsageAttributionId(
context,
AttributionId.VALUE,
)
}
}
}
1 change: 1 addition & 0 deletions maps3d-compose-demo/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ android {
}

dependencies {
implementation(project(":library"))
implementation(project(":maps3d-compose"))

implementation(libs.androidx.core.ktx)
Expand Down
Loading
Loading