Skip to content

Commit 4e3bc33

Browse files
committed
add FCM support, largeImage, multiline push
1 parent 91b1126 commit 4e3bc33

File tree

4 files changed

+136
-9
lines changed

4 files changed

+136
-9
lines changed
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
package io.neson.react.notification;
2+
3+
import android.content.Intent;
4+
import android.os.Bundle;
5+
import android.util.Log;
6+
import com.google.gson.Gson;
7+
import org.mozilla.javascript.*;
8+
import java.util.Map;
9+
import com.google.firebase.messaging.FirebaseMessagingService;
10+
import com.google.firebase.messaging.RemoteMessage;
11+
import io.neson.react.notification.NotificationAttributes;
12+
13+
public class FCMNotificationListenerService extends FirebaseMessagingService {
14+
15+
private static final String TAG = "FCMNotificationListenerService";
16+
// This is compressed manually from the encodeNativeNotification function
17+
// in index.js
18+
// https://skalman.github.io/UglifyJS-online/
19+
private static final String NOTIFICATION_ATTRIBUTES_JS_PARSING_CODE = "function encodeNativeNotification(e){if(\"string\"==typeof e&&(e=JSON.parse(e)),e.smallIcon||(e.smallIcon=\"ic_launcher\"),e.id||(e.id=parseInt(1e5*Math.random())),e.action||(e.action=\"DEFAULT\"),e.payload||(e.payload={}),void 0===e.autoClear&&(e.autoClear=!0),void 0===e.tickerText&&(e.tickerText=e.subject?e.subject+\": \"+e.message:e.message),void 0===e.priority&&(e.priority=1),void 0===e.sound&&(e.sound=\"default\"),void 0===e.vibrate&&(e.vibrate=\"default\"),void 0===e.lights&&(e.lights=\"default\"),e.delayed=void 0!==e.delay,e.scheduled=void 0!==e.sendAt,e.sendAt&&\"object\"!=typeof e.sendAt&&(e.sendAt=new Date(e.sendAt)),e.endAt&&\"object\"!=typeof e.endAt&&(e.endAt=new Date(e.endAt)),e.when&&\"object\"!=typeof e.when&&(e.when=new Date(e.when)),void 0!==e.sendAt&&(e.sendAtYear=e.sendAt.getFullYear(),e.sendAtMonth=e.sendAt.getMonth()+1,e.sendAtDay=e.sendAt.getDate(),e.sendAtWeekDay=e.sendAt.getDay(),e.sendAtHour=e.sendAt.getHours(),e.sendAtMinute=e.sendAt.getMinutes()),e.sendAt&&(e.sendAt=e.sendAt.getTime()),e.endAt&&(e.endAt=e.endAt.getTime()),e.when&&(e.when=e.when.getTime()),void 0!==e.sendAt&&(\"number\"==typeof e.repeatEvery?(e.repeatType=\"time\",e.repeatTime=e.repeatEvery):\"string\"==typeof e.repeatEvery&&(e.repeatType=e.repeatEvery),e.repeatCount))if(\"number\"==typeof e.repeatEvery)e.endAt=parseInt(e.sendAt+e.repeatEvery*e.repeatCount+e.repeatEvery/2);else if(\"string\"==typeof e.repeatEvery)switch(e.repeatEvery){case\"minute\":e.endAt=e.sendAt+6e4*e.repeatCount+3e4;break;case\"hour\":e.endAt=e.sendAt+36e5*e.repeatCount+18e5;break;case\"halfDay\":e.endAt=e.sendAt+432e5*e.repeatCount+216e5;break;case\"day\":e.endAt=e.sendAt+864e5*e.repeatCount+432e5;break;case\"week\":e.endAt=e.sendAt+6048e5*e.repeatCount+2592e5;break;case\"month\":e.endAt=e.sendAt+2592e6*e.repeatCount+1296e6;break;case\"year\":e.endAt=e.sendAt+31536e6*e.repeatCount+864e7}return e.sendAt&&(e.sendAt=\"\"+e.sendAt),e.endAt&&(e.endAt=\"\"+e.endAt),e.when&&(e.when=\"\"+e.when),e.repeatEvery&&(e.repeatEvery=\"\"+e.repeatEvery),e.progress&&(e.progress=1e3*e.progress),e.payload=JSON.stringify(e.payload),e}";
20+
21+
@Override
22+
public void onMessageReceived(RemoteMessage remoteMessage) {
23+
sendNotification(remoteMessage);
24+
25+
Map<String, String> data = remoteMessage.getData();
26+
String notificationString = data.get("notification");
27+
28+
29+
if (notificationString != null) {
30+
sendSysNotification(notificationString);
31+
}
32+
}
33+
34+
private void sendNotification(RemoteMessage remoteMessage) {
35+
Log.d(TAG, "sendNotification");
36+
37+
Intent i = new Intent("com.evollu.react.fcm.ReceiveNotification");
38+
i.putExtra("data", remoteMessage);
39+
sendOrderedBroadcast(i, null);
40+
}
41+
42+
private void sendSysNotification(String notificationString) {
43+
Object[] functionParams = new Object[] { notificationString };
44+
45+
Context rhino = Context.enter();
46+
rhino.setOptimizationLevel(-1);
47+
48+
Scriptable scope = rhino.initStandardObjects();
49+
50+
rhino.evaluateString(scope, NOTIFICATION_ATTRIBUTES_JS_PARSING_CODE, "script", 1, null);
51+
52+
Function function = (Function) scope.get("encodeNativeNotification", scope);
53+
54+
Object parsedParams = function.call(rhino, scope, scope, functionParams);
55+
56+
Gson gson = new Gson();
57+
String parsedParamsJson = gson.toJson(parsedParams);
58+
59+
Log.d(TAG, "Notification parsedParams: " + parsedParamsJson);
60+
61+
NotificationAttributes notificationAttributes = new NotificationAttributes();
62+
notificationAttributes.loadFromMap((Map) parsedParams);
63+
64+
NotificationManager nm = new NotificationManager(this);
65+
nm.create(notificationAttributes.id, notificationAttributes);
66+
}
67+
}

