Analytics Tools for Kotlin Multiplatform Mobile iOS and android

Overview

abc-kmm-analytics-tools: Analytics Tools for Kotlin Multiplatform Mobile iOS and android

Kotlin KMM AGP Gradle Platform

Index

Features

  • Unified handling of various event trackers is possible
  • Automatically tracking and sending events of screen view and capture
  • Provide screen name mapper
  • Remove boilerplate by binding UI elements to event triggers
  • Common interfaces available in KMM Shared

Example

Requirements

  • iOS
    • Deployment Target 10.0 or higher
  • Android
    • minSdkVersion 21

Installation

Gradle Settings

Add below gradle settings into your KMP (Kotlin Multiplatform Project)

build.gradle.kts in shared

() .forEach { it.baseName = "shared" it.transitiveExport = true it.export(analyticsTools) } } sourceSets { val commonMain by getting { dependencies { implementation(analyticsTools) } } val commonTest by getting { dependencies { implementation(kotlin("test-common")) implementation(kotlin("test-annotations-common")) } } val androidMain by getting { dependencies { implementation(analyticsTools) api(analyticsTools) } } val androidTest by getting { dependencies { implementation(kotlin("test-junit")) implementation("junit:junit:4.13.2") implementation("androidx.test:core:1.0.0") implementation("androidx.test:runner:1.1.0") implementation("org.robolectric:robolectric:4.2") } } val iosMain by getting { dependencies { implementation(analyticsTools) api(analyticsTools) } } val iosTest by getting } } ">
plugins {
    id("com.android.library")
    kotlin("multiplatform")
    kotlin("native.cocoapods")
}

val analyticsTools = "com.linecorp.abc:kmm-analytics-tools:1.0.14"

kotlin {
    android()
    ios {
        binaries
            .filterIsInstance<Framework>()
            .forEach {
                it.baseName = "shared"
                it.transitiveExport = true
                it.export(analyticsTools)
            }
    }

    sourceSets {
        val commonMain by getting {
            dependencies {
                implementation(analyticsTools)
            }
        }
        val commonTest by getting {
            dependencies {
                implementation(kotlin("test-common"))
                implementation(kotlin("test-annotations-common"))
            }
        }
        val androidMain by getting {
            dependencies {
                implementation(analyticsTools)
                api(analyticsTools)
            }
        }
        val androidTest by getting {
            dependencies {
                implementation(kotlin("test-junit"))
                implementation("junit:junit:4.13.2")
                implementation("androidx.test:core:1.0.0")
                implementation("androidx.test:runner:1.1.0")
                implementation("org.robolectric:robolectric:4.2")
            }
        }
        val iosMain by getting {
            dependencies {
                implementation(analyticsTools)
                api(analyticsTools)
            }
        }
        val iosTest by getting
    }
}

Project Settings

Android

  • You can use right now without other settings.

iOS

  1. Create Podfile with below setting in your project root.
    use_frameworks!
    
    platform :ios, '10.0'
    
    install! 'cocoapods', :deterministic_uuids => false
    
    target 'iosApp' do
        pod 'shared', :path => '../shared/'
    end
  2. Run command pod install on the terminal

Configure

Using Screen Mapper

Screen mapper is mapping system that to map between screen class and screen name. The file ATScreenNameMapper.json that defines screen mapping table will automatically used if needed in system.

Android

  1. Create a file named ATScreenNameMapper.json in your assets folder like below.

  2. Write table as json format for screen name mapping.

{
  "MainActivity": "main"
}

iOS

  1. Create a file named ATScreenNameMapper.json in your project like below.

  2. Write table as json format for screen name mapping.

{
  "MainViewController": "main"
}

Initialization

Android

ATEventCenter.setConfiguration {
    canTrackScreenView { true }
    canTrackScreenCapture { true }
    register(TSDelegate())
    register(GoogleAnalyticsDelegate())
}

iOS

<.(.*)>", options: .allowCommentsAndWhitespace) let str = String(describing: type(of: self)) let range = NSMakeRange(0, str.count) return regex.stringByReplacingMatches(in: str, options: .reportCompletion, range: range, withTemplate: "") } } ">
ATEventCenter.Companion().setConfiguration {
    $0.canTrackScreenView { _ in
        true
    }
    $0.canTrackScreenCapture {
        true
    }
    $0.mapScreenClass {
        $0.className()
    }
    $0.topViewController {
        UIViewController.topMost
    }
    $0.register(delegate: TSDelegate())
    $0.register(delegate: GoogleAnalyticsDelegate())
}

extension UIViewController {
    static var topMost: UIViewController? {
        UIViewControllerUtil.Companion().topMost()
    }

    var className: String {
        let regex = try! NSRegularExpression(pattern: "<.(.*)>", options: .allowCommentsAndWhitespace)
        let str = String(describing: type(of: self))
        let range = NSMakeRange(0, str.count)
        return regex.stringByReplacingMatches(in: str, options: .reportCompletion, range: range, withTemplate: "")
    }
}

