Skip to content

Commit

Permalink
Merge pull request #525 from deBasMan21/feat/Analytics
Browse files Browse the repository at this point in the history
Add firebase analytics
  • Loading branch information
nbransby authored Jun 16, 2024
2 parents ba3d156 + fb79f41 commit bf112f7
Show file tree
Hide file tree
Showing 21 changed files with 957 additions and 0 deletions.
2 changes: 2 additions & 0 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ jobs:
run: ./gradlew :updateVersions
- name: Grant execute permission for gradlew
run: chmod +x gradlew
- name: Publish Firebase Analytics
run: ./gradlew :firebase-analytics:publish
- name: Publish Firebase App
run: ./gradlew :firebase-app:publish
- name: Publish Firebase Auth
Expand Down
1 change: 1 addition & 0 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ val minSdkVersion by extra(23)
tasks {
register("updateVersions") {
dependsOn(
"firebase-analytics:updateVersion", "firebase-analytics:updateDependencyVersion",
"firebase-app:updateVersion", "firebase-app:updateDependencyVersion",
"firebase-auth:updateVersion", "firebase-auth:updateDependencyVersion",
"firebase-common:updateVersion", "firebase-common:updateDependencyVersion",
Expand Down
173 changes: 173 additions & 0 deletions firebase-analytics/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSetTree

/*
* Copyright (c) 2023 GitLive Ltd. Use of this source code is governed by the Apache 2.0 license.
*/

version = project.property("firebase-analytics.version") as String

plugins {
id("com.android.library")
kotlin("native.cocoapods")
kotlin("multiplatform")
}

android {
val minSdkVersion: Int by project
val compileSdkVersion: Int by project

compileSdk = compileSdkVersion
namespace = "dev.gitlive.firebase.analytics"

defaultConfig {
minSdk = minSdkVersion
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
}

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

testOptions {
unitTests.apply {
isIncludeAndroidResources = true
}
}
packaging {
resources.pickFirsts.add("META-INF/kotlinx-serialization-core.kotlin_module")
resources.pickFirsts.add("META-INF/AL2.0")
resources.pickFirsts.add("META-INF/LGPL2.1")
}
lint {
abortOnError = false
}
}

val supportIosTarget = project.property("skipIosTarget") != "true"

kotlin {

targets.configureEach {
compilations.configureEach {
kotlinOptions.freeCompilerArgs += "-Xexpect-actual-classes"
}
}

@Suppress("OPT_IN_USAGE")
androidTarget {
instrumentedTestVariant.sourceSetTree.set(KotlinSourceSetTree.test)
unitTestVariant.sourceSetTree.set(KotlinSourceSetTree.test)
publishAllLibraryVariants()
compilations.configureEach {
kotlinOptions {
jvmTarget = "11"
}
}
}

jvm {
compilations.getByName("main") {
kotlinOptions {
jvmTarget = "17"
}
}
compilations.getByName("test") {
kotlinOptions {
jvmTarget = "17"
}
}
}

if (supportIosTarget) {
iosArm64()
iosX64()
iosSimulatorArm64()
cocoapods {
ios.deploymentTarget = "12.0"
framework {
baseName = "FirebaseAnalytics"
}
noPodspec()
pod("FirebaseAnalytics") {
version = "10.25.0"
extraOpts += listOf("-compiler-option", "-fmodules")
}
}
}

js(IR) {
useCommonJs()
nodejs {
testTask(
Action {
useKarma {
useChromeHeadless()
}
}
)
}
browser {
testTask(
Action {
useKarma {
useChromeHeadless()
}
}
)
}
}

sourceSets {
all {
languageSettings.apply {
val apiVersion: String by project
val languageVersion: String by project
this.apiVersion = apiVersion
this.languageVersion = languageVersion
progressiveMode = true
if (name.lowercase().contains("ios")) {
optIn("kotlinx.cinterop.ExperimentalForeignApi")
}
}
}

getByName("commonMain") {
dependencies {
api(project(":firebase-app"))
implementation(project(":firebase-common"))
}
}

getByName("commonTest") {
dependencies {
implementation(project(":test-utils"))
}
}

getByName("androidMain") {
dependencies {
api("com.google.firebase:firebase-analytics")
}
}
}
}

if (project.property("firebase-analytics.skipIosTests") == "true") {
tasks.forEach {
if (it.name.contains("ios", true) && it.name.contains("test", true)) { it.enabled = false }
}
}

if (project.property("firebase-analytics.skipJsTests") == "true") {
tasks.forEach {
if (it.name.contains("js", true) && it.name.contains("test", true)) { it.enabled = false }
}
}

signing {
val signingKey: String? by project
val signingPassword: String? by project
useInMemoryPgpKeys(signingKey, signingPassword)
sign(publishing.publications)
}
39 changes: 39 additions & 0 deletions firebase-analytics/firebase_analytics.podspec
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
Pod::Spec.new do |spec|
spec.name = 'firebase_analytics'
spec.version = '1.8.1'
spec.homepage = ''
spec.source = { :http=> ''}
spec.authors = ''
spec.license = ''
spec.summary = ''
spec.vendored_frameworks = 'build/cocoapods/framework/firebase_analytics.framework'
spec.libraries = 'c++'



spec.pod_target_xcconfig = {
'KOTLIN_PROJECT_PATH' => ':firebase-analytics',
'PRODUCT_MODULE_NAME' => 'firebase_analytics',
}

spec.script_phases = [
{
:name => 'Build firebase_analytics',
:execution_position => :before_compile,
:shell_path => '/bin/sh',
:script => <<-SCRIPT
if [ "YES" = "$OVERRIDE_KOTLIN_BUILD_IDE_SUPPORTED" ]; then
echo "Skipping Gradle build task invocation due to OVERRIDE_KOTLIN_BUILD_IDE_SUPPORTED environment variable set to \"YES\""
exit 0
fi
set -ev
REPO_ROOT="$PODS_TARGET_SRCROOT"
"$REPO_ROOT/../gradlew" -p "$REPO_ROOT" $KOTLIN_PROJECT_PATH:syncFramework \
-Pkotlin.native.cocoapods.platform=$PLATFORM_NAME \
-Pkotlin.native.cocoapods.archs="$ARCHS" \
-Pkotlin.native.cocoapods.configuration="$CONFIGURATION"
SCRIPT
}
]

end
31 changes: 31 additions & 0 deletions firebase-analytics/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
{
"name": "@gitlive/firebase-analytics",
"version": "1.12.0",
"description": "Wrapper around firebase for usage in Kotlin Multiplatform projects",
"main": "firebase-analytics.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"repository": {
"type": "git",
"url": "git+https://github.com/GitLiveApp/firebase-kotlin-sdk.git"
},
"keywords": [
"kotlin",
"multiplatform",
"kotlin-js",
"firebase"
],
"author": "dev.gitlive",
"license": "Apache-2.0",
"bugs": {
"url": "https://github.com/GitLiveApp/firebase-kotlin-sdk/issues"
},
"homepage": "https://github.com/GitLiveApp/firebase-kotlin-sdk",
"dependencies": {
"@gitlive/firebase-app": "1.12.0",
"firebase": "9.19.1",
"kotlin": "1.6.10",
"kotlinx-coroutines-core": "1.6.1-native-mt"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android">

<application android:usesCleartextTraffic="true" />
</manifest>
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
/*
* Copyright (c) 2020 GitLive Ltd. Use of this source code is governed by the Apache 2.0 license.
*/

@file:JvmName("tests")
package dev.gitlive.firebase.analytics

import androidx.test.platform.app.InstrumentationRegistry

actual val emulatorHost: String = "10.0.2.2"

actual val context: Any = InstrumentationRegistry.getInstrumentation().targetContext

@Target(AnnotationTarget.CLASS, AnnotationTarget.FUNCTION)
actual annotation class IgnoreForAndroidUnitTest
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
@file:JvmName("analyticsAndroid")
package dev.gitlive.firebase.analytics

import android.os.Bundle
import android.os.IBinder
import android.os.Parcelable
import android.util.Size
import android.util.SizeF
import com.google.firebase.analytics.analytics
import com.google.firebase.analytics.setConsent
import dev.gitlive.firebase.Firebase
import dev.gitlive.firebase.FirebaseApp
import kotlinx.coroutines.tasks.await
import java.io.Serializable

actual val Firebase.analytics: FirebaseAnalytics
get() = FirebaseAnalytics(com.google.firebase.Firebase.analytics)

actual fun Firebase.analytics(app: FirebaseApp) =
FirebaseAnalytics(com.google.firebase.Firebase.analytics)

actual class FirebaseAnalytics(val android: com.google.firebase.analytics.FirebaseAnalytics) {
actual fun logEvent(name: String, parameters: Map<String, Any>?) {
android.logEvent(name, parameters?.toBundle())
}
actual fun setUserProperty(name: String, value: String) {
android.setUserProperty(name, value)
}
actual fun setUserId(id: String) {
android.setUserId(id)
}
actual fun resetAnalyticsData() {
android.resetAnalyticsData()
}
actual fun setDefaultEventParameters(parameters: Map<String, String>) {
android.setDefaultEventParameters(parameters.toBundle())
}

actual fun setAnalyticsCollectionEnabled(enabled: Boolean) {
android.setAnalyticsCollectionEnabled(enabled)
}

actual fun setSessionTimeoutInterval(sessionTimeoutInterval: Long) {
android.setSessionTimeoutDuration(sessionTimeoutInterval)
}

actual suspend fun getSessionId(): Long? = android.sessionId.await()

actual fun setConsent(consentSettings: Map<ConsentType, ConsentStatus>) {
consentSettings.entries.associate {
it.key to when (it.value) {
ConsentStatus.GRANTED -> com.google.firebase.analytics.FirebaseAnalytics.ConsentStatus.GRANTED
ConsentStatus.DENIED -> com.google.firebase.analytics.FirebaseAnalytics.ConsentStatus.DENIED
}
}.let { androidConsentSettings ->
android.setConsent {
androidConsentSettings.entries.forEach {
when (it.key) {
ConsentType.AD_PERSONALIZATION ->
this.adPersonalization = it.value

ConsentType.AD_STORAGE ->
this.adStorage = it.value

ConsentType.AD_USER_DATA ->
this.adUserData = it.value

ConsentType.ANALYTICS_STORAGE ->
this.analyticsStorage = it.value
}
}

}
}
}

actual enum class ConsentType {
AD_PERSONALIZATION,
AD_STORAGE,
AD_USER_DATA,
ANALYTICS_STORAGE
}

actual enum class ConsentStatus {
GRANTED,
DENIED
}
}

actual class FirebaseAnalyticsException(message: String): Exception(message)

private fun Map<String, Any>.toBundle() = Bundle().apply {
forEach { (key, value) ->
when(value::class) {
String::class -> putString(key, value as String)
Int::class -> putInt(key, value as Int)
Long::class -> putLong(key, value as Long)
Double::class -> putDouble(key, value as Double)
Boolean::class -> putBoolean(key, value as Boolean)
}

}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package dev.gitlive.firebase.analytics

import org.junit.Ignore

actual val emulatorHost: String = "10.0.2.2"

actual val context: Any = ""

actual typealias IgnoreForAndroidUnitTest = Ignore
Loading

0 comments on commit bf112f7

Please sign in to comment.