android/src/main/java/io/neson/react/notification/Notification.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,17 @@ public android.app.Notification build() {
130130
notificationBuilder.setPriority(attributes.priority);
131131
}
132132

133+
if (attributes.largeIcon != null) {
134+
int largeIconId = context.getResources().getIdentifier(attributes.largeIcon, "drawable", context.getPackageName());
135+
Bitmap largeIcon = BitmapFactory.decodeResource(context.getResources(), largeIconId);
136+
notificationBuilder.setLargeIcon(largeIcon);
137+
}
138+
139+
if (attributes.group != null) {
140+
notificationBuilder.setGroup(attributes.group);
141+
notificationBuilder.setGroupSummary(true);
142+
}
143+
133144
if(attributes.inboxStyle){
134145

135146
android.support.v7.app.NotificationCompat.InboxStyle inboxStyle = new android.support.v7.app.NotificationCompat.InboxStyle();
@@ -145,6 +156,8 @@ public android.app.Notification build() {
145156
inboxStyle.addLine(Html.fromHtml(attributes.inboxStyleLines.get(i)));
146157
}
147158
}
159+
notificationBuilder.setStyle(inboxStyle);
160+
148161

149162
Log.i("ReactSystemNotification", "set inbox style!!");
150163

@@ -233,6 +246,8 @@ else if (attributes.bigStyleImageBase64 != null) {
233246
notificationBuilder.setSound(Uri.parse(attributes.sound));
234247
}
235248

249+
250+
236251
return notificationBuilder.build();
237252
}
238253

android/src/main/java/io/neson/react/notification/NotificationAttributes.java

Lines changed: 52 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,13 @@
44
import com.facebook.react.bridge.ReadableMap;
55
import com.facebook.react.bridge.WritableArray;
66
import com.facebook.react.bridge.WritableMap;
7+
import com.facebook.react.bridge.ReadableNativeArray;
8+
79

810
import java.util.ArrayList;
911
import java.util.Map;
1012
import java.util.Iterator;
1113

12-
import com.facebook.react.bridge.WritableNativeMap;
1314
import com.google.gson.Gson;
1415