Setup User Properties

This function must be called in the scope where the user properties are changed

Android or Shared

ATEventCenter.setUserProperties()

iOS

ATEventCenter.Companion().setUserProperties()

Implementation

Delegate

Delegate class is proxy for various event trackers.

Android or Shared

class GoogleAnalyticsDelegate: ATEventDelegate {
    // @optional to map key of event
    override fun mapEventKey(event: Event): String {
        event.value
    }

    // @optional to map key of parameter
    override fun mapParamKey(container: KeyValueContainer): String {
        container.key
    }

    // @required to set up event tracker
    override fun setup() {
    }

    // @required to set user properties for event tracker
    override fun setUserProperties() {
    }

    // @required to send event to the event tracker
    override fun send(event: String, params: Map<String, String>) {
    }
}

iOS

final class GoogleAnalyticsDelegate: ATEventDelegate {
    // @required to map key of parameter
    func mapEventKey(event: Event) -> String {
        event.value
    }

    // @required to map key of parameter
    func mapParamKey(container: KeyValueContainer) -> String {
        container.key
    }
    
    // @required to set up event tracker
    func setup() {
    }

    // @required to set user properties for event tracker
    func setUserProperties() {
    }
    
    // @required to send event to the event tracker
    func send(event: String, params: [String: String]) {
    }
}

Parameters

Kotlin

sealed class Param: KeyValueContainer {
    data class UserName(override val value: String): Param()
    data class ViewTime(override val value: Int): Param()
}

Swift

enum Param {
    final class UserName: AnyKeyValueContainer
    {}
    final class ViewTime: AnyKeyValueContainer
    {}
}

If you want something more swift, use your own KeyValueContainer.

enum Param {
    final class UserName: MyKeyValueContainer<String> {}
    final class ViewTime: MyKeyValueContainer<Int> {}
}

class MyKeyValueContainer<T: Any>: KeyValueContainer {
    init(_ value: T) {
        self.value = value
    }
    
    let value: Any
    
    var key: String {
        "\(self)".components(separatedBy: ".").last?.snakenized ?? ""
    }
}

ATEventParamProvider

ATEventParamProvider is used to get extra parameters when send to events and functions are called automatically.

Android

listOf() } } } ">
class MainActivity : AppCompatActivity(), ATEventParamProvider {
    override fun params(event: Event, source: Any?): List<KeyValueContainer> {
        return when(event) {
            Event.VIEW -> listOf(
                Param.UserName("steve"),
                Param.ViewTime(10000))
            else -> listOf()
        }
    }
}

iOS

extension MainViewController: ATEventParamProvider {
    func params(event: Event, source: Any?) -> [KeyValueContainer] {
        switch event {
        case .view:
            return [
                Param.UserName("steve"), 
                Param.ViewTime(10000)
            ]
        default:
            return []
        }
    }
}

ATEventTriggerUICompatible (iOS Only)

This is an interface to make it easy to connect the click event of a ui element to an event trigger.

extension UIControl: ATEventTriggerUICompatible {
    public func registerTrigger(invoke: @escaping () -> Void) {
        rx.controlEvent(.touchUpInside)
            .bind { invoke() }
            .disposed(by: disposeBag)
    }
}

Integration with UI

Android

Legacy

  • Using with Event Trigger
v.eventTrigger.send() } } } ">
sealed class Param: KeyValueContainer {
    data class UserName(override val value: String): Param()
}

class MainActivity : AppCompatActivity(), ATEventParamProvider {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val button = findViewById<Button>(R.id.button)
        
        button.eventTrigger
            .click("button")
            .register { listOf(Param.UserName("steve")) }

        button.setOnClickListener { v ->
            v.eventTrigger.send()
        }
    }
}
  • Using Directly
">
<Button
      android:id="@+id/button"
      android:text="Hello!"
      android:onClick="onClickHello"/>
fun onClickHello(view: View) {
    ATEventCenter.send(
        Event.CLICK,
        listOf(BaseParam.ClickSource("hello")))
}

iOS

SwiftUI

Button("Hello") {
    ATEventCenter.Companion().send(
        event: .click,
        params: [BaseParam.ClickSource(value: "hello")])
}

Legacy

Using with Event Trigger

  • Extension to get instance of ATEventTrigger
extension ATEventTriggerCompatible {
    var eventTrigger: ATEventTrigger<Self> {
        ATEventTriggerFactory.Companion().create(owner: self) as! ATEventTrigger<Self>
    }
}
  • Extension to make it easy to connect the click event of a ui element to an event trigger
extension UIControl: ATEventTriggerUICompatible {
    public func registerTrigger(invoke: @escaping () -> Void) {
        rx.controlEvent(.touchUpInside)
            .bind { invoke() }
            .disposed(by: disposeBag)
    }
}
  • Client side
enum Param {
    final class UserName: AnyKeyValueContainer
    { }
}

override func viewDidLoad() {
    super.viewDidLoad()
    
    button.eventTrigger
        .click(source: "hello")
        .register { [Param.UserName("steve")] }
}

