morristech
2/14/2019 - 10:11 PM

Writing SOLID Analytics With Kotlin for Android - Check out the UPDATED GitHub Repo: https://github.com/sofakingforever/kotlin-analytics/

Writing SOLID Analytics With Kotlin for Android - Check out the UPDATED GitHub Repo: https://github.com/sofakingforever/kotlin-analytics/

package com.sofakingforever.analytics

// This code demonstrates how you could (should) decouple analytics libraries
// (or anything else) from your business logic code,
// effectively allowing you to add & remove analytics services on-the-fly.

// https://medium.com/@nadavfima/how-to-build-better-analytics-with-kotlin-60ab50ce25ac


class Analytics(private vararg val dispatchers: AnalyticsDispatcher) {


    @Volatile
    var isAnalyticsEnabled = true

    fun trackContentView(vararg contentViews: AnalyticsContentView) {

        if (!isAnalyticsEnabled) return

        contentViews.forEach { event ->
            dispatchers.forEach { dispatcher ->
                dispatcher.trackContentView(event)
            }
        }


    }

    fun trackCustomEvent(vararg events: AnalyticsEvent) {

        if (!isAnalyticsEnabled) return

        events.forEach {
            dispatchers.forEach { dispatcher ->
                dispatcher.trackCustomEvent(it)
            }
        }
    }

}
package com.sofakingforever.analytics

interface AnalyticsDispatcher {

    fun trackContentView(contentView: AnalyticsContentView)

    fun trackCustomEvent(event: AnalyticsEvent)

}
package com.sofakingforever.analytics.dispatchers

import com.crashlytics.android.answers.Answers
import com.crashlytics.android.answers.ContentViewEvent
import com.crashlytics.android.answers.CustomEvent
import com.sofakingforever.analytics.AnalyticsDispatcher
import com.sofakingforever.analytics.AnalyticsContentView
import com.sofakingforever.analytics.AnalyticsEvent

class AnswersDispatcherImpl : AnalyticsDispatcher {

    override fun trackCustomEvent(event: AnalyticsEvent) {
        Answers.getInstance().logCustom(event.createAnswersAnalyticsEvent())
    }

    override fun trackContentView(contentView: AnalyticsContentView) {
        Answers.getInstance().logContentView(contentView.createAnswersEvent())
    }

    private fun AnalyticsEvent.createAnswersAnalyticsEvent(): CustomEvent {
        return CustomEvent(this.getEventName())
                .apply {

                    this@createAnswersAnalyticsEvent.getParameters()
                            .forEach {
                                if (it.value is Number) {
                                    putCustomAttribute(it.key, it.value as Number)
                                } else if (it.value is String) {
                                    putCustomAttribute(it.key, it.value as String)
                                } else {
                                    throw RuntimeException("value type " + it.value.javaClass.toString() + " is illegal")
                                }
                            }

                }
    }


    private fun AnalyticsContentView.createAnswersEvent(): ContentViewEvent {
        return ContentViewEvent().putContentName(this.getViewName())
    }

}

package com.sofakingforever.analytics

interface AnalyticsContentView {

    fun getViewName(): String

}

interface AnalyticsEvent {

    fun getEventName(): String

    fun getParameters(): MutableMap<String, Any> {
        return mutableMapOf()
    }

}


class ExampleApp : Application() {

    lateinit var analytics: Analytics

    override fun onCreate() {
    
    analytics = Analytics(AnswersDispatcherImpl()).apply { isAnalyticsEnabled = true } // or false
        
    analytics.trackCustomEvent(ExampleEvent());
    
    }
}
class ExampleEvent : AnalyticsEvent {
    override fun getEventName(): String = "example_event"
}