1516
public class NotificationAttributes {
@@ -51,6 +52,8 @@ public class NotificationAttributes {
5152
public String bigStyleImageBase64;
5253
public String subText;
5354
public Integer progress;
55+
public Integer lifetime;
56+
public Integer progressEnd;
5457
public String color;
5558
public Integer number;
5659
public String category;
@@ -61,6 +64,8 @@ public class NotificationAttributes {
6164
public String inboxStyleSummaryText;
6265
public ArrayList<String> inboxStyleLines;
6366

67+
public String group;
68+
6469
public void loadFromMap(Map map) {
6570
WritableMap writableMap = (WritableMap) new WritableNativeMap();
6671

@@ -83,6 +88,34 @@ public void loadFromMap(Map map) {
8388

8489
} else if (value.getClass().equals(Boolean.class)) {
8590
writableMap.putBoolean(key, (Boolean) value);
91+
92+
93+
} else if ("inboxStyle".equals(key)) {
94+
inboxStyle = true;
95+
WritableMap inboxStyleMap = new WritableNativeMap();
96+
97+
Map inboxMap = (Map) value;
98+
if (inboxMap.containsKey("bigContentTitle")) {
99+
inboxStyleBigContentTitle = (String) inboxMap.get("bigContentTitle");
100+
inboxStyleMap.putString("bigContentTitle", inboxStyleBigContentTitle);
101+
}
102+
103+
if (inboxMap.containsKey("summaryText")) {
104+
inboxStyleSummaryText = (String) inboxMap.get("summaryText");
105+
inboxStyleMap.putString("summaryText", inboxStyleSummaryText);
106+
}
107+
108+
if (inboxMap.containsKey("lines")) {
109+
WritableArray inboxLines = new com.facebook.react.bridge.WritableNativeArray();
110+
org.mozilla.javascript.NativeArray inboxStyleLines = (org.mozilla.javascript.NativeArray) inboxMap.get("lines");
111+
112+
for(int i=0; i < inboxStyleLines.size(); i++){
113+
inboxLines.pushString((String) inboxStyleLines.get(i));
114+
}
115+
inboxStyleMap.putArray("lines", inboxLines);
116+
}
117+
118+
writableMap.putMap("inboxStyle", inboxStyleMap);
86119

87120
} else {
88121
Gson gson = new Gson();
@@ -134,22 +167,28 @@ public void loadFromReadableMap(ReadableMap readableMap) {
134167
if (readableMap.hasKey("bigStyleImageBase64")) bigStyleImageBase64 = readableMap.getString("bigStyleImageBase64");
135168
if (readableMap.hasKey("subText")) subText = readableMap.getString("subText");
136169
if (readableMap.hasKey("progress")) progress = readableMap.getInt("progress");
170+
if (readableMap.hasKey("progressEnd")) progressEnd = readableMap.getInt("progressEnd");
171+
if (readableMap.hasKey("lifetime")) lifetime = readableMap.getInt("lifetime");
172+
137173
if (readableMap.hasKey("color")) color = readableMap.getString("color");
138174
if (readableMap.hasKey("number")) number = readableMap.getInt("number");
139175
if (readableMap.hasKey("category")) category = readableMap.getString("category");
140176
if (readableMap.hasKey("localOnly")) localOnly = readableMap.getBoolean("localOnly");
177+
if (readableMap.hasKey("group")) group = readableMap.getString("group");
141178

142179
if (readableMap.hasKey("inboxStyle")){
143180
inboxStyle = true;
144-
ReadableMap inboxStyle = readableMap.getMap("inboxStyle");
181+
ReadableMap inboxStyleMap = readableMap.getMap("inboxStyle");
145182

146-
inboxStyleBigContentTitle = inboxStyle.getString("bigContentTitle");
147-
inboxStyleSummaryText = inboxStyle.getString("summaryText");
183+
inboxStyleBigContentTitle = inboxStyleMap.getString("bigContentTitle");
184+
inboxStyleSummaryText = inboxStyleMap.getString("summaryText");
148185

149-
ReadableArray inboxLines = inboxStyle.getArray("lines");
150-
inboxStyleLines = new ArrayList<>();
151-
for(int i=0; i < inboxLines.size(); i++){
152-
inboxStyleLines.add(inboxLines.getString(i));
186+
ReadableArray inboxLines = inboxStyleMap.getArray("lines");
187+
if (inboxLines != null) {
188+
inboxStyleLines = new ArrayList<>();
189+
for(int i=0; i < inboxLines.size(); i++){
190+
inboxStyleLines.add(inboxLines.getString(i));
191+
}
153192
}
154193
}else{
155194
inboxStyle = false;
@@ -202,10 +241,14 @@ public ReadableMap asReadableMap() {
202241
if (number != null) writableMap.putInt("number", number);
203242
if (category != null) writableMap.putString("category", category);
204243
if (localOnly != null) writableMap.putBoolean("localOnly", localOnly);
244+
if (group != null) writableMap.putString("group", group);
245+
246+
if (progressEnd != null) writableMap.putInt("progressEnd", progressEnd);
247+
if (lifetime != null) writableMap.putInt("lifetime", lifetime);
205248

206249
if (inboxStyle){
207250

208-
WritableMap inboxStyle = new com.facebook.react.bridge.WritableNativeMap();
251+
WritableMap inboxStyle = new WritableNativeMap();
209252

210253
if (inboxStyleBigContentTitle != null) inboxStyle.putString("bigContentTitle", inboxStyleBigContentTitle);
211254
if (inboxStyleSummaryText != null) inboxStyle.putString("summaryText", inboxStyleSummaryText);

android/src/main/java/io/neson/react/notification/NotificationModule.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import com.facebook.react.bridge.ReadableArray;
2020
import com.facebook.react.bridge.WritableArray;
2121
import com.facebook.react.bridge.WritableNativeArray;
22+
import com.facebook.react.bridge.LifecycleEventListener;
2223

2324
import io.neson.react.notification.NotificationManager;
2425
import io.neson.react.notification.Notification;
@@ -299,4 +300,5 @@ public void onReceive(Context context, Intent intent) {
299300
}
300301
}, intentFilter);
301302
}
303+
302304
}

0 commit comments

Comments
 (0)