Using Directly

@IBAction func clicked(_ sender: UIButton) {
    ATEventCenter.Companion().send(
        event: .click,
        params: [BaseParam.ClickSource(value: "hello")])
}

TODO

  • Publish to maven repository
  • Write install guide
  • Integration UI with event trigger for iOS
    • LegacyUI
    • SwiftUI
  • Integration UI with event trigger for Android
    • Legacy
      • View, Any
    • Compose
You might also like...
A tool that enables advanced features through adb installing and uninstalling apps like wildcards and multi device support. Useful if you want to clean your test device from all company apks or install a lot of apks in one go.  Written in Java so it should run on your platform.
Sweet Android libraries written in Kotlin

Kandy A Kotlin library set dedicated to Android platform which will make programming sweet again! Repository All modules are available on the jcenter.

The Kotlin fake data generator library!
The Kotlin fake data generator library!

Fakeit This library is a port of the Ruby gem Faker. It generates realistic fake data — like names, emails, dates, countries — for a variety of scenar

A CLI client for Up Bank, written in Kotlin.

upperkt pronounced /ˈʌpəkʌt/ Uppercut your Up balance today! (It's a CLI client for Up - an Australian neobank, written in Kotlin) Installing Right no

Simple library to generate and view PDF in Android
Simple library to generate and view PDF in Android

PDFCreatorAndroid Simple library to generate and view PDF in Android A simple library to create and view PDF with zero dependency Or native code. Add

Android Material Design Theme UI and Tool Library. Support: 4.0.3~O
Android Material Design Theme UI and Tool Library. Support: 4.0.3~O

GitHub OSChina 中文 English Genius-Android Genius-Android: by Material Design style and some commonly used packages. Starting in 2015, The divided into

It makes a preview from an url, grabbing all the information such as title, relevant texts and images. This a version for Android of my web link preview https://github.com/LeonardoCardoso/Link-Preview
It makes a preview from an url, grabbing all the information such as title, relevant texts and images. This a version for Android of my web link preview https://github.com/LeonardoCardoso/Link-Preview

LeoCardz Link Preview for Android It makes a preview from an url, grabbing all the information such as title, relevant texts and images. Visual Exampl

Android USB host serial driver library for CDC, FTDI, Arduino and other devices.

usb-serial-for-android This is a driver library for communication with Arduinos and other USB serial hardware on Android, using the Android USB Host M

Modulearchive - Improve the efficiency of compiling Android.Package module as AAR and cache it
Modulearchive - Improve the efficiency of compiling Android.Package module as AAR and cache it

ModuleArchive 一个可以提升Android编译效率的Gradle小插件 在多module工程下,大多数情况我们若干子module是不会变动的 但是在当前gradle版本偶尔会触发联动编译进而影响编译效率。 本插件会自动缓存编译后的子模块生产物(xxx.aar),且会自动替换依赖为aar依

Releases(1.1.0)
Owner
LINE
LINE
Tiny tracking lib for Google Analytics.

BloodHoud Tiny library for tracking screens and events with google analytics and / or firebase analytics. How to install repositories { maven {

Jan Rabe 22 Oct 5, 2022
🍼Debug Bottle is an Android runtime debug / develop tools written using kotlin language.

???? 中文 / ???? 日本語 / ???? English ?? Debug Bottle An Android debug / develop tools written using Kotlin language. All the features in Debug bottle are

Yuriel Arlencloyn 846 Nov 14, 2022
A tool to install components of the Android SDK into a Maven repository or repository manager to use with the Android Maven Plugin, Gradle and other tools.

Maven Android SDK Deployer Original author including numerous fixes and changes: Manfred Moser [email protected] at simpligility technologies i

simpligility 1.4k Dec 27, 2022
A tool to install components of the Android SDK into a Maven repository or repository manager to use with the Android Maven Plugin, Gradle and other tools.

Maven Android SDK Deployer Original author including numerous fixes and changes: Manfred Moser [email protected] at simpligility technologies i

simpligility 1.4k Dec 27, 2022
Combines tools for fast android app devlopment

Android - Rapid Test Driven Development Combine tools to generate most of the boilerplate code. Examples how to test different aspects of an android a

Nico Küchler 379 Nov 25, 2022
A set of Android tools that facilitate apps development

A set of Android tools that facilitate apps development Well, this repo contains pretty much code used internally at Stanfy to develop Android apps. S

Stanfy 183 Dec 3, 2022
An easy to use translation / localization api written in Kotlin that can be used with Java and Kotlin

KTranslate KTranslate is an easy to use TranslationAPI written in Kotlin, with currently 26 supported languages. It is very easy to use in Kotlin and

Felix Beinssen 0 Sep 2, 2022
Android Resource Manager application to manage and analysis your app resources with many features like image resize, Color, Dimens and code Analysis

Android Resource Manager application to manage and analysis your app resources with many features like image resize, Color, Dimens and code Analysis

Amr Hesham 26 Nov 16, 2022