mirror of
https://github.com/element-hq/element-android
synced 2024-11-28 13:38:49 +03:00
Analytics: Framework to send screen event
This commit is contained in:
parent
a8c29f55f5
commit
0a08a50e11
7 changed files with 121 additions and 18 deletions
|
@ -21,7 +21,7 @@ import dagger.hilt.InstallIn
|
|||
import dagger.hilt.components.SingletonComponent
|
||||
import im.vector.app.core.dialogs.UnrecognizedCertificateDialog
|
||||
import im.vector.app.core.error.ErrorFormatter
|
||||
import im.vector.app.features.analytics.VectorAnalytics
|
||||
import im.vector.app.features.analytics.AnalyticsTracker
|
||||
import im.vector.app.features.call.webrtc.WebRtcCallManager
|
||||
import im.vector.app.features.home.AvatarRenderer
|
||||
import im.vector.app.features.navigation.Navigator
|
||||
|
@ -56,7 +56,7 @@ interface SingletonEntryPoint {
|
|||
|
||||
fun pinLocker(): PinLocker
|
||||
|
||||
fun analytics(): VectorAnalytics
|
||||
fun analyticsTracker(): AnalyticsTracker
|
||||
|
||||
fun webRtcCallManager(): WebRtcCallManager
|
||||
|
||||
|
|
|
@ -65,7 +65,9 @@ import im.vector.app.core.extensions.toMvRxBundle
|
|||
import im.vector.app.core.utils.toast
|
||||
import im.vector.app.features.MainActivity
|
||||
import im.vector.app.features.MainActivityArgs
|
||||
import im.vector.app.features.analytics.VectorAnalytics
|
||||
import im.vector.app.features.analytics.AnalyticsTracker
|
||||
import im.vector.app.features.analytics.plan.Screen
|
||||
import im.vector.app.features.analytics.screen.ScreenEvent
|
||||
import im.vector.app.features.configuration.VectorConfiguration
|
||||
import im.vector.app.features.consent.ConsentNotGivenHelper
|
||||
import im.vector.app.features.navigation.Navigator
|
||||
|
@ -90,6 +92,15 @@ import timber.log.Timber
|
|||
import javax.inject.Inject
|
||||
|
||||
abstract class VectorBaseActivity<VB : ViewBinding> : AppCompatActivity(), MavericksView {
|
||||
/* ==========================================================================================
|
||||
* Analytics
|
||||
* ========================================================================================== */
|
||||
|
||||
protected var analyticsScreenName: Screen.ScreenName? = null
|
||||
private var screenEvent: ScreenEvent? = null
|
||||
|
||||
protected lateinit var analyticsTracker: AnalyticsTracker
|
||||
|
||||
/* ==========================================================================================
|
||||
* View
|
||||
* ========================================================================================== */
|
||||
|
@ -133,7 +144,6 @@ abstract class VectorBaseActivity<VB : ViewBinding> : AppCompatActivity(), Maver
|
|||
private lateinit var sessionListener: SessionListener
|
||||
protected lateinit var bugReporter: BugReporter
|
||||
private lateinit var pinLocker: PinLocker
|
||||
protected lateinit var analytics: VectorAnalytics
|
||||
|
||||
@Inject
|
||||
lateinit var rageShake: RageShake
|
||||
|
@ -189,7 +199,7 @@ abstract class VectorBaseActivity<VB : ViewBinding> : AppCompatActivity(), Maver
|
|||
configurationViewModel = viewModelProvider.get(ConfigurationViewModel::class.java)
|
||||
bugReporter = singletonEntryPoint.bugReporter()
|
||||
pinLocker = singletonEntryPoint.pinLocker()
|
||||
analytics = singletonEntryPoint.analytics()
|
||||
analyticsTracker = singletonEntryPoint.analyticsTracker()
|
||||
navigator = singletonEntryPoint.navigator()
|
||||
activeSessionHolder = singletonEntryPoint.activeSessionHolder()
|
||||
vectorPreferences = singletonEntryPoint.vectorPreferences()
|
||||
|
@ -324,7 +334,7 @@ abstract class VectorBaseActivity<VB : ViewBinding> : AppCompatActivity(), Maver
|
|||
override fun onResume() {
|
||||
super.onResume()
|
||||
Timber.i("onResume Activity ${javaClass.simpleName}")
|
||||
|
||||
screenEvent = analyticsScreenName?.let { ScreenEvent(it) }
|
||||
configurationViewModel.onActivityResumed()
|
||||
|
||||
if (this !is BugReportActivity && vectorPreferences.useRageshake()) {
|
||||
|
@ -363,6 +373,7 @@ abstract class VectorBaseActivity<VB : ViewBinding> : AppCompatActivity(), Maver
|
|||
|
||||
override fun onPause() {
|
||||
super.onPause()
|
||||
screenEvent?.send(analyticsTracker)
|
||||
Timber.i("onPause Activity ${javaClass.simpleName}")
|
||||
|
||||
rageShake.stop()
|
||||
|
|
|
@ -37,7 +37,9 @@ import im.vector.app.core.di.ActivityEntryPoint
|
|||
import im.vector.app.core.extensions.singletonEntryPoint
|
||||
import im.vector.app.core.extensions.toMvRxBundle
|
||||
import im.vector.app.core.utils.DimensionConverter
|
||||
import im.vector.app.features.analytics.VectorAnalytics
|
||||
import im.vector.app.features.analytics.AnalyticsTracker
|
||||
import im.vector.app.features.analytics.plan.Screen
|
||||
import im.vector.app.features.analytics.screen.ScreenEvent
|
||||
import kotlinx.coroutines.flow.launchIn
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import reactivecircus.flowbinding.android.view.clicks
|
||||
|
@ -47,6 +49,14 @@ import timber.log.Timber
|
|||
* Add Mavericks capabilities, handle DI and bindings.
|
||||
*/
|
||||
abstract class VectorBaseBottomSheetDialogFragment<VB : ViewBinding> : BottomSheetDialogFragment(), MavericksView {
|
||||
/* ==========================================================================================
|
||||
* Analytics
|
||||
* ========================================================================================== */
|
||||
|
||||
protected var analyticsScreenName: Screen.ScreenName? = null
|
||||
private var screenEvent: ScreenEvent? = null
|
||||
|
||||
protected lateinit var analyticsTracker: AnalyticsTracker
|
||||
|
||||
/* ==========================================================================================
|
||||
* View
|
||||
|
@ -84,8 +94,6 @@ abstract class VectorBaseBottomSheetDialogFragment<VB : ViewBinding> : BottomShe
|
|||
|
||||
open val showExpanded = false
|
||||
|
||||
protected lateinit var analytics: VectorAnalytics
|
||||
|
||||
interface ResultListener {
|
||||
fun onBottomSheetResult(resultCode: Int, data: Any?)
|
||||
|
||||
|
@ -124,13 +132,19 @@ abstract class VectorBaseBottomSheetDialogFragment<VB : ViewBinding> : BottomShe
|
|||
val activityEntryPoint = EntryPointAccessors.fromActivity(vectorBaseActivity, ActivityEntryPoint::class.java)
|
||||
viewModelFactory = activityEntryPoint.viewModelFactory()
|
||||
val singletonEntryPoint = context.singletonEntryPoint()
|
||||
analytics = singletonEntryPoint.analytics()
|
||||
analyticsTracker = singletonEntryPoint.analyticsTracker()
|
||||
super.onAttach(context)
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
Timber.i("onResume BottomSheet ${javaClass.simpleName}")
|
||||
screenEvent = analyticsScreenName?.let { ScreenEvent(it) }
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
super.onPause()
|
||||
screenEvent?.send(analyticsTracker)
|
||||
}
|
||||
|
||||
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
|
||||
|
|
|
@ -42,7 +42,9 @@ import im.vector.app.core.dialogs.UnrecognizedCertificateDialog
|
|||
import im.vector.app.core.error.ErrorFormatter
|
||||
import im.vector.app.core.extensions.singletonEntryPoint
|
||||
import im.vector.app.core.extensions.toMvRxBundle
|
||||
import im.vector.app.features.analytics.VectorAnalytics
|
||||
import im.vector.app.features.analytics.AnalyticsTracker
|
||||
import im.vector.app.features.analytics.plan.Screen
|
||||
import im.vector.app.features.analytics.screen.ScreenEvent
|
||||
import im.vector.app.features.navigation.Navigator
|
||||
import im.vector.lib.ui.styles.dialogs.MaterialProgressDialog
|
||||
import kotlinx.coroutines.flow.launchIn
|
||||
|
@ -51,6 +53,18 @@ import reactivecircus.flowbinding.android.view.clicks
|
|||
import timber.log.Timber
|
||||
|
||||
abstract class VectorBaseFragment<VB : ViewBinding> : Fragment(), MavericksView {
|
||||
/* ==========================================================================================
|
||||
* Analytics
|
||||
* ========================================================================================== */
|
||||
|
||||
protected var analyticsScreenName: Screen.ScreenName? = null
|
||||
private var screenEvent: ScreenEvent? = null
|
||||
|
||||
protected lateinit var analyticsTracker: AnalyticsTracker
|
||||
|
||||
/* ==========================================================================================
|
||||
* Activity
|
||||
* ========================================================================================== */
|
||||
|
||||
protected val vectorBaseActivity: VectorBaseActivity<*> by lazy {
|
||||
activity as VectorBaseActivity<*>
|
||||
|
@ -61,7 +75,6 @@ abstract class VectorBaseFragment<VB : ViewBinding> : Fragment(), MavericksView
|
|||
* ========================================================================================== */
|
||||
|
||||
protected lateinit var navigator: Navigator
|
||||
protected lateinit var analytics: VectorAnalytics
|
||||
protected lateinit var errorFormatter: ErrorFormatter
|
||||
protected lateinit var unrecognizedCertificateDialog: UnrecognizedCertificateDialog
|
||||
|
||||
|
@ -98,7 +111,7 @@ abstract class VectorBaseFragment<VB : ViewBinding> : Fragment(), MavericksView
|
|||
val activityEntryPoint = EntryPointAccessors.fromActivity(vectorBaseActivity, ActivityEntryPoint::class.java)
|
||||
navigator = singletonEntryPoint.navigator()
|
||||
errorFormatter = singletonEntryPoint.errorFormatter()
|
||||
analytics = singletonEntryPoint.analytics()
|
||||
analyticsTracker = singletonEntryPoint.analyticsTracker()
|
||||
unrecognizedCertificateDialog = singletonEntryPoint.unrecognizedCertificateDialog()
|
||||
viewModelFactory = activityEntryPoint.viewModelFactory()
|
||||
childFragmentManager.fragmentFactory = activityEntryPoint.fragmentFactory()
|
||||
|
@ -125,12 +138,14 @@ abstract class VectorBaseFragment<VB : ViewBinding> : Fragment(), MavericksView
|
|||
override fun onResume() {
|
||||
super.onResume()
|
||||
Timber.i("onResume Fragment ${javaClass.simpleName}")
|
||||
screenEvent = analyticsScreenName?.let { ScreenEvent(it) }
|
||||
}
|
||||
|
||||
@CallSuper
|
||||
override fun onPause() {
|
||||
super.onPause()
|
||||
Timber.i("onPause Fragment ${javaClass.simpleName}")
|
||||
screenEvent?.send(analyticsTracker)
|
||||
}
|
||||
|
||||
@CallSuper
|
||||
|
|
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* Copyright (c) 2021 New Vector Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package im.vector.app.features.analytics.screen
|
||||
|
||||
import android.os.SystemClock
|
||||
import im.vector.app.features.analytics.AnalyticsTracker
|
||||
import im.vector.app.features.analytics.plan.Screen
|
||||
import timber.log.Timber
|
||||
|
||||
/**
|
||||
* Track a screen display. Unique usage.
|
||||
*/
|
||||
class ScreenEvent(val screenName: Screen.ScreenName) {
|
||||
private val startTime = SystemClock.elapsedRealtime()
|
||||
|
||||
// Protection to avoid multiple sending
|
||||
private var isSent = false
|
||||
|
||||
fun send(analyticsTracker: AnalyticsTracker) {
|
||||
if (isSent) {
|
||||
Timber.w("Event $screenName Already sent!")
|
||||
return
|
||||
}
|
||||
isSent = true
|
||||
analyticsTracker.screen(
|
||||
Screen(
|
||||
screenName = screenName,
|
||||
durationMs = (SystemClock.elapsedRealtime() - startTime).toInt()
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
|
@ -116,7 +116,6 @@ import im.vector.app.core.utils.startInstallFromSourceIntent
|
|||
import im.vector.app.core.utils.toast
|
||||
import im.vector.app.databinding.DialogReportContentBinding
|
||||
import im.vector.app.databinding.FragmentRoomDetailBinding
|
||||
import im.vector.app.features.analytics.AnalyticsTracker
|
||||
import im.vector.app.features.analytics.plan.Click
|
||||
import im.vector.app.features.attachments.AttachmentTypeSelectorView
|
||||
import im.vector.app.features.attachments.AttachmentsHelper
|
||||
|
@ -259,7 +258,6 @@ class RoomDetailFragment @Inject constructor(
|
|||
private val roomDetailPendingActionStore: RoomDetailPendingActionStore,
|
||||
private val pillsPostProcessorFactory: PillsPostProcessor.Factory,
|
||||
private val callManager: WebRtcCallManager,
|
||||
private val analyticsTracker: AnalyticsTracker,
|
||||
private val voiceMessagePlaybackTracker: VoiceMessagePlaybackTracker,
|
||||
private val clock: Clock
|
||||
) :
|
||||
|
|
|
@ -29,7 +29,9 @@ import im.vector.app.core.error.ErrorFormatter
|
|||
import im.vector.app.core.extensions.singletonEntryPoint
|
||||
import im.vector.app.core.platform.VectorBaseActivity
|
||||
import im.vector.app.core.utils.toast
|
||||
import im.vector.app.features.analytics.VectorAnalytics
|
||||
import im.vector.app.features.analytics.AnalyticsTracker
|
||||
import im.vector.app.features.analytics.plan.Screen
|
||||
import im.vector.app.features.analytics.screen.ScreenEvent
|
||||
import kotlinx.coroutines.flow.launchIn
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import org.matrix.android.sdk.api.session.Session
|
||||
|
@ -37,6 +39,18 @@ import reactivecircus.flowbinding.android.view.clicks
|
|||
import timber.log.Timber
|
||||
|
||||
abstract class VectorSettingsBaseFragment : PreferenceFragmentCompat(), MavericksView {
|
||||
/* ==========================================================================================
|
||||
* Analytics
|
||||
* ========================================================================================== */
|
||||
|
||||
protected var analyticsScreenName: Screen.ScreenName? = null
|
||||
private var screenEvent: ScreenEvent? = null
|
||||
|
||||
protected lateinit var analyticsTracker: AnalyticsTracker
|
||||
|
||||
/* ==========================================================================================
|
||||
* Activity
|
||||
* ========================================================================================== */
|
||||
|
||||
val vectorActivity: VectorBaseActivity<*> by lazy {
|
||||
activity as VectorBaseActivity<*>
|
||||
|
@ -47,7 +61,6 @@ abstract class VectorSettingsBaseFragment : PreferenceFragmentCompat(), Maverick
|
|||
// members
|
||||
protected lateinit var session: Session
|
||||
protected lateinit var errorFormatter: ErrorFormatter
|
||||
protected lateinit var analytics: VectorAnalytics
|
||||
|
||||
/* ==========================================================================================
|
||||
* Views
|
||||
|
@ -72,17 +85,23 @@ abstract class VectorSettingsBaseFragment : PreferenceFragmentCompat(), Maverick
|
|||
super.onAttach(context)
|
||||
session = singletonEntryPoint.activeSessionHolder().getActiveSession()
|
||||
errorFormatter = singletonEntryPoint.errorFormatter()
|
||||
analytics = singletonEntryPoint.analytics()
|
||||
analyticsTracker = singletonEntryPoint.analyticsTracker()
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
Timber.i("onResume Fragment ${javaClass.simpleName}")
|
||||
screenEvent = analyticsScreenName?.let { ScreenEvent(it) }
|
||||
vectorActivity.supportActionBar?.setTitle(titleRes)
|
||||
// find the view from parent activity
|
||||
mLoadingView = vectorActivity.findViewById(R.id.vector_settings_spinner_views)
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
super.onPause()
|
||||
screenEvent?.send(analyticsTracker)
|
||||
}
|
||||
|
||||
abstract fun bindPref()
|
||||
|
||||
abstract var titleRes: Int
|
||||
|
|
Loading…
Reference in a new issue