Skip to content

Commit a9af1ea

Browse files
committed
Added NotificationExtender to allow customizing notifications
1 parent b2f0fc0 commit a9af1ea

17 files changed

+601
-121
lines changed

OneSignalSDK/app/src/main/AndroidManifest.xml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,16 @@
9090
</intent-filter>
9191
</receiver>
9292
-->
93+
94+
95+
<service
96+
android:name=".NotificationExtenderServiceTest"
97+
android:exported="false">
98+
<intent-filter>
99+
<action android:name="com.onesignal.NotificationExtender" />
100+
</intent-filter>
101+
</service>
102+
93103
</application>
94104

95105
</manifest>
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
package com.onesignal.example;
2+
3+
import android.support.v4.app.NotificationCompat;
4+
5+
import com.onesignal.OSNotificationPayload;
6+
import com.onesignal.NotificationExtenderService;
7+
8+
import java.lang.reflect.Field;
9+
import java.math.BigInteger;
10+
11+
public class NotificationExtenderServiceTest extends NotificationExtenderService {
12+
13+
@Override
14+
protected boolean onNotificationProcessing(OSNotificationPayload notification) {
15+
printObject(notification);
16+
if (notification.actionButtons != null) {
17+
for(OSNotificationPayload.ActionButton button : notification.actionButtons) {
18+
System.out.println("button:");
19+
printObject(button);
20+
}
21+
}
22+
23+
OverrideSettings overrideSettings = new OverrideSettings();
24+
25+
overrideSettings.extender = new NotificationCompat.Extender() {
26+
@Override
27+
public NotificationCompat.Builder extend(NotificationCompat.Builder builder) {
28+
return builder.setColor(new BigInteger("FF00FF00", 16).intValue());
29+
}
30+
};
31+
32+
displayNotification(overrideSettings);
33+
34+
return true;
35+
}
36+
37+
private void printObject(Object obj) {
38+
for (Field field : obj.getClass().getDeclaredFields()) {
39+
String name = field.getName();
40+
try {
41+
Object value = field.get(obj);
42+
System.out.printf("Field name: %s, Field value: %s%n", name, value);
43+
} catch (Throwable t){}
44+
}
45+
}
46+
}

OneSignalSDK/app/src/test/java/com/onesignal/OneSignalPackagePrivateHelper.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
package com.onesignal;
22

3+
import android.content.Context;
4+
import android.os.Bundle;
35
import android.os.Looper;
46

7+
import org.json.JSONObject;
58
import org.robolectric.util.Scheduler;
69

710
import java.util.Map;
@@ -38,6 +41,18 @@ public static void SyncService_onTaskRemoved() {
3841
SyncService.onTaskRemoved();
3942
}
4043

44+
public static JSONObject bundleAsJSONObject(Bundle bundle) {
45+
return NotificationBundleProcessor.bundleAsJSONObject(bundle);
46+
}
47+
48+
public static void NotificationBundleProcessor_ProcessFromGCMIntentService(Context context, Bundle bundle, NotificationExtenderService.OverrideSettings overrideSettings) {
49+
NotificationBundleProcessor.ProcessFromGCMIntentService(context, bundle, overrideSettings);
50+
}
51+
52+
public static boolean GcmBroadcastReceiver_processBundle(Context context, Bundle bundle) {
53+
return GcmBroadcastReceiver.processBundle(context, bundle);
54+
}
55+
4156

4257
public class NotificationTable extends OneSignalDbContract.NotificationTable { }
4358
}

OneSignalSDK/app/src/test/java/com/onesignal/ShadowRoboNotificationManager.java

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,9 +62,7 @@ public void notify(String tag, int id, Notification notification) {
6262
lastNotif = shadowOf(notification);
6363
lastNotifId = id;
6464
notifications.add(new PostedNotification(id, lastNotif));
65-
System.out.println("notification: " + lastNotif.getContentText());
6665
super.notify(tag, id, notification);
67-
//throw new RuntimeException("Get stack trace!");
6866
}
6967

7068
}

OneSignalSDK/app/src/test/java/com/test/onesignal/GenerateNotificationRunner.java

Lines changed: 131 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -32,14 +32,18 @@
3232
import android.content.Intent;
3333
import android.content.pm.ActivityInfo;
3434
import android.content.pm.ResolveInfo;
35+
import android.content.pm.ServiceInfo;
3536
import android.database.Cursor;
3637
import android.database.sqlite.SQLiteDatabase;
3738
import android.os.Bundle;
3839

