Skip to content

Commit 12f2908

Browse files
authored
Merge pull request #393 from Iterable/jay/MOB-3386-android-session-tracking
[MOB-3386] android session tracking
2 parents f932710 + d1807b8 commit 12f2908

File tree

5 files changed

+223
-138
lines changed

5 files changed

+223
-138
lines changed

iterableapi-ui/src/main/java/com/iterable/iterableapi/ui/inbox/IterableInboxFragment.java

Lines changed: 7 additions & 137 deletions
Original file line numberDiff line numberDiff line change
@@ -15,23 +15,18 @@
1515
import android.widget.RelativeLayout;
1616
import android.widget.TextView;
1717

18+
import com.iterable.iterableapi.InboxSessionManager;
1819
import com.iterable.iterableapi.IterableActivityMonitor;
1920
import com.iterable.iterableapi.IterableApi;
2021
import com.iterable.iterableapi.IterableConstants;
2122
import com.iterable.iterableapi.IterableInAppDeleteActionType;
2223
import com.iterable.iterableapi.IterableInAppLocation;
2324
import com.iterable.iterableapi.IterableInAppManager;
2425
import com.iterable.iterableapi.IterableInAppMessage;
25-
import com.iterable.iterableapi.IterableInboxSession;
2626
import com.iterable.iterableapi.IterableLogger;
2727
import com.iterable.iterableapi.ui.R;
2828

2929
import java.text.DateFormat;
30-
import java.util.ArrayList;
31-
import java.util.Date;
32-
import java.util.HashMap;
33-
import java.util.List;
34-
import java.util.Map;
3530

