Skip to content

Commit ebbb399

Browse files
zhu-xiaoweixiaoweii
andauthored
feat: modify session, user engagement preset event, change user scheme (#10)
--------- Co-authored-by: xiaoweii <xiaoweii@amazom.com>
1 parent 2c9646c commit ebbb399

File tree

64 files changed

+1341
-1186
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

64 files changed

+1341
-1186
lines changed

NOTICE

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
1+
Copyright 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved.

build.gradle

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved.
2+
* Copyright 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License").
55
* You may not use this file except in compliance with the License.
@@ -47,12 +47,15 @@ ext {
4747
targetSdkVersion = 30
4848
awsSdkVersion = '2.51.0'
4949
amplifySdkVersion = '1.37.2'
50+
lifecycleVersion = "2.6.1"
5051
dependency = [
5152
android: [
5253
desugartools: 'com.android.tools:desugar_jdk_libs:1.0.9',
5354
],
5455
androidx: [
55-
test: 'androidx.test:core:1.5.0'
56+
test: 'androidx.test:core:1.5.0',
57+
lifecycle_common: "androidx.lifecycle:lifecycle-common-java8:$lifecycleVersion",
58+
lifecycle_process: "androidx.lifecycle:lifecycle-process:$lifecycleVersion",
5659
],
5760
amplifyframework: [
5861
core: "com.amplifyframework:core:$amplifySdkVersion"

clickstream/build.gradle

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved.
2+
* Copyright 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License").
55
* You may not use this file except in compliance with the License.
@@ -20,6 +20,8 @@ dependencies {
2020
implementation dependency.aws.mobileclient
2121
implementation dependency.amplifyframework.core
2222
implementation dependency.okhttp
23+
implementation dependency.androidx.lifecycle_common
24+
implementation dependency.androidx.lifecycle_process
2325

2426
testImplementation dependency.junit
2527
testImplementation dependency.mockito

clickstream/src/main/AndroidManifest.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<?xml version="1.0" encoding="utf-8"?><!--
2-
Copyright 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved.
2+
Copyright 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved.
33
44
Licensed under the Apache License, Version 2.0 (the "License").
55
You may not use this file except in compliance with the License.

clickstream/src/main/java/software/aws/solution/clickstream/AWSClickstreamPlugin.java

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved.
2+
* Copyright 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License").
55
* You may not use this file except in compliance with the License.
@@ -19,6 +19,7 @@
1919
import android.content.Context;
2020
import androidx.annotation.NonNull;
2121
import androidx.annotation.Nullable;
22+
import androidx.lifecycle.ProcessLifecycleOwner;
2223

2324
import com.amplifyframework.analytics.AnalyticsEventBehavior;
2425
import com.amplifyframework.analytics.AnalyticsException;
@@ -60,14 +61,19 @@ public AWSClickstreamPlugin(final Application application) {
6061

6162
@Override
6263
public void identifyUser(@NonNull String userId, @Nullable UserProfile profile) {
63-
analyticsClient.addUserAttribute(Event.ReservedAttribute.USER_ID, userId);
64-
if (profile instanceof ClickstreamUserAttribute) {
65-
for (Map.Entry<String, AnalyticsPropertyBehavior<?>> entry :
66-
((ClickstreamUserAttribute) profile).getUserAttributes()) {
67-
AnalyticsPropertyBehavior<?> property = entry.getValue();
68-
analyticsClient.addUserAttribute(entry.getKey(), property.getValue());
64+
if (userId.equals(Event.ReservedAttribute.USER_ID_UNSET)) {
65+
if (profile instanceof ClickstreamUserAttribute) {
66+
for (Map.Entry<String, AnalyticsPropertyBehavior<?>> entry :
67+
((ClickstreamUserAttribute) profile).getUserAttributes()) {
68+
AnalyticsPropertyBehavior<?> property = entry.getValue();
69+
analyticsClient.addUserAttribute(entry.getKey(), property.getValue());
70+
}
6971
}
72+
} else {
73+
analyticsClient.updateUserId(userId);
7074
}
75+
analyticsClient.updateUserAttribute();
76+
recordEvent(Event.PresetEvent.PROFILE_SET);
7177
}
7278

7379
@Override
@@ -79,7 +85,7 @@ public void disable() {
7985
@Override
8086
public void enable() {
8187
autoEventSubmitter.start();
82-
activityLifecycleManager.startLifecycleTracking(application);
88+
activityLifecycleManager.startLifecycleTracking(application, ProcessLifecycleOwner.get().getLifecycle());
8389
}
8490

8591
@Override
@@ -191,7 +197,7 @@ public void configure(
191197
autoEventSubmitter.start();
192198

193199
activityLifecycleManager = new ActivityLifecycleManager(clickstreamManager);
194-
activityLifecycleManager.startLifecycleTracking(application);
200+
activityLifecycleManager.startLifecycleTracking(application, ProcessLifecycleOwner.get().getLifecycle());
195201
}
196202

197203
@Override

clickstream/src/main/java/software/aws/solution/clickstream/AWSClickstreamPluginConfiguration.java

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved.
2+
* Copyright 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License").
55
* You may not use this file except in compliance with the License.
@@ -21,6 +21,7 @@
2121
public final class AWSClickstreamPluginConfiguration {
2222
private static final long DEFAULT_SEND_EVENTS_INTERVAL = 10000L;
2323
private static final long DEFAULT_CALL_TIME_OUT = 15000L;
24+
private static final long DEFAULT_SESSION_TIME_OUT = 1800000L;
2425

2526
// Clickstream configuration options
2627
private final String appId;
@@ -30,6 +31,7 @@ public final class AWSClickstreamPluginConfiguration {
3031
private final boolean isTrackAppLifecycleEvents;
3132
private final boolean isTrackAppExceptionEvents;
3233
private final boolean isCompressEvents;
34+
private final long sessionTimeOut;
3335

3436
private AWSClickstreamPluginConfiguration(Builder builder) {
3537
this.appId = builder.appId;
@@ -39,6 +41,7 @@ private AWSClickstreamPluginConfiguration(Builder builder) {
3941
this.sendEventsInterval = builder.sendEventsInterval;
4042
this.endpoint = builder.endpoint;
4143
this.isCompressEvents = builder.isCompressEvents;
44+
this.sessionTimeOut = builder.sessionTimeOut;
4245
}
4346

4447
/**
@@ -104,6 +107,15 @@ boolean isCompressEvents() {
104107
return isCompressEvents;
105108
}
106109

110+
/**
111+
* Accessor for session time out.
112+
*
113+
* @return sessionTimeOut
114+
*/
115+
long getSessionTimeOut() {
116+
return sessionTimeOut;
117+
}
118+
107119
/**
108120
* Return a builder that can be used to construct a new instance of
109121
* {@link AWSClickstreamPluginConfiguration}.
@@ -126,6 +138,8 @@ static final class Builder {
126138
private boolean isTrackAppLifecycleEvents = true;
127139
private boolean isTrackAppExceptionEvents = false;
128140

141+
private long sessionTimeOut = DEFAULT_SESSION_TIME_OUT;
142+
129143
Builder withAppId(final String appId) {
130144
this.appId = appId;
131145
return this;
@@ -156,6 +170,11 @@ Builder withTrackAppExceptionEvents(final boolean trackAppExceptionEvents) {
156170
return this;
157171
}
158172

173+
Builder withSessionTimeOut(final long sessionTimeOut) {
174+
this.sessionTimeOut = sessionTimeOut;
175+
return this;
176+
}
177+
159178
AWSClickstreamPluginConfiguration build() {
160179
return new AWSClickstreamPluginConfiguration(this);
161180
}

clickstream/src/main/java/software/aws/solution/clickstream/ActivityLifecycleManager.java

Lines changed: 27 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved.
2+
* Copyright 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License").
55
* You may not use this file except in compliance with the License.
@@ -18,6 +18,10 @@
1818
import android.app.Activity;
1919
import android.app.Application;
2020
import android.os.Bundle;
21+
import androidx.annotation.NonNull;
22+
import androidx.lifecycle.Lifecycle;
23+
import androidx.lifecycle.LifecycleEventObserver;
24+
import androidx.lifecycle.LifecycleOwner;
2125

2226
import com.amazonaws.logging.Log;
2327
import com.amazonaws.logging.LogFactory;
@@ -29,7 +33,7 @@
2933
* Tracks when the host application enters or leaves foreground.
3034
* The constructor registers to receive activity lifecycle events.
3135
**/
32-
final class ActivityLifecycleManager implements Application.ActivityLifecycleCallbacks {
36+
final class ActivityLifecycleManager implements Application.ActivityLifecycleCallbacks, LifecycleEventObserver {
3337
private static final Log LOG = LogFactory.getLog(ActivityLifecycleManager.class);
3438

3539
private final SessionClient sessionClient;
@@ -49,8 +53,9 @@ final class ActivityLifecycleManager implements Application.ActivityLifecycleCal
4953
foregroundActivityCount = 0;
5054
}
5155

52-
void startLifecycleTracking(final Application application) {
56+
void startLifecycleTracking(final Application application, Lifecycle lifecycle) {
5357
application.registerActivityLifecycleCallbacks(this);
58+
lifecycle.addObserver(this);
5459
}
5560

5661
void stopLifecycleTracking(final Application application) {
@@ -72,7 +77,6 @@ public void onActivityResumed(final Activity activity) {
7277
// An activity came to foreground. Application potentially entered foreground as well
7378
// if there were no other activities in the foreground.
7479
LOG.debug("Activity resumed: " + activity.getLocalClassName());
75-
autoRecordEventClient.recordActivityStart(activity);
7680
checkIfApplicationEnteredForeground();
7781
foregroundActivityCount++;
7882
autoRecordEventClient.recordViewScreen(activity);
@@ -95,8 +99,6 @@ public void onActivityStopped(final Activity activity) {
9599
LOG.debug("Activity stopped: " + activity.getLocalClassName());
96100
foregroundActivityCount--;
97101
checkIfApplicationEnteredBackground();
98-
autoRecordEventClient.recordUserEngagement(activity);
99-
autoRecordEventClient.removeActivityStart(activity);
100102
}
101103

102104
@Override
@@ -110,23 +112,6 @@ public void onActivityDestroyed(final Activity activity) {
110112
LOG.debug("Activity destroyed " + activity.getLocalClassName());
111113
}
112114

113-
/**
114-
* Called when the application enters the foreground.
115-
*/
116-
void applicationEnteredForeground() {
117-
LOG.debug("Application entered the foreground.");
118-
sessionClient.startSession();
119-
sessionClient.handleFirstOpen();
120-
}
121-
122-
/**
123-
* Called when the application enters the background.
124-
*/
125-
void applicationEnteredBackground() {
126-
LOG.debug("Application entered the background.");
127-
sessionClient.stopSession();
128-
}
129-
130115
/**
131116
* Called from onActivityResumed to check if the application came to the foreground.
132117
*/
@@ -135,8 +120,7 @@ private void checkIfApplicationEnteredForeground() {
135120
// indicates we are indeed in the background.
136121
if (foregroundActivityCount == 0 && !inForeground) {
137122
inForeground = true;
138-
// Since this is called when an activity has started, we now know the app has entered the foreground.
139-
applicationEnteredForeground();
123+
LOG.debug("Application open.");
140124
}
141125
}
142126

@@ -147,7 +131,24 @@ private void checkIfApplicationEnteredBackground() {
147131
// If the App is in the foreground and there are no longer any activities that have not been stopped.
148132
if (foregroundActivityCount == 0 && inForeground) {
149133
inForeground = false;
150-
applicationEnteredBackground();
134+
LOG.debug("Application exit.");
135+
}
136+
}
137+
138+
@Override
139+
public void onStateChanged(@NonNull LifecycleOwner lifecycleOwner, @NonNull Lifecycle.Event event) {
140+
if (event == Lifecycle.Event.ON_STOP) {
141+
LOG.debug("Application entered the background.");
142+
sessionClient.storeSession();
143+
autoRecordEventClient.recordUserEngagement();
144+
} else if (event == Lifecycle.Event.ON_START) {
145+
LOG.debug("Application entered the foreground.");
146+
autoRecordEventClient.updateEngageTimestamp();
147+
autoRecordEventClient.handleFirstOpen();
148+
boolean isNewSession = sessionClient.initialSession();
149+
if (isNewSession) {
150+
autoRecordEventClient.setIsEntrances();
151+
}
151152
}
152153
}
153154
}
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
/*
2+
* Copyright 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License").
5+
* You may not use this file except in compliance with the License.
6+
* A copy of the License is located at
7+
*
8+
* http://aws.amazon.com/apache2.0
9+
*
10+
* or in the "license" file accompanying this file. This file is distributed
11+
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
12+
* express or implied. See the License for the specific language governing
13+
* permissions and limitations under the License.
14+
*/
15+
16+
package software.aws.solution.clickstream;
17+
18+
import androidx.annotation.NonNull;
19+
20+
import com.amplifyframework.analytics.AnalyticsProperties;
21+
import com.amplifyframework.analytics.AnalyticsPropertyBehavior;
22+
23+
import java.util.Objects;
24+
25+
/**
26+
* AnalyticsLongProperty wraps an Long value to store in {@link AnalyticsProperties}.
27+
*/
28+
public final class AnalyticsLongProperty implements AnalyticsPropertyBehavior<Long> {
29+
private final Long value;
30+
31+
private AnalyticsLongProperty(Long value) {
32+
this.value = value;
33+
}
34+
35+
/**
36+
* getValue returns the wrapped Long value stored in the property.
37+
*
38+
* @return The wrapped Boolean value
39+
*/
40+
@NonNull
41+
@Override
42+
public Long getValue() {
43+
return value;
44+
}
45+
46+
/**
47+
* Factory method to instantiate an {@link AnalyticsLongProperty} from a {@link Long} value.
48+
*
49+
* @param value an Long value
50+
* @return an instance of {@link AnalyticsLongProperty}
51+
*/
52+
@NonNull
53+
public static AnalyticsLongProperty from(@NonNull Long value) {
54+
return new AnalyticsLongProperty(Objects.requireNonNull(value));
55+
}
56+
}

clickstream/src/main/java/software/aws/solution/clickstream/AutoEventSubmitter.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved.
2+
* Copyright 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License").
55
* You may not use this file except in compliance with the License.

clickstream/src/main/java/software/aws/solution/clickstream/ClickstreamAnalytics.java

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved.
2+
* Copyright 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License").
55
* You may not use this file except in compliance with the License.
@@ -23,6 +23,7 @@
2323

2424
import software.aws.solution.clickstream.client.AnalyticsClient;
2525
import software.aws.solution.clickstream.client.ClickstreamConfiguration;
26+
import software.aws.solution.clickstream.client.Event;
2627

2728
/**
2829
* This is the top-level customer-facing interface to The ClickstreamAnalytics.
@@ -88,12 +89,12 @@ public static void deleteGlobalAttributes(@NonNull String... attributeName) {
8889
}
8990

9091
/**
91-
* add user.
92+
* add user attributes.
9293
*
9394
* @param userProfile user
9495
*/
9596
public static void addUserAttributes(ClickstreamUserAttribute userProfile) {
96-
Amplify.Analytics.identifyUser(userProfile.getUserId(), userProfile);
97+
Amplify.Analytics.identifyUser(Event.ReservedAttribute.USER_ID_UNSET, userProfile);
9798
}
9899

99100
/**
@@ -102,7 +103,11 @@ public static void addUserAttributes(ClickstreamUserAttribute userProfile) {
102103
* @param userId user
103104
*/
104105
public static void setUserId(String userId) {
105-
Amplify.Analytics.identifyUser(userId, new ClickstreamUserAttribute.Builder().build());
106+
String newUserId = userId;
107+
if (newUserId == null) {
108+
newUserId = "";
109+
}
110+
Amplify.Analytics.identifyUser(newUserId, new ClickstreamUserAttribute.Builder().build());
106111
}
107112

108113
/**

0 commit comments

Comments
 (0)