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

Clean up analytical metrics collection #1145

Merged
merged 3 commits into from
Oct 1, 2023
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
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ import com.github.ashutoshgngwr.noice.billing.DonationFlowProvider
import com.github.ashutoshgngwr.noice.billing.SubscriptionBillingProvider
import com.github.ashutoshgngwr.noice.di.DonationFlowProviderModule
import com.github.ashutoshgngwr.noice.di.SubscriptionBillingProviderModule
import com.github.ashutoshgngwr.noice.fragment.SubscriptionPurchaseListFragment
import com.github.ashutoshgngwr.noice.fragment.SubscriptionPurchasesFragment
import com.github.ashutoshgngwr.noice.models.AudioQuality
import com.github.ashutoshgngwr.noice.models.Preset
import com.github.ashutoshgngwr.noice.repository.PresetRepository
Expand Down Expand Up @@ -188,11 +188,11 @@ class MainActivityTest {
fun subscriptionPurchaseListIntent() {
Intent(ApplicationProvider.getApplicationContext(), MainActivity::class.java)
.setAction(Intent.ACTION_VIEW)
.setData(Uri.parse(SubscriptionPurchaseListFragment.URI))
.setData(Uri.parse(SubscriptionPurchasesFragment.URI))
.let { launch<MainActivity>(it) }
.onActivity { activity ->
val navController = activity.findNavController(R.id.main_nav_host_fragment)
assertEquals(R.id.subscription_purchase_list, navController.currentDestination?.id)
assertEquals(R.id.subscription_purchases, navController.currentDestination?.id)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import com.github.ashutoshgngwr.noice.AppDispatchers
import com.github.ashutoshgngwr.noice.databinding.GooglePlayDonationPurchaseCompleteFragmentBinding
import com.github.ashutoshgngwr.noice.ext.launchAndRepeatOnStarted
import com.github.ashutoshgngwr.noice.metrics.AnalyticsProvider
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
import dagger.hilt.android.AndroidEntryPoint
import dagger.hilt.android.lifecycle.HiltViewModel
Expand All @@ -23,6 +24,9 @@
@AndroidEntryPoint
class GooglePlayDonationPurchaseCompleteFragment : BottomSheetDialogFragment() {

@set:Inject
internal var analyticsProvider: AnalyticsProvider? = null

Check warning on line 28 in app/src/full/java/com/github/ashutoshgngwr/noice/billing/GooglePlayDonationPurchaseCompleteFragment.kt

View check run for this annotation

Codecov / codecov/patch

app/src/full/java/com/github/ashutoshgngwr/noice/billing/GooglePlayDonationPurchaseCompleteFragment.kt#L28

Added line #L28 was not covered by tests

private lateinit var binding: GooglePlayDonationPurchaseCompleteFragmentBinding
private val viewModel: GooglePlayDonationPurchaseCompleteViewModel by viewModels()

Expand All @@ -42,6 +46,7 @@
val purchaseInfoJson = requireNotNull(arguments?.getString(PURCHASE_INFO_JSON))
val purchaseSignature = requireNotNull(arguments?.getString(PURCHASE_SIGNATURE))
viewModel.consumePurchase(Purchase(purchaseInfoJson, purchaseSignature))
analyticsProvider?.setCurrentScreen(this::class)
}

companion object {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,17 @@
import android.view.View
import android.view.ViewGroup
import com.github.ashutoshgngwr.noice.databinding.GooglePlayDonationPurchasePendingFragmentBinding
import com.github.ashutoshgngwr.noice.metrics.AnalyticsProvider
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
import dagger.hilt.android.AndroidEntryPoint
import javax.inject.Inject

@AndroidEntryPoint
class GooglePlayDonationPurchasePendingFragment : BottomSheetDialogFragment() {

@set:Inject
internal var analyticsProvider: AnalyticsProvider? = null

Check warning on line 17 in app/src/full/java/com/github/ashutoshgngwr/noice/billing/GooglePlayDonationPurchasePendingFragment.kt

View check run for this annotation

Codecov / codecov/patch

app/src/full/java/com/github/ashutoshgngwr/noice/billing/GooglePlayDonationPurchasePendingFragment.kt#L17

Added line #L17 was not covered by tests

private lateinit var binding: GooglePlayDonationPurchasePendingFragmentBinding

override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, state: Bundle?): View {
Expand All @@ -18,5 +25,6 @@

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
binding.okay.setOnClickListener { dismiss() }
analyticsProvider?.setCurrentScreen(this::class)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package com.github.ashutoshgngwr.noice.metrics

import android.os.Bundle
import androidx.core.os.bundleOf
import com.github.ashutoshgngwr.noice.BuildConfig
import com.google.firebase.analytics.FirebaseAnalytics
import com.google.firebase.analytics.ktx.analytics
import com.google.firebase.analytics.ktx.setConsent
Expand All @@ -14,70 +15,35 @@ import kotlin.reflect.KClass
class FirebaseAnalyticsProvider : AnalyticsProvider {

private val fa = Firebase.analytics
private val playerStartTimes = mutableMapOf<String, Long>()

private var playbackStartTime = -1L
private var castSessionStartTime = -1L

init {
fa.setConsent {
adStorage = FirebaseAnalytics.ConsentStatus.DENIED
analyticsStorage = FirebaseAnalytics.ConsentStatus.GRANTED
}

fa.setDefaultEventParameters(
bundleOf("app_version_code" to BuildConfig.VERSION_CODE)
)
}

override fun setCollectionEnabled(e: Boolean) {
fa.setAnalyticsCollectionEnabled(e)
}

override fun setCurrentScreen(name: String, clazz: KClass<out Any>, params: Bundle) {
params.putString(FirebaseAnalytics.Param.SCREEN_NAME, name)
clazz.simpleName?.also {
params.putString(FirebaseAnalytics.Param.SCREEN_CLASS, it)
}

fa.logEvent(FirebaseAnalytics.Event.SCREEN_VIEW, params)
}


override fun logEvent(name: String, params: Bundle) {
fa.logEvent(name, params)
}

override fun logPlayerStartEvent(key: String) {
if (key !in playerStartTimes) {
playerStartTimes[key] = System.currentTimeMillis()
}

if (playbackStartTime <= 0) {
playbackStartTime = System.currentTimeMillis()
}
}

override fun logPlayerStopEvent(key: String) {
playerStartTimes.remove(key)?.also {
val params = bundleOf("sound_key" to key, "duration_ms" to System.currentTimeMillis() - it)
fa.logEvent("sound_session", params)
}

if (playerStartTimes.isEmpty() && playbackStartTime > 0) {
val duration = System.currentTimeMillis() - playbackStartTime
fa.logEvent("playback_session", bundleOf("duration_ms" to duration))
playbackStartTime = -1L
}
}

override fun logCastSessionStartEvent() {
castSessionStartTime = System.currentTimeMillis()
}

override fun logCastSessionEndEvent() {
if (castSessionStartTime <= 0) {
return
override fun setCurrentScreen(clazz: KClass<out Any>) {
clazz.simpleName?.also { className ->
val screenName = className.removeSuffix("Activity").removeSuffix("Fragment")
fa.logEvent(
FirebaseAnalytics.Event.SCREEN_VIEW, bundleOf(
FirebaseAnalytics.Param.SCREEN_NAME to screenName,
FirebaseAnalytics.Param.SCREEN_CLASS to clazz.simpleName,
)
)
}

val params = bundleOf("duration_ms" to System.currentTimeMillis() - castSessionStartTime)
fa.logEvent("cast_session", params)
castSessionStartTime = -1
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import androidx.core.view.WindowInsetsCompat
import androidx.core.view.WindowInsetsControllerCompat
import androidx.core.view.isVisible
import com.github.ashutoshgngwr.noice.databinding.AlarmRingerActivityBinding
import com.github.ashutoshgngwr.noice.metrics.AnalyticsProvider
import com.github.ashutoshgngwr.noice.repository.SettingsRepository
import dagger.hilt.EntryPoint
import dagger.hilt.InstallIn
Expand All @@ -32,6 +33,9 @@ class AlarmRingerActivity : AppCompatActivity() {
@set:Inject
internal lateinit var serviceController: ServiceController

@set:Inject
internal var analyticsProvider: AnalyticsProvider? = null

private val settingsRepository by lazy {
EntryPointAccessors.fromApplication(application, AlarmRingerActivityEntryPoint::class.java)
.settingsRepository()
Expand Down Expand Up @@ -61,6 +65,7 @@ class AlarmRingerActivity : AppCompatActivity() {
setContentView(binding.root)
showWhenLocked()
onBackPressedDispatcher.addCallback(this) { } // no-op
analyticsProvider?.setCurrentScreen(this::class)
}

override fun onStart() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import android.os.Bundle
import androidx.annotation.VisibleForTesting
import androidx.core.app.ActivityCompat
import androidx.core.content.edit
import androidx.core.os.bundleOf
import androidx.fragment.app.Fragment
import androidx.preference.PreferenceManager
import com.github.appintro.AppIntro
Expand Down Expand Up @@ -114,23 +113,22 @@ class AppIntroActivity : AppIntro() {
)
)

analyticsProvider?.setCurrentScreen("app_intro", AppIntroActivity::class)
analyticsProvider?.setCurrentScreen(this::class)
}

override fun onSkipPressed(currentFragment: Fragment?) {
markSeenInPrefsAndFinish(true)
markSeenInPrefsAndFinish()
}

override fun onDonePressed(currentFragment: Fragment?) {
markSeenInPrefsAndFinish(false)
markSeenInPrefsAndFinish()
}

private fun markSeenInPrefsAndFinish(isSkipped: Boolean) {
private fun markSeenInPrefsAndFinish() {
PreferenceManager.getDefaultSharedPreferences(this).edit {
putBoolean(PREF_HAS_USER_SEEN_APP_INTRO, true)
}

finish()
analyticsProvider?.logEvent("app_intro_complete", bundleOf("success" to !isSkipped))
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import androidx.annotation.VisibleForTesting
import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.app.AppCompatDelegate
import androidx.core.content.edit
import androidx.core.os.bundleOf
import androidx.core.os.postDelayed
import androidx.core.view.isVisible
import androidx.core.widget.TextViewCompat
Expand All @@ -29,9 +28,8 @@ import com.github.ashutoshgngwr.noice.ext.getInternetConnectivityFlow
import com.github.ashutoshgngwr.noice.ext.launchAndRepeatOnStarted
import com.github.ashutoshgngwr.noice.fragment.DialogFragment
import com.github.ashutoshgngwr.noice.fragment.HomeFragmentArgs
import com.github.ashutoshgngwr.noice.fragment.SubscriptionPurchaseListFragment
import com.github.ashutoshgngwr.noice.fragment.SubscriptionPurchasedFragmentArgs
import com.github.ashutoshgngwr.noice.metrics.AnalyticsProvider
import com.github.ashutoshgngwr.noice.fragment.SubscriptionPurchasesFragment
import com.github.ashutoshgngwr.noice.metrics.ReviewFlowProvider
import com.github.ashutoshgngwr.noice.repository.PresetRepository
import com.github.ashutoshgngwr.noice.repository.SettingsRepository
Expand Down Expand Up @@ -84,9 +82,6 @@ class MainActivity : AppCompatActivity(), SubscriptionBillingProvider.Listener {
@set:Inject
internal lateinit var reviewFlowProvider: ReviewFlowProvider

@set:Inject
internal var analyticsProvider: AnalyticsProvider? = null

/**
* indicates whether the activity was delivered a new intent since it was last resumed.
*/
Expand Down Expand Up @@ -119,7 +114,6 @@ class MainActivity : AppCompatActivity(), SubscriptionBillingProvider.Listener {

SoundDownloadsRefreshWorker.refreshDownloads(this)
reviewFlowProvider.init(this)
analyticsProvider?.logEvent("ui_open", bundleOf("theme" to settingsRepository.getAppTheme()))
hasNewIntent = true
initOfflineIndicator()
donationFlowProvider.setCallbackFragmentHost(this)
Expand Down Expand Up @@ -235,8 +229,8 @@ class MainActivity : AppCompatActivity(), SubscriptionBillingProvider.Listener {
}
}

Intent.ACTION_VIEW == intent.action && SubscriptionPurchaseListFragment.URI == dataString -> {
navController.navigate(R.id.subscription_purchase_list)
Intent.ACTION_VIEW == intent.action && SubscriptionPurchasesFragment.URI == dataString -> {
navController.navigate(R.id.subscription_purchases)
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import androidx.appcompat.app.AppCompatActivity
import androidx.core.os.bundleOf
import androidx.lifecycle.lifecycleScope
import com.github.ashutoshgngwr.noice.R
import com.github.ashutoshgngwr.noice.metrics.AnalyticsProvider
import com.github.ashutoshgngwr.noice.repository.PresetRepository
import com.github.ashutoshgngwr.noice.service.SoundPlaybackService
import dagger.hilt.android.AndroidEntryPoint
Expand All @@ -28,9 +27,6 @@ class PresetShortcutHandlerActivity : AppCompatActivity() {
const val EXTRA_SHORTCUT_TYPE = "shortcut_type"
}

@set:Inject
internal var analyticsProvider: AnalyticsProvider? = null

@set:Inject
internal lateinit var presetRepository: PresetRepository

Expand Down Expand Up @@ -69,7 +65,6 @@ class PresetShortcutHandlerActivity : AppCompatActivity() {
}

finish()
analyticsProvider?.logEvent("preset_shortcut_open", params)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import androidx.lifecycle.viewModelScope
import com.github.ashutoshgngwr.noice.R
import com.github.ashutoshgngwr.noice.databinding.SignInLinkHandlerFragmentBinding
import com.github.ashutoshgngwr.noice.metrics.AnalyticsProvider
import com.github.ashutoshgngwr.noice.repository.AccountRepository
import com.github.ashutoshgngwr.noice.repository.Resource
import com.github.ashutoshgngwr.noice.repository.errors.NetworkError
Expand Down Expand Up @@ -49,6 +50,9 @@
@AndroidEntryPoint
class SignInLinkHandlerFragment : BottomSheetDialogFragment() {

@set:Inject
internal var analyticsProvider: AnalyticsProvider? = null

Check warning on line 54 in app/src/main/java/com/github/ashutoshgngwr/noice/activity/SignInLinkHandlerActivity.kt

View check run for this annotation

Codecov / codecov/patch

app/src/main/java/com/github/ashutoshgngwr/noice/activity/SignInLinkHandlerActivity.kt#L54

Added line #L54 was not covered by tests

private lateinit var binding: SignInLinkHandlerFragmentBinding
private val viewModel: SignInLinkHandlerViewModel by viewModels()

Expand Down Expand Up @@ -76,6 +80,7 @@
}

viewModel.signInWithToken(signInToken)
analyticsProvider?.setCurrentScreen(this::class)
}

companion object {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,7 @@ class AboutFragment : Fragment(), LibsConfiguration.LibsListener {
}

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
analyticsProvider?.setCurrentScreen("about", AboutFragment::class)
analyticsProvider?.setCurrentScreen(this::class)
}

private fun buildElement(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.annotation.StringRes
import androidx.core.os.bundleOf
import androidx.fragment.app.Fragment
import androidx.fragment.app.viewModels
import androidx.lifecycle.ViewModel
Expand Down Expand Up @@ -99,8 +98,6 @@ class AccountFragment : Fragment() {
)
.toString()
.also { item.context.startCustomTab(it) }

analyticsProvider?.logEvent("issue_tracker_open", bundleOf())
}

R.id.submit_feedback -> {
Expand All @@ -112,8 +109,6 @@ class AccountFragment : Fragment() {
}
.toString()
.also { item.context.startCustomTab(it) }

analyticsProvider?.logEvent("feedback_form_open", bundleOf())
}

R.id.privacy_policy -> item.context.startCustomTab(R.string.app_privacy_policy_url)
Expand Down Expand Up @@ -142,6 +137,7 @@ class AccountFragment : Fragment() {
}

viewModel.loadData()
analyticsProvider?.setCurrentScreen(this::class)
}

private fun launchActivityForUrl(@StringRes resId: Int) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import com.github.ashutoshgngwr.noice.ext.launchAndRepeatOnStarted
import com.github.ashutoshgngwr.noice.ext.showErrorSnackBar
import com.github.ashutoshgngwr.noice.ext.showTimePicker
import com.github.ashutoshgngwr.noice.ext.startAppDetailsSettingsActivity
import com.github.ashutoshgngwr.noice.metrics.AnalyticsProvider
import com.github.ashutoshgngwr.noice.models.Alarm
import com.github.ashutoshgngwr.noice.models.Preset
import com.github.ashutoshgngwr.noice.repository.AlarmRepository
Expand All @@ -59,6 +60,9 @@ private const val FREE_ALARM_COUNT = 2
@AndroidEntryPoint
class AlarmsFragment : Fragment(), AlarmViewHolder.ViewController {

@set:Inject
internal var analyticsProvider: AnalyticsProvider? = null

private lateinit var binding: AlarmsFragmentBinding

private val viewModel: AlarmsViewModel by viewModels()
Expand Down Expand Up @@ -109,6 +113,8 @@ class AlarmsFragment : Fragment(), AlarmViewHolder.ViewController {
.filter { it > 0 }
.collect { showErrorSnackBar(R.string.alarms_disabled_due_to_subscription_expiration) }
}

analyticsProvider?.setCurrentScreen(this::class)
}

private fun startAddAlarmFlow() {
Expand Down
Loading
Loading