3631
/**
3732
* The main class for Inbox UI. Renders the list of Inbox messages and handles touch interaction:
@@ -54,12 +49,12 @@ public class IterableInboxFragment extends Fragment implements IterableInAppMana
5449
TextView noMessagesBodyTextView;
5550
RecyclerView recyclerView;
5651

57-
private final SessionManager sessionManager = new SessionManager();
52+
private final InboxSessionManager sessionManager = new InboxSessionManager();
5853
private IterableInboxAdapterExtension adapterExtension = new DefaultAdapterExtension();
5954
private IterableInboxComparator comparator = new DefaultInboxComparator();
6055
private IterableInboxFilter filter = new DefaultInboxFilter();
6156
private IterableInboxDateMapper dateMapper = new DefaultInboxDateMapper();
62-
private boolean sessionStarted = false;
57+
6358

6459
/**
6560
* Create an Inbox fragment with default parameters
@@ -194,7 +189,8 @@ public void onResume() {
194189
super.onResume();
195190
updateList();
196191
IterableApi.getInstance().getInAppManager().addListener(this);
197-
startSession();
192+
193+
sessionManager.startSession();
198194
}
199195

200196
@Override
@@ -208,7 +204,7 @@ public void onDestroy() {
208204
super.onDestroy();
209205
IterableActivityMonitor.getInstance().removeCallback(appStateCallback);
210206
if (this.getActivity() != null && !this.getActivity().isChangingConfigurations()) {
211-
stopSession();
207+
sessionManager.endSession();
212208
}
213209
}
214210

@@ -219,24 +215,10 @@ public void onSwitchToForeground() {
219215

220216
@Override
221217
public void onSwitchToBackground() {
222-
stopSession();
218+
sessionManager.endSession();
223219
}
224220
};
225221

226-
private void startSession() {
227-
if (!sessionStarted) {
228-
sessionStarted = true;
229-
sessionManager.onAppDidEnterForeground();
230-
}
231-
}
232-
233-
private void stopSession() {
234-
if (sessionStarted) {
235-
sessionStarted = false;
236-
sessionManager.onAppDidEnterBackground();
237-
}
238-
}
239-
240222
private void updateList() {
241223
IterableInboxAdapter adapter = (IterableInboxAdapter) recyclerView.getAdapter();
242224
adapter.setInboxItems(IterableApi.getInstance().getInAppManager().getInboxMessages());
@@ -348,116 +330,4 @@ public CharSequence mapMessageToDateString(@NonNull IterableInAppMessage message
348330
}
349331
}
350332
}
351-
352-
private static class SessionManager {
353-
IterableInboxSession session = new IterableInboxSession();
354-
Map<String, ImpressionData> impressions = new HashMap<>();
355-
356-
private void onAppDidEnterForeground() {
357-
if (session.sessionStartTime != null) {
358-
IterableLogger.e(TAG, "Inbox session started twice");
359-
return;
360-
}
361-
session = new IterableInboxSession(
362-
new Date(),
363-
null,
364-
IterableApi.getInstance().getInAppManager().getInboxMessages().size(),
365-
IterableApi.getInstance().getInAppManager().getUnreadInboxMessagesCount(),
366-
0,
367-
0,
368-
null);
369-
IterableApi.getInstance().setInboxSessionId(session.sessionId);
370-
}
371-
372-
private void onAppDidEnterBackground() {
373-
if (session.sessionStartTime == null) {
374-
IterableLogger.e(TAG, "Inbox Session ended without start");
375-
return;
376-
}
377-
endAllImpressions();
378-
IterableInboxSession sessionToTrack = new IterableInboxSession(
379-
session.sessionStartTime,
380-
new Date(),
381-
session.startTotalMessageCount,
382-
session.startUnreadMessageCount,
383-
IterableApi.getInstance().getInAppManager().getInboxMessages().size(),
384-
IterableApi.getInstance().getInAppManager().getUnreadInboxMessagesCount(),
385-
getImpressionList());
386-
IterableApi.getInstance().trackInboxSession(sessionToTrack);
387-
IterableApi.getInstance().clearInboxSessionId();
388-
session = new IterableInboxSession();
389-
impressions = new HashMap<>();
390-
}
391-
392-
private void onMessageImpressionStarted(IterableInAppMessage message) {
393-
IterableLogger.printInfo();
394-
String messageId = message.getMessageId();
395-
ImpressionData impressionData = impressions.get(messageId);
396-
if (impressionData == null) {
397-
impressionData = new ImpressionData(messageId, message.isSilentInboxMessage());
398-
impressions.put(messageId, impressionData);
399-
}
400-
impressionData.startImpression();
401-
}
402-
403-
private void onMessageImpressionEnded(IterableInAppMessage message) {
404-
IterableLogger.printInfo();
405-
String messageId = message.getMessageId();
406-
ImpressionData impressionData = impressions.get(messageId);
407-
if (impressionData == null) {
408-
IterableLogger.e(TAG, "onMessageImpressionEnded: impressionData not found");
409-
return;
410-
}
411-
if (impressionData.impressionStarted == null) {
412-
IterableLogger.e(TAG, "onMessageImpressionEnded: impressionStarted is null");
413-
return;
414-
}
415-
impressionData.endImpression();
416-
}
417-
418-
private void endAllImpressions() {
419-
for (ImpressionData impressionData : impressions.values()) {
420-
impressionData.endImpression();
421-
}
422-
}
423-
424-
private List<IterableInboxSession.Impression> getImpressionList() {
425-
List<IterableInboxSession.Impression> impressionList = new ArrayList<>();
426-
for (ImpressionData impressionData : impressions.values()) {
427-
impressionList.add(new IterableInboxSession.Impression(
428-
impressionData.messageId,
429-
impressionData.silentInbox,
430-
impressionData.displayCount,
431-
impressionData.duration
432-
));
433-
}
434-
return impressionList;
435-
}
436-
}
437-
438-
private static class ImpressionData {
439-
final String messageId;
440-
final boolean silentInbox;
441-
int displayCount = 0;
442-
float duration = 0.0f;
443-
444-
Date impressionStarted = null;
445-
446-
private ImpressionData(String messageId, boolean silentInbox) {
447-
this.messageId = messageId;
448-
this.silentInbox = silentInbox;
449-
}
450-
451-
private void startImpression() {
452-
this.impressionStarted = new Date();
453-
}
454-
455-
private void endImpression() {
456-
if (this.impressionStarted != null) {
457-
this.displayCount += 1;
458-
this.duration += (float) (new Date().getTime() - this.impressionStarted.getTime()) / 1000;
459-
this.impressionStarted = null;
460-
}
461-
}
462-
}
463333
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
package com.iterable.iterableapi;
2+
3+
import androidx.annotation.RestrictTo;
4+
5+
import java.util.Date;
6+
7+
@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
8+
class ImpressionData {
9+
final String messageId;
10+
final boolean silentInbox;
11+
int displayCount = 0;
12+
float duration = 0.0f;
13+
14+
Date impressionStarted = null;
15+
16+
ImpressionData(String messageId, boolean silentInbox) {
17+
this.messageId = messageId;
18+
this.silentInbox = silentInbox;
19+
}
20+
21+
void startImpression() {
22+
this.impressionStarted = new Date();
23+
}
24+
25+
void endImpression() {
26+
if (this.impressionStarted != null) {
27+
this.displayCount += 1;
28+
this.duration += (float) (new Date().getTime() - this.impressionStarted.getTime()) / 1000;
29+
this.impressionStarted = null;
30+
}
31+
}
32+
}
Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
package com.iterable.iterableapi;
2+
3+
import androidx.annotation.RestrictTo;
4+
5+
import java.util.ArrayList;
6+
import java.util.Date;
7+
import java.util.HashMap;
8+
import java.util.HashSet;
9+
import java.util.List;
10+
import java.util.Map;
11+
import java.util.Set;
12+
13+
@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
14+
public class InboxSessionManager {
15+
private static final String TAG = "InboxSessionManager";
16+
17+
IterableInboxSession session = new IterableInboxSession();
18+
Map<String, ImpressionData> impressions = new HashMap<>();
19+
20+
public void startSession() {
21+
if (session.sessionStartTime != null) {
22+
IterableLogger.e(TAG, "Inbox session started twice");
23+
return;
24+
}
25+
26+
session = new IterableInboxSession(
27+
new Date(),
28+
null,
29+
IterableApi.getInstance().getInAppManager().getInboxMessages().size(),
30+
IterableApi.getInstance().getInAppManager().getUnreadInboxMessagesCount(),
31+
0,
32+
0,
33+
null);
34+
35+
IterableApi.getInstance().setInboxSessionId(session.sessionId);
36+
}
37+
38+
public void startSession(List<IterableInboxSession.Impression> visibleRows) {
39+
startSession();
40+
41+
updateVisibleRows(visibleRows);
42+
}
43+
44+
public void endSession() {
45+
if (session.sessionStartTime == null) {
46+
IterableLogger.e(TAG, "Inbox Session ended without start");
47+
return;
48+
}
49+
50+
endAllImpressions();
51+
52+
IterableInboxSession sessionToTrack = new IterableInboxSession(
53+
session.sessionStartTime,
54+
new Date(),
55+
session.startTotalMessageCount,
56+
session.startUnreadMessageCount,
57+
IterableApi.getInstance().getInAppManager().getInboxMessages().size(),
58+
IterableApi.getInstance().getInAppManager().getUnreadInboxMessagesCount(),
59+
getImpressionList());
60+
61+
IterableApi.getInstance().trackInboxSession(sessionToTrack);
62+
IterableApi.getInstance().clearInboxSessionId();
63+
64+
session = new IterableInboxSession();
65+
impressions = new HashMap<>();
66+
}
67+
68+
public void updateVisibleRows(List<IterableInboxSession.Impression> visibleRows) {
69+
IterableLogger.printInfo();
70+
71+
// this code is basically doing the equivalent of a diff, but manually
72+
// sorry, i couldn't find a better/quicker way under the time constraint
73+
Set<String> previousImpressions = impressions.keySet();
74+
HashSet<String> visibleMessageIds = new HashSet();
75+
76+
for (IterableInboxSession.Impression row : visibleRows) {
77+
visibleMessageIds.add(row.messageId);
78+
}
79+
80+
Set<String> impressionsToStart = visibleMessageIds;
81+
impressionsToStart.removeAll(previousImpressions);
82+
83+
Set<String> impressionsToEnd = previousImpressions;
84+
impressionsToEnd.removeAll(visibleMessageIds);
85+
86+
for (String messageId : impressionsToStart) {
87+
onMessageImpressionStarted(IterableApi.getInstance().getInAppManager().getMessageById(messageId));
88+
}
89+
90+
for (String messageId : impressionsToEnd) {
91+
endImpression(messageId);
92+
}
93+
}
94+
95+
public void onMessageImpressionStarted(IterableInAppMessage message) {
96+
IterableLogger.printInfo();
97+
98+
String messageId = message.getMessageId();
99+
startImpression(messageId, message.isSilentInboxMessage());
100+
}
101+
102+
public void onMessageImpressionEnded(IterableInAppMessage message) {
103+
IterableLogger.printInfo();
104+
105+
String messageId = message.getMessageId();
106+
endImpression(messageId);
107+
}
108+
109+
private void startImpression(String messageId, boolean silentInbox) {
110+
ImpressionData impressionData = impressions.get(messageId);
111+
112+
if (impressionData == null) {
113+
impressionData = new ImpressionData(messageId, silentInbox);
114+
impressions.put(messageId, impressionData);
115+
}
116+
117+
impressionData.startImpression();
118+
}
119+
120+
private void endImpression(String messageId) {
121+
ImpressionData impressionData = impressions.get(messageId);
122+
123+
if (impressionData == null) {
124+
IterableLogger.e(TAG, "onMessageImpressionEnded: impressionData not found");
125+
return;
126+
}
127+
128+
if (impressionData.impressionStarted == null) {
129+
IterableLogger.e(TAG, "onMessageImpressionEnded: impressionStarted is null");
130+
return;
131+
}
132+
133+
impressionData.endImpression();
134+
}
135+
136+
private void endAllImpressions() {
137+
for (ImpressionData impressionData : impressions.values()) {
138+
impressionData.endImpression();
139+
}
140+
}
141+
142+
private List<IterableInboxSession.Impression> getImpressionList() {
143+
List<IterableInboxSession.Impression> impressionList = new ArrayList<>();
144+
for (ImpressionData impressionData : impressions.values()) {
145+
impressionList.add(new IterableInboxSession.Impression(
146+
impressionData.messageId,
147+
impressionData.silentInbox,
148+
impressionData.displayCount,
149+
impressionData.duration
150+
));
151+
}
152+
return impressionList;
153+
}
154+
}

0 commit comments

Comments
 (0)