Skip to content

Commit 34d39d5

Browse files
authored
callback on message displayed (#270)
1 parent 512e207 commit 34d39d5

File tree

7 files changed

+174
-4
lines changed

7 files changed

+174
-4
lines changed

AndroidSDKCore/src/main/java/com/leanplum/ActionContext.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -389,7 +389,7 @@ private boolean createActionContextForMessageId(String messageAction,
389389
@Override
390390
public void variablesChanged() {
391391
try {
392-
ActionManager.getInstance().recordMessageImpression(actionContext.getMessageId());
392+
Leanplum.triggerMessageDisplayed(actionContext);
393393
} catch (Throwable t) {
394394
Util.handleException(t);
395395
}

AndroidSDKCore/src/main/java/com/leanplum/Leanplum.java

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,15 +25,18 @@
2525
import android.content.Context;
2626
import android.location.Location;
2727
import android.os.AsyncTask;
28+
import android.os.Message;
2829
import android.support.annotation.VisibleForTesting;
2930
import android.text.TextUtils;
3031

3132
import com.leanplum.ActionContext.ContextualValues;
3233
import com.leanplum.callbacks.ActionCallback;
34+
import com.leanplum.callbacks.MessageDisplayedCallback;
3335
import com.leanplum.callbacks.RegisterDeviceCallback;
3436
import com.leanplum.callbacks.RegisterDeviceFinishedCallback;
3537
import com.leanplum.callbacks.StartCallback;
3638
import com.leanplum.callbacks.VariablesChangedCallback;
39+
import com.leanplum.internal.ActionManager;
3740
import com.leanplum.internal.Constants;
3841
import com.leanplum.internal.FileManager;
3942
import com.leanplum.internal.JsonConverter;
@@ -51,6 +54,7 @@
5154
import com.leanplum.internal.Util.DeviceIdInfo;
5255
import com.leanplum.internal.VarCache;
5356
import com.leanplum.messagetemplates.MessageTemplates;
57+
import com.leanplum.models.MessageArchiveData;
5458
import com.leanplum.utils.BuildUtil;
5559
import com.leanplum.utils.SharedPreferencesUtil;
5660

@@ -93,6 +97,8 @@ public class Leanplum {
9397
new ArrayList<>();
9498
private static final ArrayList<VariablesChangedCallback> onceNoDownloadsHandlers =
9599
new ArrayList<>();
100+
private static final ArrayList<MessageDisplayedCallback> messageDisplayedHandlers =
101+
new ArrayList<>();
96102
private static final Object heartbeatLock = new Object();
97103
private static final String LEANPLUM_NOTIFICATION_CHANNEL =
98104
"com.leanplum.LeanplumNotificationChannel";
@@ -1296,6 +1302,60 @@ public static void removeVariablesChangedAndNoDownloadsPendingHandler(
12961302
}
12971303
}
12981304

1305+
/**
1306+
* Add a callback for when a message is displayed.
1307+
*/
1308+
public static void addMessageDisplayedHandler(
1309+
MessageDisplayedCallback handler) {
1310+
if (handler == null) {
1311+
Log.e("addMessageDisplayedHandler - Invalid handler parameter " +
1312+
"provided.");
1313+
return;
1314+
}
1315+
1316+
synchronized (messageDisplayedHandlers) {
1317+
messageDisplayedHandlers.add(handler);
1318+
}
1319+
}
1320+
1321+
/**
1322+
* Removes a variables changed and no downloads pending callback.
1323+
*/
1324+
public static void removeMessageDisplayedHandler(
1325+
MessageDisplayedCallback handler) {
1326+
if (handler == null) {
1327+
Log.e("removeMessageDisplayedHandler - Invalid handler parameter " +
1328+
"provided.");
1329+
return;
1330+
}
1331+
1332+
synchronized (messageDisplayedHandlers) {
1333+
messageDisplayedHandlers.remove(handler);
1334+
}
1335+
}
1336+
1337+
public static void triggerMessageDisplayed(ActionContext actionContext) {
1338+
ActionManager.getInstance().recordMessageImpression(actionContext.getMessageId());
1339+
synchronized (messageDisplayedHandlers) {
1340+
for (MessageDisplayedCallback callback : messageDisplayedHandlers) {
1341+
String messageID = actionContext.getMessageId();
1342+
String messageBody = "";
1343+
try {
1344+
messageBody = (String) actionContext.getArgs().get("Message");
1345+
} catch (Throwable t) {
1346+
Util.handleException(t);
1347+
}
1348+
String recipientUserID = Leanplum.getUserId();
1349+
Date deliveryDateTime = new Date();
1350+
1351+
MessageArchiveData messageArchiveData = new MessageArchiveData(messageID,
1352+
messageBody, recipientUserID, deliveryDateTime);
1353+
callback.setMessageArchiveData(messageArchiveData);
1354+
OsHandler.getInstance().post(callback);
1355+
}
1356+
}
1357+
}
1358+
12991359
/**
13001360
* Add a callback to call ONCE when no more file downloads are pending (either when no files
13011361
* needed to be downloaded or all downloads have been completed).
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
/*
2+
* Copyright 2013, Leanplum, Inc. All rights reserved.
3+
*
4+
* Licensed to the Apache Software Foundation (ASF) under one
5+
* or more contributor license agreements. See the NOTICE file
6+
* distributed with this work for additional information
7+
* regarding copyright ownership. The ASF licenses this file
8+
* to you under the Apache License, Version 2.0 (the
9+
* "License"); you may not use this file except in compliance
10+
* with the License. You may obtain a copy of the License at
11+
*
12+
* http://www.apache.org/licenses/LICENSE-2.0
13+
*
14+
* Unless required by applicable law or agreed to in writing,
15+
* software distributed under the License is distributed on an
16+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17+
* KIND, either express or implied. See the License for the
18+
* specific language governing permissions and limitations
19+
* under the License.
20+
*/
21+
22+
package com.leanplum.callbacks;
23+
24+
import com.leanplum.models.MessageArchiveData;
25+
26+
/**
27+
* Message displayed callback.
28+
*
29+
* @author Mayank Sanganeria
30+
*/
31+
public abstract class MessageDisplayedCallback implements Runnable {
32+
33+
private MessageArchiveData messageArchiveData;
34+
35+
public void setMessageArchiveData(MessageArchiveData messageArchiveData) {
36+
this.messageArchiveData = messageArchiveData;
37+
}
38+
39+
public void run() {
40+
this.messageDisplayed(messageArchiveData);
41+
}
42+
43+
public abstract void messageDisplayed(MessageArchiveData messageArchiveData);
44+
}

AndroidSDKCore/src/main/java/com/leanplum/internal/LeanplumInternal.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -259,7 +259,7 @@ public int compare(ActionContext o1, ActionContext o2) {
259259
@Override
260260
public void variablesChanged() {
261261
try {
262-
ActionManager.getInstance().recordMessageImpression(actionContext.getMessageId());
262+
Leanplum.triggerMessageDisplayed(actionContext);
263263
} catch (Throwable t) {
264264
Util.handleException(t);
265265
}

AndroidSDKCore/src/main/java/com/leanplum/internal/Socket.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -234,7 +234,7 @@ void handleTriggerEvent(JSONArray arguments) {
234234
((BaseActionContext) context).setIsPreview(true);
235235
context.update();
236236
LeanplumInternal.triggerAction(context);
237-
ActionManager.getInstance().recordMessageImpression(messageId);
237+
Leanplum.triggerMessageDisplayed(context);
238238
}
239239
} catch (JSONException e) {
240240
Log.e("Error getting action info", e);
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
package com.leanplum.models;
2+
3+
import android.support.annotation.NonNull;
4+
5+
import java.util.Date;
6+
7+
public class MessageArchiveData {
8+
@NonNull public String messageID;
9+
@NonNull public String messageBody;
10+
@NonNull public String recipientUserID;
11+
@NonNull public Date deliveryDateTime;
12+
13+
public MessageArchiveData(String messageID, String messageBody, String recipientUserID, Date deliveryDateTime) {
14+
this.messageID = messageID;
15+
this.messageBody = messageBody;
16+
this.recipientUserID = recipientUserID;
17+
this.deliveryDateTime = deliveryDateTime;
18+
}
19+
}

AndroidSDKTests/src/test/java/com/leanplum/LeanplumTest.java

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
import com.leanplum._whitebox.utilities.ResponseHelper;
3333
import com.leanplum._whitebox.utilities.VariablesTestClass;
3434
import com.leanplum.annotations.Parser;
35+
import com.leanplum.callbacks.MessageDisplayedCallback;
3536
import com.leanplum.callbacks.StartCallback;
3637
import com.leanplum.callbacks.VariablesChangedCallback;
3738
import com.leanplum.internal.CollectionUtil;
@@ -45,18 +46,21 @@
4546
import com.leanplum.internal.Request;
4647
import com.leanplum.internal.Util;
4748
import com.leanplum.internal.VarCache;
49+
import com.leanplum.models.MessageArchiveData;
4850

4951
import org.json.JSONArray;
5052
import org.json.JSONException;
5153
import org.json.JSONObject;
5254
import org.junit.Test;
55+
import org.mockito.Mock;
5356
import org.mockito.Mockito;
5457
import org.robolectric.RuntimeEnvironment;
5558

5659
import java.lang.reflect.Method;
5760
import java.net.URLConnection;
5861
import java.util.ArrayList;
5962
import java.util.Arrays;
63+
import java.util.Date;
6064
import java.util.HashMap;
6165
import java.util.HashSet;
6266
import java.util.Iterator;
@@ -80,7 +84,9 @@
8084
import static org.mockito.Matchers.anyInt;
8185
import static org.mockito.Matchers.anyString;
8286
import static org.mockito.Mockito.never;
87+
import static org.mockito.Mockito.only;
8388
import static org.mockito.Mockito.times;
89+
import static org.mockito.Mockito.when;
8490
import static org.powermock.api.mockito.PowerMockito.doNothing;
8591
import static org.powermock.api.mockito.PowerMockito.doReturn;
8692
import static org.powermock.api.mockito.PowerMockito.verifyStatic;
@@ -1048,7 +1054,7 @@ public void testLocationProvider() throws Exception {
10481054
addresses.add(address);
10491055
Geocoder geocoder = Mockito.mock(Geocoder.class);
10501056
whenNew(Geocoder.class).withAnyArguments().thenReturn(geocoder);
1051-
Mockito.when(geocoder.getFromLocation(anyDouble(), anyDouble(), anyInt()))
1057+
when(geocoder.getFromLocation(anyDouble(), anyDouble(), anyInt()))
10521058
.thenReturn(addresses);
10531059

10541060
// Validate set location request shorthand.
@@ -1455,4 +1461,45 @@ private List<JSONObject> responsesWithCountAndPrefix(int n, String prefix) {
14551461
}
14561462
return responsesList;
14571463
}
1464+
1465+
/**
1466+
* Test trigger message displayed calls callback
1467+
*/
1468+
@Test
1469+
public void testTriggerMessageDisplayedCallbackCalled() {
1470+
final String messageID = "testMessageID";
1471+
final String messageBody = "testMessageBody";
1472+
final String userID = "testUserID";
1473+
1474+
Map<String, Object> args = new HashMap<>();
1475+
args.put("Message", messageBody);
1476+
final ActionContext testActionContext = new ActionContext("test", args, messageID);
1477+
1478+
when(Leanplum.getUserId()).thenReturn(userID);
1479+
1480+
class CallbackTest {
1481+
public boolean callbackCalled = false;
1482+
public MessageDisplayedCallback callback;
1483+
1484+
CallbackTest() {
1485+
callback = new MessageDisplayedCallback() {
1486+
@Override
1487+
public void messageDisplayed(MessageArchiveData messageArchiveData) {
1488+
callbackCalled = true;
1489+
assertTrue(messageArchiveData.messageID.equals(messageID));
1490+
assertTrue(messageArchiveData.messageBody.equals(messageBody));
1491+
assertTrue(messageArchiveData.recipientUserID.equals(userID));
1492+
long timeDiff = new Date().getTime() - messageArchiveData.deliveryDateTime.getTime();
1493+
assertTrue(timeDiff < 1000);
1494+
}
1495+
};
1496+
}
1497+
}
1498+
1499+
CallbackTest callbackTest = new CallbackTest();
1500+
1501+
Leanplum.addMessageDisplayedHandler(callbackTest.callback);
1502+
Leanplum.triggerMessageDisplayed(testActionContext);
1503+
assertTrue(callbackTest.callbackCalled);
1504+
}
14581505
}

0 commit comments

Comments
 (0)