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

Add Application Open and Application Backgrounded Events #620

Merged
merged 8 commits into from
Jul 23, 2019

Conversation

carloskelly13
Copy link
Contributor

@carloskelly13 carloskelly13 commented Jul 16, 2019

Addresses LIB-1156 and LIB-1143.

@codecov-io
Copy link

codecov-io commented Jul 16, 2019

Codecov Report

Merging #620 into master will decrease coverage by 0.13%.
The diff coverage is 87.83%.

Impacted file tree graph

@@            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
Impacted Files Coverage Δ
...src/main/java/com/segment/analytics/Analytics.java 75.53% <100%> (-0.03%) ⬇️
...analytics/AnalyticsActivityLifecycleCallbacks.java 86.56% <86.56%> (ø)
.../src/main/java/com/segment/analytics/ValueMap.java 86.39% <0%> (-2.73%) ⬇️
...ain/java/com/segment/analytics/internal/Utils.java 74.13% <0%> (-1.15%) ⬇️
...cs/src/main/java/com/segment/analytics/Traits.java 92.3% <0%> (-1.1%) ⬇️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 93c7d5b...064c69a. Read the comment docs.

if (shutdown) {
return;
}
track(
Copy link
Contributor

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.

Copy link
Contributor

@f2prateek f2prateek left a 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.

@carloskelly13
Copy link
Contributor Author

That is a good point. Since we don't have access to android.arch.lifecycle I could use the atomic boolean like we did for onActivityCreated to ensure it only fires for the first activity. Otherwise the user would have to manually add the tracking.

@f2prateek
Copy link
Contributor

👍 I think there are tradeoffs of both approaches:

  • android.arch.lifecycle approach: likely more reliable as they've handled edge cases for us, but requires adding a new dependency.
  • boolean approach: likely less reliable as we might not account properly for all edge cases, but doesn't require a dependency.

I think the boolean approach is best for now as it mimics what we already do, but we should consider the android.arch.lifecycle approach in the future to make this more bullet proof.

@carloskelly13
Copy link
Contributor Author

Sounds good. I will update that!

@carloskelly13
Copy link
Contributor Author

carloskelly13 commented Jul 17, 2019

It looks like it is part of Jetpack AndroidX so there are other dependencies to add when using android.arch.lifecycle. https://developer.android.com/jetpack/androidx/releases/lifecycle

According to the docs it either has a Java 8 dependency or a Kotlin one and the annotation processor differs on each.

@f2prateek
Copy link
Contributor

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);
Copy link
Contributor Author

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);
Copy link
Contributor Author

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)
Copy link
Contributor

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)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why was this removed?

Copy link
Contributor Author

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.

Copy link
Contributor

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?

Copy link
Contributor

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));
Copy link
Contributor Author

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);
Copy link
Contributor Author

@carloskelly13 carloskelly13 Jul 18, 2019

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");
Copy link
Contributor Author

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);
Copy link
Contributor Author

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 {
Copy link
Contributor

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.

Copy link
Contributor

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)

Copy link
Contributor

@f2prateek f2prateek left a 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!

@f2prateek f2prateek requested review from bsneed and fathyb July 22, 2019 18:48
@fathyb fathyb merged commit 1cfb025 into segmentio:master Jul 23, 2019
fathyb added a commit that referenced this pull request Jul 23, 2019
@fathyb
Copy link
Contributor

fathyb commented Jul 23, 2019

I merged by accident, sorry! Made a revert PR under #621

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants