commit
049750dd51
@ -0,0 +1,6 @@
|
|||||||
|
# https://editorconfig.org/
|
||||||
|
# This configuration is used by ktlint when spotless invokes it
|
||||||
|
|
||||||
|
[*.{kt,kts}]
|
||||||
|
ij_kotlin_allow_trailing_comma=true
|
||||||
|
ij_kotlin_allow_trailing_comma_on_call_site=true
|
@ -0,0 +1,38 @@
|
|||||||
|
name: Android CI with GMD
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
pull_request:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
|
||||||
|
android-ci:
|
||||||
|
runs-on: macos-12
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
device-config: [ "pixel4api30aospatd", "pixelcapi30aospatd" ]
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/setup-java@v3
|
||||||
|
with:
|
||||||
|
distribution: 'zulu'
|
||||||
|
java-version: '11'
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- name: Setup Android SDK
|
||||||
|
uses: android-actions/setup-android@v2
|
||||||
|
|
||||||
|
- name: Run instrumented tests with GMD
|
||||||
|
run: ./gradlew cleanManagedDevices --unused-only &&
|
||||||
|
./gradlew ${{ matrix.device-config }}DemoDebugAndroidTest -Dorg.gradle.workers.max=1
|
||||||
|
-Pandroid.testoptions.manageddevices.emulator.gpu="swiftshader_indirect" -Pandroid.experimental.testOptions.managedDevices.emulator.showKernelLogging=true
|
||||||
|
|
||||||
|
- name: Upload test reports
|
||||||
|
if: success() || failure()
|
||||||
|
uses: actions/upload-artifact@v3
|
||||||
|
with:
|
||||||
|
name: test-reports
|
||||||
|
path: |
|
||||||
|
'**/*/build/reports/androidTests/'
|
@ -0,0 +1,2 @@
|
|||||||
|
# This file can be used to trigger an internal build by changing the number below
|
||||||
|
3
|
@ -0,0 +1,125 @@
|
|||||||
|
{
|
||||||
|
"project_info": {
|
||||||
|
"project_number": "YourProjectId",
|
||||||
|
"project_id": "abc",
|
||||||
|
"storage_bucket": "abc"
|
||||||
|
},
|
||||||
|
"client": [
|
||||||
|
{
|
||||||
|
"client_info": {
|
||||||
|
"mobilesdk_app_id": "Your:App:Id",
|
||||||
|
"android_client_info": {
|
||||||
|
"package_name": "com.google.samples.apps.nowinandroid"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"oauth_client": [],
|
||||||
|
"api_key": [
|
||||||
|
{
|
||||||
|
"current_key": "APlaceholderAPIKeyWith-ThirtyNineCharsX"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"services": {
|
||||||
|
"appinvite_service": {
|
||||||
|
"other_platform_oauth_client": []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"client_info": {
|
||||||
|
"mobilesdk_app_id": "Your:App:Id",
|
||||||
|
"android_client_info": {
|
||||||
|
"package_name": "com.google.samples.apps.nowinandroid.demo.debug"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"oauth_client": [],
|
||||||
|
"api_key": [
|
||||||
|
{
|
||||||
|
"current_key": "APlaceholderAPIKeyWith-ThirtyNineCharsX"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"services": {
|
||||||
|
"appinvite_service": {
|
||||||
|
"other_platform_oauth_client": []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"client_info": {
|
||||||
|
"mobilesdk_app_id": "Your:App:Id",
|
||||||
|
"android_client_info": {
|
||||||
|
"package_name": "com.google.samples.apps.nowinandroid.demo.benchmark"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"oauth_client": [],
|
||||||
|
"api_key": [
|
||||||
|
{
|
||||||
|
"current_key": "APlaceholderAPIKeyWith-ThirtyNineCharsX"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"services": {
|
||||||
|
"appinvite_service": {
|
||||||
|
"other_platform_oauth_client": []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"client_info": {
|
||||||
|
"mobilesdk_app_id": "Your:App:Id",
|
||||||
|
"android_client_info": {
|
||||||
|
"package_name": "com.google.samples.apps.nowinandroid.benchmark"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"oauth_client": [],
|
||||||
|
"api_key": [
|
||||||
|
{
|
||||||
|
"current_key": "APlaceholderAPIKeyWith-ThirtyNineCharsX"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"services": {
|
||||||
|
"appinvite_service": {
|
||||||
|
"other_platform_oauth_client": []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"client_info": {
|
||||||
|
"mobilesdk_app_id": "Your:App:Id",
|
||||||
|
"android_client_info": {
|
||||||
|
"package_name": "com.google.samples.apps.nowinandroid.debug"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"oauth_client": [],
|
||||||
|
"api_key": [
|
||||||
|
{
|
||||||
|
"current_key": "APlaceholderAPIKeyWith-ThirtyNineCharsX"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"services": {
|
||||||
|
"appinvite_service": {
|
||||||
|
"other_platform_oauth_client": []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"client_info": {
|
||||||
|
"mobilesdk_app_id": "Your:App:Id",
|
||||||
|
"android_client_info": {
|
||||||
|
"package_name": "com.google.samples.apps.nowinandroid.demo"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"oauth_client": [],
|
||||||
|
"api_key": [
|
||||||
|
{
|
||||||
|
"current_key": "APlaceholderAPIKeyWith-ThirtyNineCharsX"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"services": {
|
||||||
|
"appinvite_service": {
|
||||||
|
"other_platform_oauth_client": []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
|
||||||
|
"configuration_version": "1"
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,26 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!--
|
||||||
|
Copyright 2023 The Android Open Source Project
|
||||||
|
|
||||||
|
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>
|
||||||
|
<!-- Enable Firebase analytics for `prod` builds -->
|
||||||
|
<meta-data
|
||||||
|
tools:replace="android:value"
|
||||||
|
android:name="firebase_analytics_collection_deactivated"
|
||||||
|
android:value="false" />
|
||||||
|
</application>
|
||||||
|
</manifest>
|
@ -0,0 +1,58 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2022 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import com.android.build.api.variant.ApplicationAndroidComponentsExtension
|
||||||
|
import com.google.firebase.crashlytics.buildtools.gradle.CrashlyticsExtension
|
||||||
|
import org.gradle.api.Plugin
|
||||||
|
import org.gradle.api.Project
|
||||||
|
import org.gradle.api.artifacts.VersionCatalogsExtension
|
||||||
|
import org.gradle.kotlin.dsl.configure
|
||||||
|
import org.gradle.kotlin.dsl.dependencies
|
||||||
|
import org.gradle.kotlin.dsl.getByType
|
||||||
|
|
||||||
|
class AndroidApplicationFirebaseConventionPlugin : Plugin<Project> {
|
||||||
|
override fun apply(target: Project) {
|
||||||
|
with(target) {
|
||||||
|
with(pluginManager) {
|
||||||
|
apply("com.google.gms.google-services")
|
||||||
|
apply("com.google.firebase.firebase-perf")
|
||||||
|
apply("com.google.firebase.crashlytics")
|
||||||
|
}
|
||||||
|
|
||||||
|
val libs = extensions.getByType<VersionCatalogsExtension>().named("libs")
|
||||||
|
dependencies {
|
||||||
|
val bom = libs.findLibrary("firebase-bom").get()
|
||||||
|
add("implementation", platform(bom))
|
||||||
|
"implementation"(libs.findLibrary("firebase.analytics").get())
|
||||||
|
"implementation"(libs.findLibrary("firebase.performance").get())
|
||||||
|
"implementation"(libs.findLibrary("firebase.crashlytics").get())
|
||||||
|
}
|
||||||
|
|
||||||
|
extensions.configure<ApplicationAndroidComponentsExtension> {
|
||||||
|
finalizeDsl {
|
||||||
|
it.buildTypes.forEach { buildType ->
|
||||||
|
// Disable the Crashlytics mapping file upload. This feature should only be
|
||||||
|
// enabled if a Firebase backend is available and configured in
|
||||||
|
// google-services.json.
|
||||||
|
buildType.configure<CrashlyticsExtension> {
|
||||||
|
mappingFileUploadEnabled = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,63 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2022 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import com.google.devtools.ksp.gradle.KspExtension
|
||||||
|
import org.gradle.api.Plugin
|
||||||
|
import org.gradle.api.Project
|
||||||
|
import org.gradle.api.artifacts.VersionCatalogsExtension
|
||||||
|
import org.gradle.api.tasks.InputDirectory
|
||||||
|
import org.gradle.api.tasks.PathSensitive
|
||||||
|
import org.gradle.api.tasks.PathSensitivity
|
||||||
|
import org.gradle.kotlin.dsl.configure
|
||||||
|
import org.gradle.kotlin.dsl.dependencies
|
||||||
|
import org.gradle.kotlin.dsl.getByType
|
||||||
|
import org.gradle.process.CommandLineArgumentProvider
|
||||||
|
import java.io.File
|
||||||
|
|
||||||
|
class AndroidRoomConventionPlugin : Plugin<Project> {
|
||||||
|
|
||||||
|
override fun apply(target: Project) {
|
||||||
|
with(target) {
|
||||||
|
pluginManager.apply("com.google.devtools.ksp")
|
||||||
|
|
||||||
|
extensions.configure<KspExtension> {
|
||||||
|
// The schemas directory contains a schema file for each version of the Room database.
|
||||||
|
// This is required to enable Room auto migrations.
|
||||||
|
// See https://developer.android.com/reference/kotlin/androidx/room/AutoMigration.
|
||||||
|
arg(RoomSchemaArgProvider(File(projectDir, "schemas")))
|
||||||
|
}
|
||||||
|
|
||||||
|
val libs = extensions.getByType<VersionCatalogsExtension>().named("libs")
|
||||||
|
dependencies {
|
||||||
|
add("implementation", libs.findLibrary("room.runtime").get())
|
||||||
|
add("implementation", libs.findLibrary("room.ktx").get())
|
||||||
|
add("ksp", libs.findLibrary("room.compiler").get())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* https://issuetracker.google.com/issues/132245929
|
||||||
|
* [Export schemas](https://developer.android.com/training/data-storage/room/migrating-db-versions#export-schemas)
|
||||||
|
*/
|
||||||
|
class RoomSchemaArgProvider(
|
||||||
|
@get:InputDirectory
|
||||||
|
@get:PathSensitive(PathSensitivity.RELATIVE)
|
||||||
|
val schemaDir: File,
|
||||||
|
) : CommandLineArgumentProvider {
|
||||||
|
override fun asArguments() = listOf("room.schemaLocation=${schemaDir.path}")
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,63 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2023 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.google.samples.apps.nowinandroid
|
||||||
|
|
||||||
|
import com.android.build.api.dsl.CommonExtension
|
||||||
|
import com.android.build.api.dsl.ManagedVirtualDevice
|
||||||
|
import org.gradle.api.Project
|
||||||
|
import org.gradle.kotlin.dsl.invoke
|
||||||
|
import java.util.Locale
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Configure project for Gradle managed devices
|
||||||
|
*/
|
||||||
|
internal fun configureGradleManagedDevices(
|
||||||
|
commonExtension: CommonExtension<*, *, *, *>,
|
||||||
|
) {
|
||||||
|
val deviceConfigs = listOf(
|
||||||
|
DeviceConfig("Pixel 4", 30, "aosp-atd"),
|
||||||
|
DeviceConfig("Pixel 6", 31, "aosp"),
|
||||||
|
DeviceConfig("Pixel C", 30, "aosp-atd"),
|
||||||
|
)
|
||||||
|
|
||||||
|
commonExtension.testOptions {
|
||||||
|
managedDevices {
|
||||||
|
devices {
|
||||||
|
deviceConfigs.forEach { deviceConfig ->
|
||||||
|
maybeCreate(deviceConfig.taskName, ManagedVirtualDevice::class.java).apply {
|
||||||
|
device = deviceConfig.device
|
||||||
|
apiLevel = deviceConfig.apiLevel
|
||||||
|
systemImageSource = deviceConfig.systemImageSource
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private data class DeviceConfig(
|
||||||
|
val device: String,
|
||||||
|
val apiLevel: Int,
|
||||||
|
val systemImageSource: String,
|
||||||
|
) {
|
||||||
|
val taskName = buildString {
|
||||||
|
append(device.toLowerCase(Locale.ROOT).replace(" ", ""))
|
||||||
|
append("api")
|
||||||
|
append(apiLevel.toString())
|
||||||
|
append(systemImageSource.replace("-", ""))
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1 @@
|
|||||||
|
/build
|
@ -0,0 +1,33 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2023 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
plugins {
|
||||||
|
id("nowinandroid.android.library")
|
||||||
|
id("nowinandroid.android.library.compose")
|
||||||
|
id("nowinandroid.android.hilt")
|
||||||
|
}
|
||||||
|
|
||||||
|
android {
|
||||||
|
namespace = "com.google.samples.apps.nowinandroid.core.analytics"
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
implementation(libs.kotlinx.coroutines.android)
|
||||||
|
implementation(libs.androidx.compose.runtime)
|
||||||
|
implementation(libs.androidx.core.ktx)
|
||||||
|
|
||||||
|
implementation(platform(libs.firebase.bom))
|
||||||
|
implementation(libs.firebase.analytics)
|
||||||
|
}
|
@ -0,0 +1,29 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2023 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.google.samples.apps.nowinandroid.core.analytics
|
||||||
|
|
||||||
|
import dagger.Binds
|
||||||
|
import dagger.Module
|
||||||
|
import dagger.hilt.InstallIn
|
||||||
|
import dagger.hilt.components.SingletonComponent
|
||||||
|
|
||||||
|
@Module
|
||||||
|
@InstallIn(SingletonComponent::class)
|
||||||
|
abstract class AnalyticsModule {
|
||||||
|
@Binds
|
||||||
|
abstract fun bindsAnalyticsHelper(analyticsHelperImpl: StubAnalyticsHelper): AnalyticsHelper
|
||||||
|
}
|
@ -0,0 +1,58 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2023 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.google.samples.apps.nowinandroid.core.analytics
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents an analytics event.
|
||||||
|
*
|
||||||
|
* @param type - the event type. Wherever possible use one of the standard
|
||||||
|
* event `Types`, however, if there is no suitable event type already defined, a custom event can be
|
||||||
|
* defined as long as it is configured in your backend analytics system (for example, by creating a
|
||||||
|
* Firebase Analytics custom event).
|
||||||
|
*
|
||||||
|
* @param extras - list of parameters which supply additional context to the event. See `Param`.
|
||||||
|
*/
|
||||||
|
data class AnalyticsEvent(
|
||||||
|
val type: String,
|
||||||
|
val extras: List<Param> = emptyList(),
|
||||||
|
) {
|
||||||
|
// Standard analytics types.
|
||||||
|
class Types {
|
||||||
|
companion object {
|
||||||
|
const val SCREEN_VIEW = "screen_view" // (extras: SCREEN_NAME)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A key-value pair used to supply extra context to an analytics event.
|
||||||
|
*
|
||||||
|
* @param key - the parameter key. Wherever possible use one of the standard `ParamKeys`,
|
||||||
|
* however, if no suitable key is available you can define your own as long as it is configured
|
||||||
|
* in your backend analytics system (for example, by creating a Firebase Analytics custom
|
||||||
|
* parameter).
|
||||||
|
*
|
||||||
|
* @param value - the parameter value.
|
||||||
|
*/
|
||||||
|
data class Param(val key: String, val value: String)
|
||||||
|
|
||||||
|
// Standard parameter keys.
|
||||||
|
class ParamKeys {
|
||||||
|
companion object {
|
||||||
|
const val SCREEN_NAME = "screen_name"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,24 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2023 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.google.samples.apps.nowinandroid.core.analytics
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implementation of AnalyticsHelper which does nothing. Useful for tests and previews.
|
||||||
|
*/
|
||||||
|
class NoOpAnalyticsHelper : AnalyticsHelper {
|
||||||
|
override fun logEvent(event: AnalyticsEvent) = Unit
|
||||||
|
}
|
@ -0,0 +1,34 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2023 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.google.samples.apps.nowinandroid.core.analytics
|
||||||
|
|
||||||
|
import android.util.Log
|
||||||
|
import javax.inject.Inject
|
||||||
|
import javax.inject.Singleton
|
||||||
|
|
||||||
|
private const val TAG = "StubAnalyticsHelper"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An implementation of AnalyticsHelper just writes the events to logcat. Used in builds where no
|
||||||
|
* analytics events should be sent to a backend.
|
||||||
|
*/
|
||||||
|
@Singleton
|
||||||
|
class StubAnalyticsHelper @Inject constructor() : AnalyticsHelper {
|
||||||
|
override fun logEvent(event: AnalyticsEvent) {
|
||||||
|
Log.d(TAG, "Received analytics event: $event")
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,28 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2023 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.google.samples.apps.nowinandroid.core.analytics
|
||||||
|
|
||||||
|
import androidx.compose.runtime.staticCompositionLocalOf
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Global key used to obtain access to the AnalyticsHelper through a CompositionLocal.
|
||||||
|
*/
|
||||||
|
val LocalAnalyticsHelper = staticCompositionLocalOf<AnalyticsHelper> {
|
||||||
|
// Provide a default AnalyticsHelper which does nothing. This is so that tests and previews
|
||||||
|
// do not have to provide one. For real app builds provide a different implementation.
|
||||||
|
NoOpAnalyticsHelper()
|
||||||
|
}
|
@ -0,0 +1,40 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2023 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.google.samples.apps.nowinandroid.core.analytics
|
||||||
|
|
||||||
|
import com.google.firebase.analytics.FirebaseAnalytics
|
||||||
|
import com.google.firebase.analytics.ktx.analytics
|
||||||
|
import com.google.firebase.ktx.Firebase
|
||||||
|
import dagger.Binds
|
||||||
|
import dagger.Module
|
||||||
|
import dagger.Provides
|
||||||
|
import dagger.hilt.InstallIn
|
||||||
|
import dagger.hilt.components.SingletonComponent
|
||||||
|
import javax.inject.Singleton
|
||||||
|
|
||||||
|
@Module
|
||||||
|
@InstallIn(SingletonComponent::class)
|
||||||
|
abstract class AnalyticsModule {
|
||||||
|
@Binds
|
||||||
|
abstract fun bindsAnalyticsHelper(analyticsHelperImpl: FirebaseAnalyticsHelper): AnalyticsHelper
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
@Provides
|
||||||
|
@Singleton
|
||||||
|
fun provideFirebaseAnalytics(): FirebaseAnalytics { return Firebase.analytics }
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,41 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2023 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.google.samples.apps.nowinandroid.core.analytics
|
||||||
|
|
||||||
|
import com.google.firebase.analytics.FirebaseAnalytics
|
||||||
|
import com.google.firebase.analytics.ktx.logEvent
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implementation of `AnalyticsHelper` which logs events to a Firebase backend.
|
||||||
|
*/
|
||||||
|
class FirebaseAnalyticsHelper @Inject constructor(
|
||||||
|
private val firebaseAnalytics: FirebaseAnalytics,
|
||||||
|
) : AnalyticsHelper {
|
||||||
|
|
||||||
|
override fun logEvent(event: AnalyticsEvent) {
|
||||||
|
firebaseAnalytics.logEvent(event.type) {
|
||||||
|
for (extra in event.extras) {
|
||||||
|
// Truncate parameter keys and values according to firebase maximum length values.
|
||||||
|
param(
|
||||||
|
key = extra.key.take(40),
|
||||||
|
value = extra.value.take(100),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,84 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2023 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.google.samples.apps.nowinandroid.core.data.repository
|
||||||
|
|
||||||
|
import com.google.samples.apps.nowinandroid.core.analytics.AnalyticsEvent
|
||||||
|
import com.google.samples.apps.nowinandroid.core.analytics.AnalyticsEvent.Param
|
||||||
|
import com.google.samples.apps.nowinandroid.core.analytics.AnalyticsHelper
|
||||||
|
|
||||||
|
fun AnalyticsHelper.logNewsResourceBookmarkToggled(newsResourceId: String, isBookmarked: Boolean) {
|
||||||
|
val eventType = if (isBookmarked) "news_resource_saved" else "news_resource_unsaved"
|
||||||
|
val paramKey = if (isBookmarked) "saved_news_resource_id" else "unsaved_news_resource_id"
|
||||||
|
logEvent(
|
||||||
|
AnalyticsEvent(
|
||||||
|
type = eventType,
|
||||||
|
extras = listOf(
|
||||||
|
Param(key = paramKey, value = newsResourceId),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun AnalyticsHelper.logTopicFollowToggled(followedTopicId: String, isFollowed: Boolean) {
|
||||||
|
val eventType = if (isFollowed) "topic_followed" else "topic_unfollowed"
|
||||||
|
val paramKey = if (isFollowed) "followed_topic_id" else "unfollowed_topic_id"
|
||||||
|
logEvent(
|
||||||
|
AnalyticsEvent(
|
||||||
|
type = eventType,
|
||||||
|
extras = listOf(
|
||||||
|
Param(key = paramKey, value = followedTopicId),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun AnalyticsHelper.logThemeChanged(themeName: String) =
|
||||||
|
logEvent(
|
||||||
|
AnalyticsEvent(
|
||||||
|
type = "theme_changed",
|
||||||
|
extras = listOf(
|
||||||
|
Param(key = "theme_name", value = themeName),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
fun AnalyticsHelper.logDarkThemeConfigChanged(darkThemeConfigName: String) =
|
||||||
|
logEvent(
|
||||||
|
AnalyticsEvent(
|
||||||
|
type = "dark_theme_config_changed",
|
||||||
|
extras = listOf(
|
||||||
|
Param(key = "dark_theme_config", value = darkThemeConfigName),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
fun AnalyticsHelper.logDynamicColorPreferenceChanged(useDynamicColor: Boolean) =
|
||||||
|
logEvent(
|
||||||
|
AnalyticsEvent(
|
||||||
|
type = "dynamic_color_preference_changed",
|
||||||
|
extras = listOf(
|
||||||
|
Param(key = "dynamic_color_preference", value = useDynamicColor.toString()),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
fun AnalyticsHelper.logOnboardingStateChanged(shouldHideOnboarding: Boolean) {
|
||||||
|
val eventType = if (shouldHideOnboarding) "onboarding_complete" else "onboarding_reset"
|
||||||
|
logEvent(
|
||||||
|
AnalyticsEvent(type = eventType),
|
||||||
|
)
|
||||||
|
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue