Skip to content

Commit

Permalink
Merge pull request #107 from azrael8576/feat/core-analytics
Browse files Browse the repository at this point in the history
  • Loading branch information
azrael8576 authored Feb 16, 2024
2 parents 6789b14 + 2aa8831 commit a8deb6a
Show file tree
Hide file tree
Showing 28 changed files with 411 additions and 7 deletions.
4 changes: 3 additions & 1 deletion app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import com.wei.picquest.PqBuildType
plugins {
alias(libs.plugins.pq.android.application)
alias(libs.plugins.pq.android.application.compose)
alias(libs.plugins.pq.android.application.firebase)
alias(libs.plugins.pq.android.application.flavors)
alias(libs.plugins.pq.android.hilt)
alias(libs.plugins.roborazzi)
Expand Down Expand Up @@ -72,6 +73,7 @@ dependencies {
implementation(projects.feature.photo)
implementation(projects.feature.video)

implementation(projects.core.analytics)
implementation(projects.core.common)
implementation(projects.core.data)
implementation(projects.core.datastore)
Expand Down Expand Up @@ -115,4 +117,4 @@ dependencies {
androidTestImplementation(libs.accompanist.testharness)
androidTestImplementation(libs.androidx.navigation.testing)
androidTestImplementation(libs.hilt.android.testing)
}
}
86 changes: 86 additions & 0 deletions app/google-services.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
{
"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.wei.picquest"
}
},
"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.wei.picquest.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.wei.picquest.demo"
}
},
"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.wei.picquest.demo.debug"
}
},
"oauth_client": [],
"api_key": [
{
"current_key": "APlaceholderAPIKeyWith-ThirtyNineCharsX"
}
],
"services": {
"appinvite_service": {
"other_platform_oauth_client": []
}
}
}
],
"configuration_version": "1"
}
7 changes: 6 additions & 1 deletion app/src/main/java/com/wei/picquest/MainActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ import androidx.lifecycle.Lifecycle
import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.repeatOnLifecycle
import com.google.accompanist.adaptive.calculateDisplayFeatures
import com.wei.picquest.core.analytics.AnalyticsHelper
import com.wei.picquest.core.analytics.LocalAnalyticsHelper
import com.wei.picquest.core.data.utils.NetworkMonitor
import com.wei.picquest.core.designsystem.theme.PqTheme
import com.wei.picquest.core.manager.SnackbarManager
Expand All @@ -40,6 +42,9 @@ class MainActivity : ComponentActivity() {
@Inject
lateinit var networkMonitor: NetworkMonitor

@Inject
lateinit var analyticsHelper: AnalyticsHelper

private val viewModel: MainActivityViewModel by viewModels()

override fun onCreate(savedInstanceState: Bundle?) {
Expand Down Expand Up @@ -95,7 +100,7 @@ class MainActivity : ComponentActivity() {
onDispose {}
}

CompositionLocalProvider {
CompositionLocalProvider(LocalAnalyticsHelper provides analyticsHelper) {
PqTheme(darkTheme = darkTheme) {
PqApp(
networkMonitor = networkMonitor,
Expand Down
14 changes: 14 additions & 0 deletions build-logic/convention/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,20 @@ tasks.withType<KotlinCompile>().configureEach {

dependencies {
compileOnly(libs.android.gradlePlugin)
compileOnly(libs.android.tools.common)
compileOnly(libs.firebase.crashlytics.gradlePlugin)
compileOnly(libs.firebase.performance.gradlePlugin)
compileOnly(libs.kotlin.gradlePlugin)
compileOnly(libs.ksp.gradlePlugin)
}

tasks {
validatePlugins {
failOnWarning.set(true)
enableStricterValidation.set(true)
}
}

gradlePlugin {
plugins {
register("androidApplicationCompose") {
Expand Down Expand Up @@ -54,6 +64,10 @@ gradlePlugin {
id = "pq.android.hilt"
implementationClass = "AndroidHiltConventionPlugin"
}
register("androidFirebase") {
id = "pq.android.application.firebase"
implementationClass = "AndroidApplicationFirebaseConventionPlugin"
}
register("androidFlavors") {
id = "pq.android.application.flavors"
implementationClass = "AndroidApplicationFlavorsConventionPlugin"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import com.android.build.api.dsl.ApplicationExtension
import com.google.firebase.crashlytics.buildtools.gradle.CrashlyticsExtension
import com.wei.picquest.libs
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.kotlin.dsl.configure
import org.gradle.kotlin.dsl.dependencies

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")
}

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<ApplicationExtension> {
buildTypes.configureEach {
// Disable the Crashlytics mapping file upload. This feature should only be
// enabled if a Firebase backend is available and configured in
// google-services.json.
configure<CrashlyticsExtension> {
mappingFileUploadEnabled = false
}
}
}
}
}
}
3 changes: 3 additions & 0 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ plugins {
alias(libs.plugins.android.library) apply false
alias(libs.plugins.kotlin.android) apply false
alias(libs.plugins.navigation.safeargs.kotlin) apply false
alias(libs.plugins.firebase.crashlytics) apply false
alias(libs.plugins.firebase.perf) apply false
alias(libs.plugins.gms) apply false
alias(libs.plugins.hilt) apply false
alias(libs.plugins.kotlin.jvm) apply false
alias(libs.plugins.kotlin.serialization) apply false
Expand Down
1 change: 1 addition & 0 deletions core/analytics/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/build
16 changes: 16 additions & 0 deletions core/analytics/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
plugins {
alias(libs.plugins.pq.android.library)
alias(libs.plugins.pq.android.library.compose)
alias(libs.plugins.pq.android.hilt)
}

android {
namespace = "com.wei.picquest.core.analytics"
}

dependencies {
implementation(libs.androidx.compose.runtime)

prodImplementation(platform(libs.firebase.bom))
prodImplementation(libs.firebase.analytics)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.wei.picquest.core.analytics

import dagger.Binds
import dagger.Module
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent

@Module
@InstallIn(SingletonComponent::class)
internal abstract class AnalyticsModule {
@Binds
abstract fun bindsAnalyticsHelper(analyticsHelperImpl: StubAnalyticsHelper): AnalyticsHelper
}
4 changes: 4 additions & 0 deletions core/analytics/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">

</manifest>
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package com.wei.picquest.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"
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.wei.picquest.core.analytics

/**
* Interface for logging analytics events. See `FirebaseAnalyticsHelper` and
* `StubAnalyticsHelper` for implementations.
*/
interface AnalyticsHelper {
fun logEvent(event: AnalyticsEvent)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.wei.picquest.core.analytics

/**
* Implementation of AnalyticsHelper which does nothing. Useful for tests and previews.
*/
class NoOpAnalyticsHelper : AnalyticsHelper {
override fun logEvent(event: AnalyticsEvent) = Unit
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package com.wei.picquest.core.analytics

import timber.log.Timber
import javax.inject.Inject
import javax.inject.Singleton

/**
* An implementation of AnalyticsHelper just writes the events to logcat. Used in builds where no
* analytics events should be sent to a backend.
*/
@Singleton
internal class StubAnalyticsHelper
@Inject
constructor() : AnalyticsHelper {
override fun logEvent(event: AnalyticsEvent) {
Timber.d("StubAnalyticsHelper, Received analytics event: $event")
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.wei.picquest.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()
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package com.wei.picquest.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)
internal abstract class AnalyticsModule {
@Binds
abstract fun bindsAnalyticsHelper(analyticsHelperImpl: FirebaseAnalyticsHelper): AnalyticsHelper

companion object {
@Provides
@Singleton
fun provideFirebaseAnalytics(): FirebaseAnalytics {
return Firebase.analytics
}
}
}
Loading

0 comments on commit a8deb6a

Please sign in to comment.