Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/add analytics #114

Merged
merged 3 commits into from
May 10, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 13 additions & 11 deletions app/src/main/java/no/nordicsemi/android/nrftoolbox/view/HomeView.kt
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import androidx.hilt.navigation.compose.hiltViewModel
import no.nordicsemi.android.analytics.Link
import no.nordicsemi.android.analytics.Profile
import no.nordicsemi.android.analytics.ProfileOpenEvent
import no.nordicsemi.android.logger.LoggerAppRunner
import no.nordicsemi.android.nrftoolbox.BuildConfig
Expand Down Expand Up @@ -57,14 +59,14 @@ fun HomeScreen() {

FeatureButton(R.drawable.ic_gls, R.string.gls_module, R.string.gls_module_full) {
viewModel.openProfile(ProfileDestination.GLS)
viewModel.logEvent(ProfileOpenEvent.GLS)
viewModel.logEvent(ProfileOpenEvent(Profile.GLS))
}

Spacer(modifier = Modifier.height(16.dp))

FeatureButton(R.drawable.ic_bps, R.string.bps_module, R.string.bps_module_full) {
viewModel.openProfile(ProfileDestination.BPS)
viewModel.logEvent(ProfileOpenEvent.BPS)
viewModel.logEvent(ProfileOpenEvent(Profile.BPS))
}

Spacer(modifier = Modifier.height(16.dp))
Expand All @@ -79,42 +81,42 @@ fun HomeScreen() {

FeatureButton(R.drawable.ic_csc, R.string.csc_module, R.string.csc_module_full, state.isCSCModuleRunning) {
viewModel.openProfile(ProfileDestination.CSC)
viewModel.logEvent(ProfileOpenEvent.CSC)
viewModel.logEvent(ProfileOpenEvent(Profile.CSC))
}

Spacer(modifier = Modifier.height(16.dp))

FeatureButton(R.drawable.ic_hrs, R.string.hrs_module, R.string.hrs_module_full, state.isHRSModuleRunning) {
viewModel.openProfile(ProfileDestination.HRS)
viewModel.logEvent(ProfileOpenEvent.HRS)
viewModel.logEvent(ProfileOpenEvent(Profile.HRS))
}

Spacer(modifier = Modifier.height(16.dp))

FeatureButton(R.drawable.ic_hts, R.string.hts_module, R.string.hts_module_full, state.isHTSModuleRunning) {
viewModel.openProfile(ProfileDestination.HTS)
viewModel.logEvent(ProfileOpenEvent.HTS)
viewModel.logEvent(ProfileOpenEvent(Profile.HTS))
}

Spacer(modifier = Modifier.height(16.dp))

FeatureButton(R.drawable.ic_rscs, R.string.rscs_module, R.string.rscs_module_full, state.isRSCSModuleRunning) {
viewModel.openProfile(ProfileDestination.RSCS)
viewModel.logEvent(ProfileOpenEvent.RSCS)
viewModel.logEvent(ProfileOpenEvent(Profile.RSCS))
}

Spacer(modifier = Modifier.height(16.dp))

FeatureButton(R.drawable.ic_cgm, R.string.cgm_module, R.string.cgm_module_full, state.isCGMModuleRunning) {
viewModel.openProfile(ProfileDestination.CGMS)
viewModel.logEvent(ProfileOpenEvent.CGMS)
viewModel.logEvent(ProfileOpenEvent(Profile.CGMS))
}

Spacer(modifier = Modifier.height(16.dp))

FeatureButton(R.drawable.ic_prx, R.string.prx_module, R.string.prx_module_full, state.isPRXModuleRunning) {
viewModel.openProfile(ProfileDestination.PRX)
viewModel.logEvent(ProfileOpenEvent.PRX)
viewModel.logEvent(ProfileOpenEvent(Profile.PRX))
}

Spacer(modifier = Modifier.height(16.dp))
Expand All @@ -129,7 +131,7 @@ fun HomeScreen() {

FeatureButton(R.drawable.ic_uart, R.string.uart_module, R.string.uart_module_full, state.isUARTModuleRunning) {
viewModel.openProfile(ProfileDestination.UART)
viewModel.logEvent(ProfileOpenEvent.UART)
viewModel.logEvent(ProfileOpenEvent(Profile.UART))
}

Spacer(modifier = Modifier.height(16.dp))
Expand All @@ -149,7 +151,7 @@ fun HomeScreen() {
} else {
uriHandler.openUri(DFU_LINK)
}
viewModel.logEvent(ProfileOpenEvent.DFU)
viewModel.logEvent(ProfileOpenEvent(Link.DFU))
}

Spacer(modifier = Modifier.height(16.dp))
Expand All @@ -160,7 +162,7 @@ fun HomeScreen() {

FeatureButton(R.drawable.ic_logger, R.string.logger_module, R.string.logger_module_full, null, loggerDescription) {
viewModel.openLogger()
viewModel.logEvent(ProfileOpenEvent.LOGGER)
viewModel.logEvent(ProfileOpenEvent(Link.LOGGER))
}

Spacer(modifier = Modifier.height(16.dp))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ class AppAnalytics @Inject constructor(

private val firebase by lazy { FirebaseAnalytics.getInstance(context) }

fun logEvent(event: AppEvent) {
firebase.logEvent(event.eventName, null)
fun logEvent(event: FirebaseEvent) {
firebase.logEvent(event.eventName, event.params)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package no.nordicsemi.android.analytics

import android.os.Bundle

sealed class FirebaseEvent(val eventName: String, val params: Bundle?)

object AppOpenEvent : FirebaseEvent("APP_OPEN", null)

class ProfileOpenEvent : FirebaseEvent {

constructor(profile: Profile) : super(EVENT_NAME, createBundle(profile.displayName))

constructor(link: Link) : super(EVENT_NAME, createBundle(link.displayName))

companion object {
private const val EVENT_NAME = "PROFILE_OPEN"
}
}

class ProfileConnectedEvent : FirebaseEvent {

constructor(profile: Profile) : super(EVENT_NAME, createBundle(profile.displayName))

constructor(link: Link) : super(EVENT_NAME, createBundle(link.displayName))

companion object {
private const val EVENT_NAME = "PROFILE_CONNECTED"
}
}

const val PROFILE_PARAM_KEY = "PROFILE_NAME"

private fun createBundle(name: String): Bundle {
return Bundle().apply { putString(PROFILE_PARAM_KEY, name) }
}

sealed class UARTAnalyticsEvent(eventName: String, params: Bundle?) : FirebaseEvent(eventName, params)

class UARTSendAnalyticsEvent(mode: UARTMode) : UARTAnalyticsEvent("UART_SEND_EVENT", createParams(mode)) {

companion object {
fun createParams(mode: UARTMode) = Bundle().apply {
putString("MODE", mode.displayName)
}
}
}

class UARTCreateConfiguration : UARTAnalyticsEvent("UART_CREATE_CONF", null)

class UARTChangeConfiguration : UARTAnalyticsEvent("UART_CHANGE_CONF", null)

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package no.nordicsemi.android.analytics

enum class Profile(val displayName: String) {
BPS("BPS"),
CGMS("CGMS"),
CSC("CSC"),
GLS("GLS"),
HRS("HRS"),
HTS("HTS"),
PRX("PRX"),
RSCS("RSCS"),
UART("UART");
}

enum class Link(val displayName: String) {
DFU("DFU"),
LOGGER("LOGGER");
}

enum class UARTMode(val displayName: String) {
MACRO("MACRO"),
TEXT("TEXT")
}
1 change: 1 addition & 0 deletions profile_bps/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ apply from: rootProject.file("library.gradle")
apply plugin: 'kotlin-parcelize'

dependencies {
implementation project(":lib_analytics")
implementation project(":lib_service")
implementation project(":lib_theme")
implementation project(":lib_utils")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,14 @@ import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import no.nordicsemi.android.analytics.AppAnalytics
import no.nordicsemi.android.analytics.Profile
import no.nordicsemi.android.analytics.ProfileConnectedEvent
import no.nordicsemi.android.bps.data.BPS_SERVICE_UUID
import no.nordicsemi.android.bps.repository.BPSRepository
import no.nordicsemi.android.bps.view.*
import no.nordicsemi.android.navigation.*
import no.nordicsemi.android.service.SuccessResult
import no.nordicsemi.android.utils.exhaustive
import no.nordicsemi.android.utils.getDevice
import no.nordicsemi.ui.scanner.DiscoveredBluetoothDevice
Expand All @@ -20,7 +24,8 @@ import javax.inject.Inject
@HiltViewModel
internal class BPSViewModel @Inject constructor(
private val repository: BPSRepository,
private val navigationManager: NavigationManager
private val navigationManager: NavigationManager,
private val analytics: AppAnalytics
) : ViewModel() {

private val _state = MutableStateFlow<BPSViewState>(NoDeviceState)
Expand Down Expand Up @@ -53,6 +58,10 @@ internal class BPSViewModel @Inject constructor(
private fun connectDevice(device: DiscoveredBluetoothDevice) {
repository.downloadData(device).onEach {
_state.value = WorkingState(it)

(it as? SuccessResult)?.let {
analytics.logEvent(ProfileConnectedEvent(Profile.BPS))
}
}.launchIn(viewModelScope)
}
}
1 change: 1 addition & 0 deletions profile_cgms/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ android {
}

dependencies {
implementation project(":lib_analytics")
implementation project(":lib_service")
implementation project(":lib_theme")
implementation project(":lib_utils")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,15 @@ import androidx.lifecycle.viewModelScope
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.flow.*
import kotlinx.coroutines.launch
import no.nordicsemi.android.analytics.AppAnalytics
import no.nordicsemi.android.analytics.Profile
import no.nordicsemi.android.analytics.ProfileConnectedEvent
import no.nordicsemi.android.cgms.data.CGMS_SERVICE_UUID
import no.nordicsemi.android.cgms.repository.CGMRepository
import no.nordicsemi.android.cgms.data.CGMServiceCommand
import no.nordicsemi.android.cgms.view.*
import no.nordicsemi.android.navigation.*
import no.nordicsemi.android.service.SuccessResult
import no.nordicsemi.android.utils.exhaustive
import no.nordicsemi.android.utils.getDevice
import no.nordicsemi.ui.scanner.ScannerDestinationId
Expand All @@ -18,7 +22,8 @@ import javax.inject.Inject
@HiltViewModel
internal class CGMViewModel @Inject constructor(
private val repository: CGMRepository,
private val navigationManager: NavigationManager
private val navigationManager: NavigationManager,
private val analytics: AppAnalytics
) : ViewModel() {

private val _state = MutableStateFlow<CGMViewState>(NoDeviceState)
Expand All @@ -33,6 +38,10 @@ internal class CGMViewModel @Inject constructor(

repository.data.onEach {
_state.value = WorkingState(it)

(it as? SuccessResult)?.let {
analytics.logEvent(ProfileConnectedEvent(Profile.CGMS))
}
}.launchIn(viewModelScope)
}

Expand Down
1 change: 1 addition & 0 deletions profile_csc/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ apply from: rootProject.file("library.gradle")
apply plugin: 'kotlin-parcelize'

dependencies {
implementation project(":lib_analytics")
implementation project(":lib_service")
implementation project(":lib_theme")
implementation project(":lib_utils")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,14 @@ import androidx.lifecycle.viewModelScope
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.flow.*
import kotlinx.coroutines.launch
import no.nordicsemi.android.analytics.AppAnalytics
import no.nordicsemi.android.analytics.Profile
import no.nordicsemi.android.analytics.ProfileConnectedEvent
import no.nordicsemi.android.csc.data.CSC_SERVICE_UUID
import no.nordicsemi.android.csc.repository.CSCRepository
import no.nordicsemi.android.csc.view.*
import no.nordicsemi.android.navigation.*
import no.nordicsemi.android.service.SuccessResult
import no.nordicsemi.android.utils.exhaustive
import no.nordicsemi.android.utils.getDevice
import no.nordicsemi.ui.scanner.ScannerDestinationId
Expand All @@ -17,7 +21,8 @@ import javax.inject.Inject
@HiltViewModel
internal class CSCViewModel @Inject constructor(
private val repository: CSCRepository,
private val navigationManager: NavigationManager
private val navigationManager: NavigationManager,
private val analytics: AppAnalytics
) : ViewModel() {

private val _state = MutableStateFlow(CSCViewState())
Expand All @@ -32,6 +37,10 @@ internal class CSCViewModel @Inject constructor(

repository.data.onEach {
_state.value = _state.value.copy(cscManagerState = WorkingState(it))

(it as? SuccessResult)?.let {
analytics.logEvent(ProfileConnectedEvent(Profile.CSC))
}
}.launchIn(viewModelScope)
}

Expand Down
1 change: 1 addition & 0 deletions profile_gls/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ android {
}

dependencies {
implementation project(":lib_analytics")
implementation project(":lib_service")
implementation project(":lib_theme")
implementation project(":lib_utils")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,15 @@ import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.flow.*
import no.nordicsemi.android.analytics.AppAnalytics
import no.nordicsemi.android.analytics.Profile
import no.nordicsemi.android.analytics.ProfileConnectedEvent
import no.nordicsemi.android.gls.GlsDetailsDestinationId
import no.nordicsemi.android.gls.repository.GLSRepository
import no.nordicsemi.android.gls.data.GLS_SERVICE_UUID
import no.nordicsemi.android.gls.main.view.*
import no.nordicsemi.android.navigation.*
import no.nordicsemi.android.service.SuccessResult
import no.nordicsemi.android.utils.exhaustive
import no.nordicsemi.android.utils.getDevice
import no.nordicsemi.ui.scanner.DiscoveredBluetoothDevice
Expand All @@ -18,7 +22,8 @@ import javax.inject.Inject
@HiltViewModel
internal class GLSViewModel @Inject constructor(
private val repository: GLSRepository,
private val navigationManager: NavigationManager
private val navigationManager: NavigationManager,
private val analytics: AppAnalytics
) : ViewModel() {

private val _state = MutableStateFlow<GLSViewState>(NoDeviceState)
Expand Down Expand Up @@ -54,6 +59,10 @@ internal class GLSViewModel @Inject constructor(
private fun connectDevice(device: DiscoveredBluetoothDevice) {
repository.downloadData(device).onEach {
_state.value = WorkingState(it)

(it as? SuccessResult)?.let {
analytics.logEvent(ProfileConnectedEvent(Profile.GLS))
}
}.launchIn(viewModelScope)
}
}
1 change: 1 addition & 0 deletions profile_hrs/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ android {
}

dependencies {
implementation project(":lib_analytics")
implementation project(":lib_service")
implementation project(":lib_theme")
implementation project(":lib_utils")
Expand Down
Loading