3940
import com.onesignal.BuildConfig;
40-
import com.onesignal.NotificationBundleProcessor;
41+
import com.onesignal.NotificationExtenderService;
4142
import com.onesignal.NotificationOpenedProcessor;
43+
import com.onesignal.OSNotificationDisplayedResult;
44+
import com.onesignal.OSNotificationPayload;
4245
import com.onesignal.OneSignalDbHelper;
46+
import com.onesignal.OneSignalPackagePrivateHelper;
4347
import com.onesignal.ShadowBadgeCountUpdater;
4448
import com.onesignal.ShadowOneSignalRestClient;
4549
import com.onesignal.ShadowRoboNotificationManager;
@@ -49,15 +53,18 @@
4953

5054
import junit.framework.Assert;
5155

56+
import org.json.JSONObject;
5257
import org.junit.Before;
5358
import org.junit.BeforeClass;
5459
import org.junit.Test;
5560
import org.junit.runner.RunWith;
5661
import org.robolectric.Robolectric;
5762
import org.robolectric.RuntimeEnvironment;
63+
import org.robolectric.Shadows;
5864
import org.robolectric.annotation.Config;
5965
import org.robolectric.shadows.ShadowLog;
6066
import org.robolectric.shadows.ShadowSystemClock;
67+
import org.robolectric.util.ServiceController;
6168

6269
import java.util.List;
6370

