-
Notifications
You must be signed in to change notification settings - Fork 625
Implement SessionInitiator and hook it up to lifecycle events #4723
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
Conversation
Generated by 🚫 Danger |
Size Report 1Affected Products
Test Logs |
firebase-sessions/src/main/kotlin/com/google/firebase/sessions/FirebaseSessions.kt
Show resolved
Hide resolved
val sessionInitiator = SessionInitiator(System::currentTimeMillis, this::initiateSessionStart) | ||
val context = firebaseApp.applicationContext.applicationContext | ||
if (context is Application) { | ||
context.registerActivityLifecycleCallbacks(sessionInitiator.activityLifecycleCallbacks) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Suggestion: Make this part of the constructor for SessionInitiator instead of exposing the activityLifecycleCallbacks
property
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I did it this way so the SessionInitiator outer class wouldn't have any Context or Activity in the ctor to make the tests simpler.
private const val SMALL_INTERVAL_MS = 3 * 1000L // not enough time to initiate a new session | ||
private const val LARGE_INTERVAL_MS = 90 * 60 * 1000L // enough to initiate another session | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These tests are great 👍
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Couple suggestions, but otherwise looks good!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for making these changes. Since these are merged now - we can make these changes (if any) in a separate PR.
val sessionInitiator = SessionInitiator(System::currentTimeMillis, this::initiateSessionStart) | ||
val context = firebaseApp.applicationContext.applicationContext | ||
if (context is Application) { | ||
context.registerActivityLifecycleCallbacks(sessionInitiator.activityLifecycleCallbacks) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we check if the context is already registered for lifecycle callbacks? This is to ensure that we are not registering multiple times.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sam suggested moving this to the SessionInitiator ctor. If we do that, then that instance can only get registered once. Would that be enough to ensure this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It depends on if the SessionInitator constructor will be called just once or more than once. Also, would the loss of a SessionInitiator object cause a deRegister to be called automatically? If so, this refactor should be fine.
firebase-sessions/src/main/kotlin/com/google/firebase/sessions/FirebaseSessions.kt
Show resolved
Hide resolved
.factory { FirebaseSessions() } | ||
.add(Dependency.required(FirebaseApp::class.java)) | ||
.factory { container -> FirebaseSessions(container.get(FirebaseApp::class.java)) } | ||
.eagerInDefaultApp() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why eager initialization? Should we go with lazy? Thoughts @davidmotson
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I set eager because I want the first session to start at app launch. Would lazy still be good enough for that?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think lazy should be fine. With eager my concern is that we might impact the startup time of the application. Especially since we would be dependent on libraries like Installations and Firelog.
The only caveat here would be the start time of a session. I think the start time of a session and the application start time are different from each other. So, I think lazy should be fine.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If I make it lazy, it never initiates on my test app if I never access the SDK. Are we sure that's what we want? When Crashlytics and Fireperf depend on it, will they always access it on every launch?
firebase-sessions/src/main/kotlin/com/google/firebase/sessions/SessionInitiator.kt
Show resolved
Hide resolved
firebase-sessions/src/main/kotlin/com/google/firebase/sessions/SessionInitiator.kt
Show resolved
Hide resolved
firebase-sessions/src/main/kotlin/com/google/firebase/sessions/SessionInitiator.kt
Show resolved
Hide resolved
|
||
override fun onActivityPaused(activity: Activity) = appBackgrounded() | ||
|
||
override fun onActivityCreated(activity: Activity, savedInstanceState: Bundle?) = Unit |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Curious if this will be the place to kick start a session event?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you mean onActivityCreated? We call initiateSessionStart() when the class is constructed for the cold boot case.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, that was my question. I get that part now. Will the code to start a new session be called in a later PR?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The init { ... }
block gets called as part of the ctor, and that calls initiateSessionStart()
already. So we start a new session when this object is constructed, representing the cold boot. And we also call it on foreground after the session timeout elapsed.
Implement SessionInitiator and hook it up to lifecycle events.
This is responsible for calling the initiateSessionStart callback whenever a session starts.
Used Longs for time, not go/goodtime, to keep the SDK light on older android api levels. Put the unit on every time variable.
Added unit tests. Used fakes, not mocks or stubs frameworks, similar to the iOS SDK.