Skip to content

Commit 1e570e5

Browse files
zhu-xiaoweixiaoweii
andauthored
feat: add _app_start event, change user engagement attribute. (#20)
Co-authored-by: xiaoweii <[email protected]>
1 parent 510174c commit 1e570e5

File tree

10 files changed

+117
-23
lines changed

10 files changed

+117
-23
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ Add the following dependency to your `app` module's `build.gradle` file.
2020

2121
```groovy
2222
dependencies {
23-
implementation 'software.aws.solution:clickstream:0.4.4'
23+
implementation 'software.aws.solution:clickstream:0.5.0'
2424
}
2525
```
2626

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,7 @@ public void onStateChanged(@NonNull LifecycleOwner lifecycleOwner, @NonNull Life
143143
autoRecordEventClient.recordUserEngagement();
144144
} else if (event == Lifecycle.Event.ON_START) {
145145
LOG.debug("Application entered the foreground.");
146-
autoRecordEventClient.handleFirstOpen();
146+
autoRecordEventClient.handleAppStart();
147147
autoRecordEventClient.updateEngageTimestamp();
148148
boolean isNewSession = sessionClient.initialSession();
149149
if (isNewSession) {

clickstream/src/main/java/software/aws/solution/clickstream/client/AutoRecordEventClient.java

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,11 @@ public class AutoRecordEventClient {
4242
*/
4343
private boolean isFirstOpen;
4444

45+
/**
46+
* whether app is first time start from process launch.
47+
*/
48+
private boolean isFirstTime = true;
49+
4550
/**
4651
* current screen is entrances.
4752
*/
@@ -71,17 +76,21 @@ public AutoRecordEventClient(@NonNull final ClickstreamContext clickstreamContex
7176
public void recordViewScreen(Activity activity) {
7277
String screenId = activity.getClass().getCanonicalName();
7378
String screenName = activity.getClass().getSimpleName();
79+
long currentTimestamp = System.currentTimeMillis();
7480
ScreenRefererTool.setCurrentScreenId(screenId);
7581
ScreenRefererTool.setCurrentScreenName(screenName);
82+
ScreenRefererTool.setCurrentScreenStartTimestamp(currentTimestamp);
7683
final AnalyticsEvent event =
7784
this.clickstreamContext.getAnalyticsClient().createEvent(Event.PresetEvent.SCREEN_VIEW);
7885
event.addAttribute(Event.ReservedAttribute.SCREEN_NAME, ScreenRefererTool.getCurrentScreenName());
7986
event.addAttribute(Event.ReservedAttribute.SCREEN_ID, ScreenRefererTool.getCurrentScreenId());
8087
event.addAttribute(Event.ReservedAttribute.PREVIOUS_SCREEN_NAME, ScreenRefererTool.getPreviousScreenName());
8188
event.addAttribute(Event.ReservedAttribute.PREVIOUS_SCREEN_ID, ScreenRefererTool.getPreviousScreenId());
8289
event.addAttribute(Event.ReservedAttribute.ENTRANCES, isEntrances ? 1 : 0);
83-
event.addAttribute(Event.ReservedAttribute.ENGAGEMENT_TIMESTAMP,
84-
System.currentTimeMillis() - startEngageTimestamp);
90+
if (!isEntrances) {
91+
event.addAttribute(Event.ReservedAttribute.ENGAGEMENT_TIMESTAMP,
92+
currentTimestamp - ScreenRefererTool.getPreviousScreenStartTimestamp());
93+
}
8594
this.clickstreamContext.getAnalyticsClient().recordEvent(event);
8695
isEntrances = false;
8796
LOG.debug("record an _screen_view event, screenId:" + screenId + "lastScreenId:" +
@@ -97,6 +106,8 @@ public void recordUserEngagement() {
97106
final AnalyticsEvent event =
98107
this.clickstreamContext.getAnalyticsClient().createEvent(Event.PresetEvent.USER_ENGAGEMENT);
99108
event.addAttribute(Event.ReservedAttribute.ENGAGEMENT_TIMESTAMP, engagementTime);
109+
event.addAttribute(Event.ReservedAttribute.SCREEN_NAME, ScreenRefererTool.getCurrentScreenName());
110+
event.addAttribute(Event.ReservedAttribute.SCREEN_ID, ScreenRefererTool.getCurrentScreenId());
100111
this.clickstreamContext.getAnalyticsClient().recordEvent(event);
101112
}
102113
}
@@ -151,7 +162,7 @@ private void checkOSVersionUpdate() {
151162
/**
152163
* handle the first open event.
153164
*/
154-
public void handleFirstOpen() {
165+
public void handleAppStart() {
155166
checkAppVersionUpdate();
156167
checkOSVersionUpdate();
157168
if (isFirstOpen) {
@@ -161,6 +172,13 @@ public void handleFirstOpen() {
161172
clickstreamContext.getSystem().getPreferences().putBoolean("isFirstOpen", false);
162173
isFirstOpen = false;
163174
}
175+
final AnalyticsEvent event =
176+
this.clickstreamContext.getAnalyticsClient().createEvent(Event.PresetEvent.APP_START);
177+
event.addAttribute(Event.ReservedAttribute.IS_FIRST_TIME, isFirstTime);
178+
event.addAttribute(Event.ReservedAttribute.SCREEN_NAME, ScreenRefererTool.getCurrentScreenName());
179+
event.addAttribute(Event.ReservedAttribute.SCREEN_ID, ScreenRefererTool.getCurrentScreenId());
180+
this.clickstreamContext.getAnalyticsClient().recordEvent(event);
181+
isFirstTime = false;
164182
}
165183

166184
/**

clickstream/src/main/java/software/aws/solution/clickstream/client/Event.java

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -269,6 +269,11 @@ public static final class ReservedAttribute {
269269
*/
270270
public static final String ENGAGEMENT_TIMESTAMP = "_engagement_time_msec";
271271

272+
/**
273+
* is the first time attribute.
274+
*/
275+
public static final String IS_FIRST_TIME = "_is_first_time";
276+
272277
private ReservedAttribute() {
273278
}
274279
}
@@ -282,15 +287,16 @@ public static final class PresetEvent {
282287
*/
283288
public static final String SESSION_START = "_session_start";
284289

285-
/**
286-
* The eventType recorded for session stop events.
287-
*/
288-
public static final String SESSION_STOP = "_session_stop";
289290
/**
290291
* The eventType recorded for app first open from install.
291292
*/
292293
public static final String FIRST_OPEN = "_first_open";
293294

295+
/**
296+
* The eventType recorded for app start when app move to foreground.
297+
*/
298+
public static final String APP_START = "_app_start";
299+
294300
/**
295301
* The user engagement event when the app is in the foreground at least one second.
296302
*/

clickstream/src/main/java/software/aws/solution/clickstream/client/ScreenRefererTool.java

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ public final class ScreenRefererTool {
2424
private static String mCurrentScreenId;
2525
private static String mPreviousScreenName;
2626
private static String mCurrentScreenName;
27+
private static long mPreviousScreenStartTimestamp;
28+
private static long mCurrentScreenStartTimestamp;
2729

2830
private ScreenRefererTool() {
2931
}
@@ -48,6 +50,16 @@ public static void setCurrentScreenId(String screenId) {
4850
mCurrentScreenId = screenId;
4951
}
5052

53+
/**
54+
* set current screen id.
55+
*
56+
* @param timestamp current screen engage timestamp.
57+
*/
58+
public static void setCurrentScreenStartTimestamp(long timestamp) {
59+
mPreviousScreenStartTimestamp = mCurrentScreenStartTimestamp;
60+
mCurrentScreenStartTimestamp = timestamp;
61+
}
62+
5163
/**
5264
* get current ScreenName.
5365
*
@@ -83,4 +95,13 @@ public static String getPreviousScreenName() {
8395
public static String getPreviousScreenId() {
8496
return mPreviousScreenId;
8597
}
98+
99+
/**
100+
* get previous screen start timestamp.
101+
*
102+
* @return previous screen start timestamp
103+
*/
104+
public static long getPreviousScreenStartTimestamp() {
105+
return mPreviousScreenStartTimestamp;
106+
}
86107
}

clickstream/src/main/java/software/aws/solution/clickstream/client/network/NetRequest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ private static Response request(@NonNull String eventJson, @NonNull ClickstreamC
106106
RequestBody body = RequestBody.create(curStr, MediaType.parse("application/json; charset=utf-8"));
107107
Request request = new Request.Builder().url(endpoint).build();
108108
HttpUrl url = request.url().newBuilder()
109-
.addQueryParameter("platform", "ANDROID")
109+
.addQueryParameter("platform", "Android")
110110
.addQueryParameter("appId", appId)
111111
.addQueryParameter("event_bundle_sequence_id", String.valueOf(bundleSequenceId))
112112
.addQueryParameter("compression", compression)

clickstream/src/main/java/software/aws/solution/clickstream/client/system/AndroidDeviceDetails.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ public String platformVersion() {
5959
* @return The name of platform.
6060
*/
6161
public String platform() {
62-
return "ANDROID";
62+
return "Android";
6363
}
6464

6565
/**

clickstream/src/test/java/software/aws/solution/clickstream/ActivityLifecycleManagerUnitTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ public void testOnAppForegrounded() {
117117
when(sessionClient.initialSession()).thenReturn(true);
118118
lifecycle.handleLifecycleEvent(Lifecycle.Event.ON_START);
119119
verify(autoRecordEventClient).updateEngageTimestamp();
120-
verify(autoRecordEventClient).handleFirstOpen();
120+
verify(autoRecordEventClient).handleAppStart();
121121
verify(sessionClient).initialSession();
122122
verify(autoRecordEventClient).setIsEntrances();
123123
}

clickstream/src/test/java/software/aws/solution/clickstream/AutoRecordEventClientTest.java

Lines changed: 59 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
import software.aws.solution.clickstream.client.ClickstreamContext;
4040
import software.aws.solution.clickstream.client.ClickstreamManager;
4141
import software.aws.solution.clickstream.client.Event;
42+
import software.aws.solution.clickstream.client.ScreenRefererTool;
4243
import software.aws.solution.clickstream.client.db.ClickstreamDBUtil;
4344
import software.aws.solution.clickstream.client.util.StringUtil;
4445
import software.aws.solution.clickstream.util.ReflectUtil;
@@ -96,7 +97,7 @@ public void setup() {
9697
@Test
9798
public void testUserEngagementSuccess() throws Exception {
9899
lifecycle.handleLifecycleEvent(Lifecycle.Event.ON_START);
99-
Thread.sleep(1500);
100+
Thread.sleep(1100);
100101
lifecycle.handleLifecycleEvent(Lifecycle.Event.ON_STOP);
101102
try (Cursor cursor = dbUtil.queryAllEvents()) {
102103
List<String> eventList = new ArrayList<>();
@@ -108,12 +109,15 @@ public void testUserEngagementSuccess() throws Exception {
108109
if (eventName.equals(Event.PresetEvent.USER_ENGAGEMENT)) {
109110
JSONObject attributes = jsonObject.getJSONObject("attributes");
110111
assertTrue(attributes.has(ReservedAttribute.ENGAGEMENT_TIMESTAMP));
112+
assertFalse(attributes.has(ReservedAttribute.SCREEN_NAME));
113+
assertFalse(attributes.has(ReservedAttribute.SCREEN_ID));
111114
assertTrue(attributes.getLong(ReservedAttribute.ENGAGEMENT_TIMESTAMP) > 1000);
112115
}
113116
}
114117
assertEquals(Event.PresetEvent.FIRST_OPEN, eventList.get(0));
115-
assertEquals(Event.PresetEvent.SESSION_START, eventList.get(1));
116-
assertEquals(Event.PresetEvent.USER_ENGAGEMENT, eventList.get(2));
118+
assertEquals(Event.PresetEvent.APP_START, eventList.get(1));
119+
assertEquals(Event.PresetEvent.SESSION_START, eventList.get(2));
120+
assertEquals(Event.PresetEvent.USER_ENGAGEMENT, eventList.get(3));
117121
}
118122
}
119123

@@ -164,6 +168,7 @@ public void testViewOneScreenEvent() throws Exception {
164168
Assert.assertFalse(attributes.has(ReservedAttribute.PREVIOUS_SCREEN_NAME));
165169
Assert.assertFalse(attributes.has(ReservedAttribute.PREVIOUS_SCREEN_ID));
166170
Assert.assertEquals(1, attributes.getInt(ReservedAttribute.ENTRANCES));
171+
Assert.assertFalse(attributes.has(ReservedAttribute.ENGAGEMENT_TIMESTAMP));
167172
}
168173
}
169174
assertTrue(eventList.contains(Event.PresetEvent.SCREEN_VIEW));
@@ -208,8 +213,9 @@ public void testViewTwoScreenEvent() throws Exception {
208213
attributes.getString(ReservedAttribute.PREVIOUS_SCREEN_NAME));
209214
assertEquals(activity1.getClass().getCanonicalName(),
210215
attributes.getString(ReservedAttribute.PREVIOUS_SCREEN_ID));
211-
212216
assertEquals(0, attributes.getInt(ReservedAttribute.ENTRANCES));
217+
Assert.assertTrue(attributes.has(ReservedAttribute.ENGAGEMENT_TIMESTAMP));
218+
Assert.assertTrue(attributes.getLong(ReservedAttribute.ENGAGEMENT_TIMESTAMP) >= 0);
213219
}
214220
}
215221

@@ -333,8 +339,8 @@ public void testOSVersionForUpdate() throws Exception {
333339
*/
334340
@Test
335341
public void testHandleFirstOpen() throws Exception {
336-
client.handleFirstOpen();
337-
assertEquals(1, dbUtil.getTotalNumber());
342+
client.handleAppStart();
343+
assertEquals(2, dbUtil.getTotalNumber());
338344
Cursor cursor = dbUtil.queryAllEvents();
339345
cursor.moveToFirst();
340346
String eventString = cursor.getString(2);
@@ -351,10 +357,10 @@ public void testHandleFirstOpen() throws Exception {
351357
*/
352358
@Test
353359
public void testHandleFirstOpenMultiTimes() throws Exception {
354-
client.handleFirstOpen();
355-
client.handleFirstOpen();
356-
client.handleFirstOpen();
357-
assertEquals(1, dbUtil.getTotalNumber());
360+
client.handleAppStart();
361+
client.handleAppStart();
362+
client.handleAppStart();
363+
assertEquals(4, dbUtil.getTotalNumber());
358364
Cursor cursor = dbUtil.queryAllEvents();
359365
cursor.moveToFirst();
360366
String eventString = cursor.getString(2);
@@ -364,6 +370,47 @@ public void testHandleFirstOpenMultiTimes() throws Exception {
364370
cursor.close();
365371
}
366372

373+
/**
374+
* test execute handleAppStart.
375+
*
376+
* @throws Exception exception.
377+
*/
378+
@Test
379+
public void testHandleAppStart() throws Exception {
380+
client.handleAppStart();
381+
Activity activity1 = mock(Activity.class);
382+
Bundle bundle = mock(Bundle.class);
383+
callbacks.onActivityCreated(activity1, bundle);
384+
callbacks.onActivityStarted(activity1);
385+
callbacks.onActivityResumed(activity1);
386+
client.handleAppStart();
387+
assertEquals(4, dbUtil.getTotalNumber());
388+
try (Cursor cursor = dbUtil.queryAllEvents()) {
389+
List<JSONObject> eventList = new ArrayList<>();
390+
while (cursor.moveToNext()) {
391+
String eventString = cursor.getString(2);
392+
JSONObject jsonObject = new JSONObject(eventString);
393+
eventList.add(jsonObject);
394+
}
395+
assertEquals(Event.PresetEvent.FIRST_OPEN, eventList.get(0).getString("event_type"));
396+
assertEquals(Event.PresetEvent.APP_START, eventList.get(1).getString("event_type"));
397+
JSONObject appStart1 = eventList.get(1).getJSONObject("attributes");
398+
assertTrue(appStart1.getBoolean(Event.ReservedAttribute.IS_FIRST_TIME));
399+
assertFalse(appStart1.has(ReservedAttribute.SCREEN_NAME));
400+
assertFalse(appStart1.has(Event.ReservedAttribute.SCREEN_ID));
401+
402+
assertEquals(Event.PresetEvent.SCREEN_VIEW, eventList.get(2).getString("event_type"));
403+
404+
assertEquals(Event.PresetEvent.APP_START, eventList.get(3).getString("event_type"));
405+
JSONObject appStart2 = eventList.get(3).getJSONObject("attributes");
406+
assertFalse(appStart2.getBoolean(Event.ReservedAttribute.IS_FIRST_TIME));
407+
assertTrue(appStart2.has(ReservedAttribute.SCREEN_NAME));
408+
assertTrue(appStart2.has(Event.ReservedAttribute.SCREEN_ID));
409+
assertEquals(activity1.getClass().getSimpleName(), appStart2.getString(ReservedAttribute.SCREEN_NAME));
410+
assertEquals(activity1.getClass().getCanonicalName(), appStart2.getString(ReservedAttribute.SCREEN_ID));
411+
}
412+
}
413+
367414
/**
368415
* test init autoRecordEventClient with null analyticsClient.
369416
*/
@@ -378,6 +425,8 @@ public void testInitAutoRecordEventClientWithNullAnalyticsClient() {
378425
*/
379426
@After
380427
public void tearDown() {
428+
ScreenRefererTool.setCurrentScreenName(null);
429+
ScreenRefererTool.setCurrentScreenId(null);
381430
dbUtil.closeDB();
382431
}
383432
}

gradle.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ org.gradle.jvmargs=-Xmx4g
1212
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
1313
org.gradle.parallel=true
1414

15-
VERSION_NAME=0.4.4
15+
VERSION_NAME=0.5.0
1616

1717
POM_GROUP=software.aws.solution
1818
POM_ARTIFACT_ID=clickstream

0 commit comments

Comments
 (0)