@@ -116,7 +123,7 @@ public static Bundle getBaseNotifBundle(String id) {
116123
static Intent createOpenIntent(int notifId, Bundle bundle) {
117124
return new Intent()
118125
.putExtra("notificationId", notifId)
119-
.putExtra("onesignal_data", NotificationBundleProcessor.bundleAsJSONObject(bundle).toString());
126+
.putExtra("onesignal_data", OneSignalPackagePrivateHelper.bundleAsJSONObject(bundle).toString());
120127
}
121128

122129
private Intent createOpenIntent(Bundle bundle) {
@@ -127,14 +134,14 @@ private Intent createOpenIntent(Bundle bundle) {
127134
public void shouldSetTitleCorrectly() throws Exception {
128135
// Should use app's Title by default
129136
Bundle bundle = getBaseNotifBundle();
130-
NotificationBundleProcessor.Process(blankActivity, bundle);
137+
OneSignalPackagePrivateHelper.NotificationBundleProcessor_ProcessFromGCMIntentService(blankActivity, bundle, null);
131138
Assert.assertEquals("UnitTestApp", ShadowRoboNotificationManager.lastNotif.getContentTitle());
132139
Assert.assertEquals(1, ShadowBadgeCountUpdater.lastCount);
133140

134141
// Should allow title from GCM payload.
135142
bundle = getBaseNotifBundle("UUID2");
136143
bundle.putString("title", "title123");
137-
NotificationBundleProcessor.Process(blankActivity, bundle);
144+
OneSignalPackagePrivateHelper.NotificationBundleProcessor_ProcessFromGCMIntentService(blankActivity, bundle, null);
138145
Assert.assertEquals("title123", ShadowRoboNotificationManager.lastNotif.getContentTitle());
139146
Assert.assertEquals(2, ShadowBadgeCountUpdater.lastCount);
140147
}
@@ -143,7 +150,7 @@ public void shouldSetTitleCorrectly() throws Exception {
143150
public void shouldHandleBasicNotifications() throws Exception {
144151
// Make sure the notification got posted and the content is correct.
145152
Bundle bundle = getBaseNotifBundle();
146-
NotificationBundleProcessor.Process(blankActivity, bundle);
153+
OneSignalPackagePrivateHelper.NotificationBundleProcessor_ProcessFromGCMIntentService(blankActivity, bundle, null);
147154
Assert.assertEquals(notifMessage, ShadowRoboNotificationManager.lastNotif.getContentText());
148155
Assert.assertEquals(1, ShadowBadgeCountUpdater.lastCount);
149156

@@ -165,14 +172,14 @@ public void shouldHandleBasicNotifications() throws Exception {
165172
int firstNotifId = cursor.getInt(1);
166173

167174
// Should not display a duplicate notification, count should still be 1
168-
NotificationBundleProcessor.Process(blankActivity, bundle);
175+
OneSignalPackagePrivateHelper.NotificationBundleProcessor_ProcessFromGCMIntentService(blankActivity, bundle, null);
169176
cursor = readableDb.query(NotificationTable.TABLE_NAME, null, null, null, null, null, null);
170177
Assert.assertEquals(1, cursor.getCount());
171178
Assert.assertEquals(0, ShadowBadgeCountUpdater.lastCount);
172179

173180
// Display a second notification
174181
bundle = getBaseNotifBundle("UUID2");
175-
NotificationBundleProcessor.Process(blankActivity, bundle);
182+
OneSignalPackagePrivateHelper.NotificationBundleProcessor_ProcessFromGCMIntentService(blankActivity, bundle, null);
176183
cursor = readableDb.query(NotificationTable.TABLE_NAME, new String[] { "android_notification_id" }, "android_notification_id <> " + firstNotifId, null, null, null, null);
177184
cursor.moveToFirst();
178185
int secondNotifId = cursor.getInt(0);
@@ -184,28 +191,29 @@ public void shouldHandleBasicNotifications() throws Exception {
184191
// Should of been added for a total of 2 records now.
185192
// First opened should of been cleaned up, 1 week old non opened notification should stay, and one new record.
186193
bundle = getBaseNotifBundle("UUID3");
187-
NotificationBundleProcessor.Process(blankActivity, bundle);
194+
OneSignalPackagePrivateHelper.NotificationBundleProcessor_ProcessFromGCMIntentService(blankActivity, bundle, null);
188195
cursor = readableDb.query(NotificationTable.TABLE_NAME, new String[] { "android_notification_id" }, null, null, null, null, null);
189196
Assert.assertEquals(2, cursor.getCount());
190197
Assert.assertEquals(2, ShadowBadgeCountUpdater.lastCount);
191198

192199
cursor.moveToFirst();
193-
boolean foundSecond = true;
200+
boolean foundSecond = false;
194201
do {
195202
Assert.assertTrue(cursor.getInt(0) != firstNotifId);
196203
if (cursor.getInt(0) == secondNotifId)
197204
foundSecond = true;
198205
} while (cursor.moveToNext());
199206

200207
Assert.assertTrue(foundSecond);
208+
cursor.close();
201209
}
202210

203211
@Test
204212
public void shouldGenerate2BasicGroupNotifications() throws Exception {
205213
// Make sure the notification got posted and the content is correct.
206214
Bundle bundle = getBaseNotifBundle();
207215
bundle.putString("grp", "test1");
208-
NotificationBundleProcessor.Process(blankActivity, bundle);
216+
OneSignalPackagePrivateHelper.NotificationBundleProcessor_ProcessFromGCMIntentService(blankActivity, bundle, null);
209217

210218
List<PostedNotification> postedNotifs = ShadowRoboNotificationManager.notifications;
211219
Assert.assertEquals(2, postedNotifs.size());
@@ -233,7 +241,7 @@ public void shouldGenerate2BasicGroupNotifications() throws Exception {
233241
bundle.putString("alert", "Notif test 2");
234242
bundle.putString("custom", "{\"i\": \"UUID2\"}");
235243
bundle.putString("grp", "test1");
236-
NotificationBundleProcessor.Process(blankActivity, bundle);
244+
OneSignalPackagePrivateHelper.NotificationBundleProcessor_ProcessFromGCMIntentService(blankActivity, bundle, null);
237245

238246
postedNotifs = ShadowRoboNotificationManager.notifications;
239247
Assert.assertEquals(2, postedNotifs.size());
@@ -263,10 +271,121 @@ public void shouldGenerate2BasicGroupNotifications() throws Exception {
263271
bundle.putString("alert", "Notif test 3");
264272
bundle.putString("custom", "{\"i\": \"UUID3\"}");
265273
bundle.putString("grp", "test1");
266-
NotificationBundleProcessor.Process(blankActivity, bundle);
274+
OneSignalPackagePrivateHelper.NotificationBundleProcessor_ProcessFromGCMIntentService(blankActivity, bundle, null);
267275

268276
Assert.assertEquals("Notif test 3", postedNotifs.get(0).notif.getContentText());
269277
Assert.assertEquals(Notification.FLAG_GROUP_SUMMARY, postedNotifs.get(0).notif.getRealNotification().flags & Notification.FLAG_GROUP_SUMMARY);
270278
Assert.assertEquals(1, ShadowBadgeCountUpdater.lastCount);
279+
cursor.close();
280+
}
281+
282+
@Test
283+
public void shouldFireNotificationExtenderService() throws Exception {
284+
Bundle bundle = getBaseNotifBundle();
285+
286+
Intent serviceIntent = new Intent();
287+
serviceIntent.setPackage("com.onesignal.example");
288+
serviceIntent.setAction("com.onesignal.NotificationExtender");
289+
ResolveInfo resolveInfo = new ResolveInfo();
290+
resolveInfo.serviceInfo = new ServiceInfo();
291+
resolveInfo.serviceInfo.name = "com.onesignal.example.NotificationExtenderServiceTest";
292+
RuntimeEnvironment.getRobolectricPackageManager().addResolveInfoForIntent(serviceIntent, resolveInfo);
293+
294+
boolean ret = OneSignalPackagePrivateHelper.GcmBroadcastReceiver_processBundle(blankActivity, bundle);
295+
Assert.assertEquals(true, ret);
296+
297+
Intent intent = Shadows.shadowOf(blankActivity).getNextStartedService();
298+
Assert.assertEquals("com.onesignal.NotificationExtender", intent.getAction());
299+
300+
ServiceController<NotificationExtenderServiceTest> controller = Robolectric.buildService(NotificationExtenderServiceTest.class);
301+
NotificationExtenderServiceTest service = controller.attach().create().get();
302+
Intent testIntent = new Intent(RuntimeEnvironment.application, NotificationExtenderServiceTest.class);
303+
testIntent.putExtras(getBundleWithAllOptionsSet());
304+
controller.withIntent(testIntent).startCommand(0, 0);
305+
306+
OSNotificationPayload notification = service.notification;
307+
Assert.assertEquals("Test H", notification.title);
308+
Assert.assertEquals("Test B", notification.message);
309+
Assert.assertEquals("9764eaeb-10ce-45b1-a66d-8f95938aaa51", notification.notificationId);
310+
311+
Assert.assertEquals(true, notification.backgroundData);
312+
Assert.assertEquals(0, notification.visibility);
313+
Assert.assertEquals("FF0000FF", notification.backgroundColor);
314+
Assert.assertEquals("703322744261", notification.fromProjectNumber);
315+
Assert.assertEquals("FFFFFF00", notification.ledColor);
316+
Assert.assertEquals("big_picture", notification.bigPicture);
317+
Assert.assertEquals("large_icon", notification.largeIcon);
318+
Assert.assertEquals("small_icon", notification.smallIcon);
319+
Assert.assertEquals("test_sound", notification.sound);
320+
Assert.assertEquals("You test $[notif_count] MSGs!", notification.groupMessage);
321+
Assert.assertEquals("http://google.com", notification.launchUrl);
322+
323+
Assert.assertEquals("id1", notification.actionButtons.get(0).id);
324+
Assert.assertEquals("button1", notification.actionButtons.get(0).text);
325+
Assert.assertEquals("ic_menu_share", notification.actionButtons.get(0).icon);
326+
Assert.assertEquals("id2", notification.actionButtons.get(1).id);
327+
Assert.assertEquals("button2", notification.actionButtons.get(1).text);
328+
Assert.assertEquals("ic_menu_send", notification.actionButtons.get(1).icon);
329+
330+
JSONObject additionalData = notification.additionalData;
331+
Assert.assertEquals("myValue", additionalData.getString("myKey"));
332+
Assert.assertEquals("nValue", additionalData.getJSONObject("nested").getString("nKey"));
333+
334+
Assert.assertNotSame(-1, service.notificationId);
335+
}
336+
337+
private static Bundle getBundleWithAllOptionsSet() {
338+
Bundle bundle = new Bundle();
339+
340+
bundle.putString("title", "Test H");
341+
bundle.putString("alert", "Test B");
342+
bundle.putString("bgn", "1");
343+
bundle.putString("vis", "0");
344+
bundle.putString("bgac", "FF0000FF");
345+
bundle.putString("from", "703322744261");
346+
bundle.putString("ledc", "FFFFFF00");
347+
bundle.putString("bicon", "big_picture");
348+
bundle.putString("licon", "large_icon");
349+
bundle.putString("sicon", "small_icon");
350+
bundle.putString("sound", "test_sound");
351+
bundle.putString("grp_msg", "You test $[notif_count] MSGs!");
352+
bundle.putString("collapse_key", "do_not_collapse");
353+
354+
355+
bundle.putString("custom",
356+
"{\"a\": {" +
357+
" \"myKey\": \"myValue\"," +
358+
" \"nested\": {\"nKey\": \"nValue\"}," +
359+
" \"actionButtons\": [{\"id\": \"id1\", \"text\": \"button1\", \"icon\": \"ic_menu_share\"}," +
360+
" {\"id\": \"id2\", \"text\": \"button2\", \"icon\": \"ic_menu_send\"}" +
361+
" ]," +
362+
" \"actionSelected\": \"__DEFAULT__\"" +
363+
" }," +
364+
"\"u\":\"http://google.com\"," +
365+
"\"i\":\"9764eaeb-10ce-45b1-a66d-8f95938aaa51\"" +
366+
"}");
367+
368+
return bundle;
369+
}
370+
371+
372+
public static class NotificationExtenderServiceTest extends NotificationExtenderService {
373+
public OSNotificationPayload notification;
374+
public int notificationId = -1;
375+
376+
// Override onStart to manually call onHandleIntent on the main thread.
377+
@Override
378+
public void onStart(Intent intent, int startId) {
379+
onHandleIntent(intent);
380+
stopSelf(startId);
381+
}
382+
383+
@Override
384+
protected boolean onNotificationProcessing(OSNotificationPayload notification) {
385+
this.notification = notification;
386+
notificationId = displayNotification(new OverrideSettings()).notificationId;
387+
388+
return true;
389+
}
271390
}
272391
}

0 commit comments

Comments
 (0)