Skip to content
Open
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
2 changes: 1 addition & 1 deletion ApiDemos/project/common-ui/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ android {
}

dependencies {

implementation(project(":library"))
implementation(libs.core.ktx)
implementation(libs.appcompat)
implementation(libs.material)
Expand Down
1 change: 1 addition & 0 deletions FireMarkers/app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ android {
}

dependencies {
implementation(project(":library"))
// ---------------------------------------------------------------------------------------------
// AndroidX & Jetpack
//
Expand Down
18 changes: 18 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,24 @@ To run instrumentation tests on a connected device or emulator, use:
Alternatively, use the `gradlew build` command to build the project directly or download an APK
under [releases](https://github.com/googlemaps/android-samples/releases).

## 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.

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.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
1 change: 1 addition & 0 deletions WearOS/Wearable/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ dependencies {
implementation(libs.core.ktx)
implementation(platform(libs.kotlin.bom))
implementation(libs.kotlin.stdlib)
implementation(project(":library"))
// [END_EXCLUDE]
// Modern Android projects use version catalogs to manage dependencies. To include the necessary dependencies,
// first add the following to your libs.versions.toml file:
Expand Down
6 changes: 6 additions & 0 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ robolectric = "4.16.1"
truth = "1.4.5"
turbine = "1.2.1"
uiautomator = "2.3.0"
mockk = "1.14.11"

# Firebase
firebaseBom = "34.8.0"
Expand All @@ -67,12 +68,16 @@ firebaseDatabase = "22.0.1"
easypermissions = "3.0.0"
volley = "1.2.1"

#Tracker lib
startup-runtime = "1.2.0"

[libraries]
# Kotlin
kotlin-bom = { module = "org.jetbrains.kotlin:kotlin-bom", version.ref = "kotlin" }
kotlin-stdlib = { group = "org.jetbrains.kotlin", name = "kotlin-stdlib", version.ref = "kotlin" }
kotlin-stdlib-jdk8 = { module = "org.jetbrains.kotlin:kotlin-stdlib-jdk8", version.ref = "kotlin" }
kotlinx-datetime = { module = "org.jetbrains.kotlinx:kotlinx-datetime", version.ref = "kotlinxDatetime" }
startup-runtime = { module = "androidx.startup:startup-runtime", version.ref = "startup-runtime" }

# AndroidX
activity = { module = "androidx.activity:activity", version.ref = "activity" }
Expand Down Expand Up @@ -130,6 +135,7 @@ turbine = { module = "app.cash.turbine:turbine", version.ref = "turbine" }
ui-test-junit4 = { module = "androidx.compose.ui:ui-test-junit4", version.ref = "compose" }
ui-test-manifest = { module = "androidx.compose.ui:ui-test-manifest", version.ref = "compose" }
uiautomator = { group = "androidx.test.uiautomator", name = "uiautomator", version.ref = "uiautomator" }
mockk = { module = "io.mockk:mockk", version.ref = "mockk" }

# Firebase
firebase-bom = { module = "com.google.firebase:firebase-bom", version.ref = "firebaseBom" }
Expand Down
1 change: 1 addition & 0 deletions library/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/build
117 changes: 117 additions & 0 deletions library/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
import org.jetbrains.kotlin.gradle.dsl.JvmTarget

/*
* 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.
*/

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

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

defaultConfig {
minSdk = libs.versions.minSdk.get().toInt()
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
consumerProguardFiles("consumer-rules.pro")
}
buildTypes {
release {
isMinifyEnabled = false
proguardFiles(
getDefaultProguardFile("proguard-android-optimize.txt"),
"proguard-rules.pro"
)
}
}
lint {
abortOnError = false
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
}
lint {
disable += setOf("MissingInflatedId", "OnClick")
sarifOutput = layout.buildDirectory.file("reports/lint-results-debug.sarif").get().asFile
}
kotlin {
compilerOptions {
jvmTarget.set(JvmTarget.JVM_17)
javaParameters.set(true)
}
}
}

dependencies {
implementation(libs.appcompat)
implementation(libs.core.ktx)
implementation(libs.material)
implementation(libs.startup.runtime)
implementation(libs.play.services.maps)
testImplementation(libs.junit)
testImplementation(libs.robolectric)
testImplementation(libs.mockk)
testImplementation(libs.espresso.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.library.utils.meta"
val packagePath = packageName.replace('.', '/')
val outputFile = File(dir, "$packagePath/ArtifactId.kt")
outputFile.parentFile.mkdirs()
val attributionId = "gmp_git_androidsamples_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(libs.versions.versionName.get())
}

androidComponents {
onVariants { variant ->
variant.sources.java?.addGeneratedSourceDirectory(
generateArtifactIdFile,
GenerateArtifactIdTask::outputDir
)
}
}
Empty file added library/consumer-rules.pro
Empty file.
21 changes: 21 additions & 0 deletions library/proguard-rules.pro
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html

# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}

# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable

# If you keep the line number information, uncomment this to
# hide the original source file name.

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: missing trailing newline.

#-renamesourcefileattribute SourceFile
34 changes: 34 additions & 0 deletions library/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<?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

https://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.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.library.utils.attribution

import android.content.Context
import androidx.annotation.Keep
import androidx.startup.Initializer
import com.example.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
internal class AttributionIdInitializer : Initializer<Unit> {
override fun create(context: Context) {
MapsApiSettings.addInternalUsageAttributionId(
// 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,62 @@
/*
* 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.library.utils

import android.content.Context
import androidx.test.core.app.ApplicationProvider
import com.example.library.utils.attribution.AttributionIdInitializer
import com.example.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 settings.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -70,3 +70,4 @@ project(":snippets:app-utils").projectDir = file("snippets/app-utils")
include(":tutorials:kotlin:Polygons")
project(":tutorials:kotlin:Polygons").projectDir = file("tutorials/kotlin/Polygons/app")
// Add others as needed, starting with these for now
include(":library")
1 change: 1 addition & 0 deletions snippets/app-compose/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ dependencies {
implementation(libs.navigation.ui.ktx)
implementation(libs.volley)
implementation(libs.lifecycle.runtime.ktx)
implementation(project(":library"))
// [END_EXCLUDE]

// Android Maps Compose composables for the Maps SDK for Android
Expand Down
1 change: 1 addition & 0 deletions snippets/app-ktx/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ dependencies {
implementation(libs.core.ktx)
implementation(libs.appcompat)
implementation(libs.lifecycle.runtime.ktx)
implementation(project(":library"))
// [END_EXCLUDE]

// KTX for the Maps SDK for Android library
Expand Down
1 change: 1 addition & 0 deletions snippets/app-places-ktx/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ dependencies {
testImplementation(libs.junit)
androidTestImplementation(libs.ext.junit)
androidTestImplementation(libs.espresso.core)
implementation(project(":library"))
// [END_EXCLUDE]

// KTX for the Places SDK for Android library
Expand Down
Loading