-
Notifications
You must be signed in to change notification settings - Fork 213
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
Add Application Open and Application Backgrounded Events #620
Add Application Open and Application Backgrounded Events #620
Conversation
Codecov Report
@@ Coverage Diff @@
## master #620 +/- ##
==========================================
- Coverage 83.27% 83.14% -0.14%
==========================================
Files 30 31 +1
Lines 2463 2509 +46
Branches 283 291 +8
==========================================
+ Hits 2051 2086 +35
- Misses 329 335 +6
- Partials 83 88 +5
Continue to review full report at Codecov.
|
if (shutdown) { | ||
return; | ||
} | ||
track( |
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.
Same as segmentio/analytics-ios#831 (comment) - I don't believe any properties should be collected here, as per https://segment.com/docs/spec/mobile/#application-backgrounded.
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 there's a bug in the behaviour here, particularly for applications with multiple activities.
Currently, I believe that "Application Opened" will be fired any time a new activity in the existing app is opened (regardless of whethere the user already had the app open or not).
Similarly, if the user exits an activity (e.g. by hitting the back button in a multi activity application), it would fire a "Application Backgrounded" event, even though they might still remain in the same app.
That is a good point. Since we don't have access to |
👍 I think there are tradeoffs of both approaches:
I think the boolean approach is best for now as it mimics what we already do, but we should consider the |
Sounds good. I will update that! |
It looks like it is part of Jetpack AndroidX so there are other dependencies to add when using According to the docs it either has a Java 8 dependency or a Kotlin one and the annotation processor differs on each. |
Oof that sucks - yeah I think the boolean approach is definitely the right one for now! |
activityLifecycleCallback = | ||
new Application.ActivityLifecycleCallbacks() { | ||
final AtomicBoolean trackedApplicationLifecycleEvents = new AtomicBoolean(false); | ||
final AtomicInteger numberOfActivities = new AtomicInteger(1); | ||
final AtomicBoolean isChangingActivityConfigurations = new AtomicBoolean(false); | ||
final AtomicBoolean firstLaunch = new AtomicBoolean(false); |
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.
Android has new application lifecycle callbacks via androidx.lifecycle
, but we can't use them due to the dependency requirements AndroidX places. Additionally that breaks the React Native wrapper as AndroidX deps won't work with new RN projects out of the box. We use the traditional method of activity reference counting to detect if we are launching a new activity or resuming to foreground.
if (!trackedApplicationLifecycleEvents.getAndSet(true) | ||
&& shouldTrackApplicationLifecycleEvents) { | ||
numberOfActivities.set(0); | ||
firstLaunch.set(true); |
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 reset the atomic variables for native Android apps. onActivityCreated
is not called when this library is used by the React Native wrapper.
@@ -896,19 +883,6 @@ protected boolean matchesSafely(TrackPayload payload) { | |||
payload.properties().getInt("build", -1) == 101; | |||
} | |||
})); | |||
verify(integration) |
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 was this removed?
@@ -796,19 +796,6 @@ protected boolean matchesSafely(TrackPayload payload) { | |||
payload.properties().getInt("build", -1) == 100; | |||
} | |||
})); | |||
verify(integration) |
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 was this removed?
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.
Both were removed as ApplicationOpened
is no longer called during trackApplicationLifecycleEventsInstalled
. It is now called in onActivityResumed
and depending if it's a cold start or not, the correct Properties are passed.
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.
Got it - shouldn't this test be moved somewhere else then?
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 see it is moved, never mind!
if (firstLaunch.get()) { | ||
properties.putValue("version", currentVersion).putValue("build", currentBuild); | ||
} | ||
properties.putValue("from_background", !firstLaunch.getAndSet(false)); |
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.
On first launch we want to ensure from_background
is false, subsequent calls, this will be true.
return payload.event().equals("Application Opened") | ||
&& payload.properties().getString("version").equals("1.0.0") | ||
&& payload.properties().getInt("build", -1) == 100 | ||
&& !payload.properties().getBoolean("from_background", true); |
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.
This is the first integration test that ensures that on first start from_background
is false
, the correct build params are part of the cold start Application Opened
tracking event.
new NoDescriptionMatcher<TrackPayload>() { | ||
@Override | ||
protected boolean matchesSafely(TrackPayload payload) { | ||
return payload.event().equals("Application Backgrounded"); |
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.
This is the second integration test that launches the app then sends it to background.
@Override | ||
protected boolean matchesSafely(TrackPayload payload) { | ||
return payload.event().equals("Application Opened") | ||
&& payload.properties().getBoolean("from_background", false); |
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.
This is the third integration test that verifies when we send the app to the background, then resume it to foreground the from_background
param is true
.
import java.util.concurrent.atomic.AtomicBoolean; | ||
import java.util.concurrent.atomic.AtomicInteger; | ||
|
||
public class AnalyticsActivityLifecycleCallbacks implements Application.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.
This should be a private class.
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.
(or at least package protected)
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.
LGTM! I think let's make the internal class package protected, and add a bit more internal documentation for how the lifecycle tracking works - and this should be good to merge!
I merged by accident, sorry! Made a revert PR under #621 |
Addresses LIB-1156 and LIB-1143.