Showing
3 changed files
with
1029 additions
and
14 deletions
... | @@ -78,22 +78,22 @@ | ... | @@ -78,22 +78,22 @@ |
78 | android:exported="false" /> | 78 | android:exported="false" /> |
79 | 79 | ||
80 | <!-- FCM Service for push notifications --> | 80 | <!-- FCM Service for push notifications --> |
81 | - <service | 81 | +<!-- <service--> |
82 | - android:name="ly.warp.sdk.services.FCMBaseMessagingService" | 82 | +<!-- android:name="ly.warp.sdk.services.FCMBaseMessagingService"--> |
83 | - android:exported="false"> | 83 | +<!-- android:exported="false">--> |
84 | - <intent-filter> | 84 | +<!-- <intent-filter>--> |
85 | - <action android:name="com.google.firebase.MESSAGING_EVENT" /> | 85 | +<!-- <action android:name="com.google.firebase.MESSAGING_EVENT" />--> |
86 | - </intent-filter> | 86 | +<!-- </intent-filter>--> |
87 | - </service> | 87 | +<!-- </service>--> |
88 | 88 | ||
89 | <!-- Service used for handling Huawei Push Notifications, comment if we are in Google build --> | 89 | <!-- Service used for handling Huawei Push Notifications, comment if we are in Google build --> |
90 | - <service | 90 | +<!-- <service--> |
91 | - android:name="ly.warp.sdk.services.HMSBaseMessagingService" | 91 | +<!-- android:name="ly.warp.sdk.services.HMSBaseMessagingService"--> |
92 | - android:exported="false"> | 92 | +<!-- android:exported="false">--> |
93 | - <intent-filter> | 93 | +<!-- <intent-filter>--> |
94 | - <action android:name="com.huawei.push.action.MESSAGING_EVENT" /> | 94 | +<!-- <action android:name="com.huawei.push.action.MESSAGING_EVENT" />--> |
95 | - </intent-filter> | 95 | +<!-- </intent-filter>--> |
96 | - </service> | 96 | +<!-- </service>--> |
97 | 97 | ||
98 | <receiver | 98 | <receiver |
99 | android:name="ly.warp.sdk.receivers.ConnectivityChangedReceiver" | 99 | android:name="ly.warp.sdk.receivers.ConnectivityChangedReceiver" | ... | ... |
1 | +package ly.warp.sdk.utils.managers; | ||
2 | + | ||
3 | +import static ly.warp.sdk.utils.constants.WarpConstants.CHANNEL_ID; | ||
4 | +import static ly.warp.sdk.utils.constants.WarpConstants.RANDOM_MAX; | ||
5 | +import static ly.warp.sdk.utils.constants.WarpConstants.RANDOM_MIN; | ||
6 | + | ||
7 | +import android.app.Notification; | ||
8 | +import android.app.NotificationChannel; | ||
9 | +import android.app.NotificationManager; | ||
10 | +import android.app.PendingIntent; | ||
11 | +import android.content.Context; | ||
12 | +import android.content.Intent; | ||
13 | +import android.content.pm.PackageManager; | ||
14 | +import android.graphics.Bitmap; | ||
15 | +import android.graphics.BitmapFactory; | ||
16 | +import android.graphics.Color; | ||
17 | +import android.media.RingtoneManager; | ||
18 | +import android.os.Build; | ||
19 | +import android.os.Bundle; | ||
20 | +import android.text.TextUtils; | ||
21 | +import android.widget.RemoteViews; | ||
22 | + | ||
23 | +import androidx.annotation.NonNull; | ||
24 | +import androidx.core.app.NotificationCompat; | ||
25 | +import androidx.work.Constraints; | ||
26 | +import androidx.work.NetworkType; | ||
27 | +import androidx.work.OneTimeWorkRequest; | ||
28 | +import androidx.work.WorkManager; | ||
29 | + | ||
30 | +import com.google.firebase.messaging.RemoteMessage; | ||
31 | + | ||
32 | +import org.apache.http.HttpStatus; | ||
33 | +import org.json.JSONException; | ||
34 | +import org.json.JSONObject; | ||
35 | + | ||
36 | +import java.io.IOException; | ||
37 | +import java.io.InputStream; | ||
38 | +import java.net.HttpURLConnection; | ||
39 | +import java.net.URL; | ||
40 | +import java.security.SecureRandom; | ||
41 | +import java.util.List; | ||
42 | +import java.util.concurrent.ThreadLocalRandom; | ||
43 | +import java.util.concurrent.TimeUnit; | ||
44 | + | ||
45 | +import ly.warp.sdk.Warply; | ||
46 | +import ly.warp.sdk.activities.WarpViewActivity; | ||
47 | +import ly.warp.sdk.io.models.PushCampaign; | ||
48 | +import ly.warp.sdk.services.PushEventsWorkerService; | ||
49 | +import ly.warp.sdk.utils.WarpUtils; | ||
50 | +import ly.warp.sdk.utils.WarplyProperty; | ||
51 | + | ||
52 | +/** | ||
53 | + * Delegate class for handling Firebase Cloud Messaging (FCM) push notifications. | ||
54 | + * This class allows client apps with existing FCM implementations to integrate Warply push handling. | ||
55 | + * | ||
56 | + * Usage: | ||
57 | + * 1. Create an instance in your FirebaseMessagingService | ||
58 | + * 2. Call handleMessage() from onMessageReceived() | ||
59 | + * 3. Call handleNewToken() from onNewToken() | ||
60 | + */ | ||
61 | +public class WarplyFCMPushDelegate { | ||
62 | + | ||
63 | + // =========================================================== | ||
64 | + // Constants | ||
65 | + // =========================================================== | ||
66 | + | ||
67 | + private static final String KEY_TITLE = "alert"; | ||
68 | + private static final String KEY_SUBTITLE = "subtitle"; | ||
69 | + private static final String KEY_TICKER = "alert"; | ||
70 | + private static final String KEY_MESSAGE = "message"; | ||
71 | + private static final String KEY_PAYLOAD = "payload"; | ||
72 | + | ||
73 | + // =========================================================== | ||
74 | + // Fields | ||
75 | + // =========================================================== | ||
76 | + | ||
77 | + private final Context context; | ||
78 | + | ||
79 | + // =========================================================== | ||
80 | + // Constructors | ||
81 | + // =========================================================== | ||
82 | + | ||
83 | + /** | ||
84 | + * Creates a new WarplyFCMPushDelegate | ||
85 | + * @param context Application context | ||
86 | + */ | ||
87 | + public WarplyFCMPushDelegate(@NonNull Context context) { | ||
88 | + this.context = context; | ||
89 | + } | ||
90 | + | ||
91 | + // =========================================================== | ||
92 | + // Public Methods | ||
93 | + // =========================================================== | ||
94 | + | ||
95 | + /** | ||
96 | + * Call this method from your FirebaseMessagingService.onMessageReceived() | ||
97 | + * @param remoteMessage The FCM message | ||
98 | + * @return true if message was handled by Warply, false if it should be processed by your app | ||
99 | + */ | ||
100 | + public boolean handleMessage(@NonNull RemoteMessage remoteMessage) { | ||
101 | + Bundle data = remoteMessage.toIntent().getExtras(); | ||
102 | + | ||
103 | + // Check if this message is for Warply | ||
104 | + if (data == null || !data.containsKey("loyalty-action")) { | ||
105 | + return false; // Not a Warply message, let the client handle it | ||
106 | + } | ||
107 | + | ||
108 | + // This is a Warply message, process it | ||
109 | + PushCampaign pc = new PushCampaign(data); | ||
110 | + | ||
111 | + // Set up analytics tracking | ||
112 | + setUpPushEvents(pc); | ||
113 | + | ||
114 | + WarpUtils.log("Warply received push with action: " + pc.getAction()); | ||
115 | + if (pc.getAction() == 0 && !pc.hasActions()) { | ||
116 | + showCampaignNotification(context, pc); | ||
117 | + } else { | ||
118 | + showDefaultNotification(context, data); | ||
119 | + } | ||
120 | + | ||
121 | + return true; // Message was handled by Warply | ||
122 | + } | ||
123 | + | ||
124 | + /** | ||
125 | + * Call this method from your FirebaseMessagingService.onNewToken() | ||
126 | + * @param token The new FCM token | ||
127 | + */ | ||
128 | + public void handleNewToken(@NonNull String token) { | ||
129 | + WarpUtils.setDeviceToken(context, token); | ||
130 | + } | ||
131 | + | ||
132 | + // =========================================================== | ||
133 | + // Private Methods | ||
134 | + // =========================================================== | ||
135 | + | ||
136 | + private void setUpPushEvents(PushCampaign pc) { | ||
137 | + Warply.getInitializer(context).init(); | ||
138 | + WarplyAnalyticsManager.logUserReceivedPush(pc); | ||
139 | + | ||
140 | + Constraints constraints = new Constraints.Builder() | ||
141 | + .setRequiredNetworkType(NetworkType.CONNECTED) | ||
142 | + .build(); | ||
143 | + | ||
144 | + OneTimeWorkRequest sendEvent = new OneTimeWorkRequest.Builder(PushEventsWorkerService.class) | ||
145 | + .setConstraints(constraints) | ||
146 | + .setInitialDelay(defineRandomStart(), TimeUnit.MINUTES) | ||
147 | + .build(); | ||
148 | + | ||
149 | + WorkManager.getInstance(context).enqueue(sendEvent); | ||
150 | + } | ||
151 | + | ||
152 | + private int defineRandomStart() { | ||
153 | + if (Build.VERSION.SDK_INT >= 21) { | ||
154 | + return ThreadLocalRandom.current().nextInt(RANDOM_MIN, RANDOM_MAX + 1); | ||
155 | + } else { | ||
156 | + SecureRandom rand = new SecureRandom(); | ||
157 | + return rand.nextInt((RANDOM_MAX - RANDOM_MIN) + 1) + RANDOM_MIN; | ||
158 | + } | ||
159 | + } | ||
160 | + | ||
161 | + // =========================================================== | ||
162 | + // Notification Methods | ||
163 | + // =========================================================== | ||
164 | + | ||
165 | + /** | ||
166 | + * Shows a campaign notification | ||
167 | + */ | ||
168 | + private void showCampaignNotification(Context context, PushCampaign pc) { | ||
169 | + showCampaignNotification(context, pc, null); | ||
170 | + } | ||
171 | + | ||
172 | + /** | ||
173 | + * Shows a campaign notification with actions | ||
174 | + */ | ||
175 | + private void showCampaignNotification(Context context, PushCampaign pc, List<NotificationCompat.Action> actions) { | ||
176 | + showCampaignNotification(context, pc, null, null); | ||
177 | + } | ||
178 | + | ||
179 | + /** | ||
180 | + * Shows a campaign notification with actions and custom view | ||
181 | + */ | ||
182 | + private void showCampaignNotification(Context context, PushCampaign pc, List<NotificationCompat.Action> actions, RemoteViews remoteViews) { | ||
183 | + WarpUtils.log("Showing campaign with session UUID: " + pc.getSessionUUID()); | ||
184 | + | ||
185 | + SecureRandom randomGenerator = new SecureRandom(); | ||
186 | + | ||
187 | + int uid = randomGenerator.nextInt(1000); | ||
188 | + if (!TextUtils.isEmpty(pc.getSessionUUID())) { | ||
189 | + uid = 0; | ||
190 | + } | ||
191 | + | ||
192 | + Intent newIntent = WarpViewActivity.createIntentFromSessionUUID( | ||
193 | + context, pc.getSessionUUID(), "from_notification_status"); | ||
194 | + newIntent.setAction(Long.toString(System.currentTimeMillis())); | ||
195 | + | ||
196 | + NotificationCompat.Builder b = new NotificationCompat.Builder(context, CHANNEL_ID); | ||
197 | + | ||
198 | + if (pc.getNotificationStyle().equalsIgnoreCase(PushCampaign.NOTIFICATION_STYLE_BIG_PICTURE) | ||
199 | + && !TextUtils.isEmpty(pc.getBigPictureUrl())) { | ||
200 | + //get big picture style | ||
201 | + NotificationCompat.BigPictureStyle bigPictureStyle = new NotificationCompat.BigPictureStyle(); | ||
202 | + bigPictureStyle.bigPicture(loadDrawable(pc.getBigPictureUrl())); | ||
203 | + if (!TextUtils.isEmpty(pc.getSubtitle())) { | ||
204 | + bigPictureStyle.setSummaryText(pc.getSubtitle()); | ||
205 | + } | ||
206 | + b.setStyle(bigPictureStyle); | ||
207 | + } else if (pc.getNotificationStyle().equalsIgnoreCase(PushCampaign.NOTIFICATION_STYLE_BIG_TEXT) | ||
208 | + && !TextUtils.isEmpty(pc.getBigText())) { | ||
209 | + //get big picture style | ||
210 | + NotificationCompat.BigTextStyle bigTextStyle = new NotificationCompat.BigTextStyle(); | ||
211 | + bigTextStyle.bigText(pc.getBigText()); | ||
212 | + if (!TextUtils.isEmpty(pc.getSummaryText())) { | ||
213 | + bigTextStyle.setSummaryText(pc.getSummaryText()); | ||
214 | + } | ||
215 | + | ||
216 | + b.setStyle(bigTextStyle); | ||
217 | + } else if (pc.getNotificationStyle().equalsIgnoreCase(PushCampaign.NOTIFICATION_STYLE_INBOX_STYLE)) { | ||
218 | + NotificationCompat.InboxStyle inboxStyle = new NotificationCompat.InboxStyle(); | ||
219 | + for (int i = 0; i < pc.getInboxLines().size(); i++) { | ||
220 | + inboxStyle.addLine(pc.getInboxLines().get(i)); | ||
221 | + } | ||
222 | + if (!TextUtils.isEmpty(pc.getSummaryText())) { | ||
223 | + inboxStyle.setSummaryText(pc.getSummaryText()); | ||
224 | + } | ||
225 | + b.setStyle(inboxStyle); | ||
226 | + } | ||
227 | + | ||
228 | + b.setDefaults(Notification.DEFAULT_VIBRATE | Notification.DEFAULT_LIGHTS); | ||
229 | + b.setTicker(pc.getTicker()); | ||
230 | + b.setChannelId(CHANNEL_ID); | ||
231 | + b.setContentTitle(pc.getTitle()); | ||
232 | + b.setContentText(pc.getSubtitle()); | ||
233 | + b.setSubText(pc.getContent()); | ||
234 | + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { | ||
235 | + b.setContentIntent(PendingIntent.getActivity(context, uid, newIntent, PendingIntent.FLAG_ONE_SHOT | PendingIntent.FLAG_MUTABLE)); | ||
236 | + } else { | ||
237 | + b.setContentIntent(PendingIntent.getActivity(context, uid, newIntent, PendingIntent.FLAG_ONE_SHOT)); | ||
238 | + } | ||
239 | + b.setAutoCancel(true); | ||
240 | + b.setOngoing(true); | ||
241 | + b.setAutoCancel(true); | ||
242 | + b.setSmallIcon(WarplyProperty.getPushIconResId(context)); | ||
243 | + b.setLargeIcon(loadDrawable(pc.getImageUrl())); | ||
244 | + | ||
245 | + //Add remote view as content if exists | ||
246 | + if (remoteViews != null) { | ||
247 | + b.setContent(remoteViews); | ||
248 | + } | ||
249 | + | ||
250 | + if (pc.getSoundUri(context) == null) | ||
251 | + b.setSound(RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION)); | ||
252 | + else | ||
253 | + b.setSound(pc.getSoundUri(context)); | ||
254 | + | ||
255 | + | ||
256 | + //If push has color | ||
257 | + int color = WarplyProperty.getPushColor(context); | ||
258 | + if (!TextUtils.isEmpty(pc.getColor())) { | ||
259 | + try { | ||
260 | + color = Color.parseColor(pc.getColor()); | ||
261 | + } catch (IllegalArgumentException iae) { | ||
262 | + iae.printStackTrace(); | ||
263 | + } | ||
264 | + } | ||
265 | + b.setColor(color); | ||
266 | + | ||
267 | + //add actions | ||
268 | + if (actions != null) { | ||
269 | + if (actions.size() > 0) { | ||
270 | + for (NotificationCompat.Action action : actions) { | ||
271 | + b.addAction(action); | ||
272 | + } | ||
273 | + } | ||
274 | + } | ||
275 | + | ||
276 | + NotificationManager nm = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); | ||
277 | + | ||
278 | + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && nm != null) { | ||
279 | + NotificationChannel notificationChannel = new NotificationChannel(CHANNEL_ID, "notification_channel", NotificationManager.IMPORTANCE_DEFAULT); | ||
280 | + nm.createNotificationChannel(notificationChannel); | ||
281 | + Notification notification_build_with_largeicon = b.setChannelId(CHANNEL_ID).build(); | ||
282 | + notification_build_with_largeicon.flags = Notification.FLAG_AUTO_CANCEL; //notification with only large icon due to the two build notificaition is not canceled from bar | ||
283 | + nm.notify(pc.getSessionUUID(), uid, notification_build_with_largeicon); | ||
284 | + } else { | ||
285 | + Notification notification_build_with_largeicon = b.build(); | ||
286 | + notification_build_with_largeicon.flags = Notification.FLAG_AUTO_CANCEL; //notification with only large icon due to the two build notificaition is not canceled from bar | ||
287 | + if (nm != null) { | ||
288 | + nm.notify(pc.getSessionUUID(), uid, notification_build_with_largeicon); | ||
289 | + } | ||
290 | + } | ||
291 | + } | ||
292 | + | ||
293 | + /** | ||
294 | + * Shows a default notification for the app | ||
295 | + */ | ||
296 | + private void showDefaultNotification(Context context, Bundle data) { | ||
297 | + String title = getNotificationTitle(data); | ||
298 | + String ticker = getNotificationTicker(data); | ||
299 | + String message = getNotificationMessage(data); | ||
300 | + | ||
301 | + PushCampaign pc = new PushCampaign(data); | ||
302 | + | ||
303 | + if (pc != null) { | ||
304 | + PackageManager pm = context.getPackageManager(); | ||
305 | + Intent newIntent = pm.getLaunchIntentForPackage(context.getPackageName()); | ||
306 | + | ||
307 | + showNotification(context, pc, newIntent, null, null, null, 0); | ||
308 | + } | ||
309 | + } | ||
310 | + | ||
311 | + /** | ||
312 | + * Shows a notification with custom parameters | ||
313 | + */ | ||
314 | + private void showNotification(Context context, PushCampaign pc, Intent newIntent, List<NotificationCompat.Action> actions, RemoteViews remoteViews, String tag, int id) { | ||
315 | + SecureRandom randomGenerator = new SecureRandom(); | ||
316 | + int uid = randomGenerator.nextInt(1000); | ||
317 | + if (id > 0) { | ||
318 | + uid = id; | ||
319 | + } | ||
320 | + WarpUtils.log("Showing notification with tag: " + tag + " and id: " + id); | ||
321 | + | ||
322 | + NotificationCompat.Builder b = new NotificationCompat.Builder(context, CHANNEL_ID); | ||
323 | + | ||
324 | + if (pc.getNotificationStyle().equalsIgnoreCase(PushCampaign.NOTIFICATION_STYLE_BIG_PICTURE) | ||
325 | + && !TextUtils.isEmpty(pc.getBigPictureUrl())) { | ||
326 | + //get big picture style | ||
327 | + NotificationCompat.BigPictureStyle bigPictureStyle = new NotificationCompat.BigPictureStyle(); | ||
328 | + bigPictureStyle.bigPicture(loadDrawable(pc.getBigPictureUrl())); | ||
329 | + if (!TextUtils.isEmpty(pc.getSubtitle())) { | ||
330 | + bigPictureStyle.setSummaryText(pc.getSubtitle()); | ||
331 | + } | ||
332 | + b.setStyle(bigPictureStyle); | ||
333 | + } else if (pc.getNotificationStyle().equalsIgnoreCase(PushCampaign.NOTIFICATION_STYLE_BIG_TEXT) | ||
334 | + && !TextUtils.isEmpty(pc.getBigText())) { | ||
335 | + //get big picture style | ||
336 | + NotificationCompat.BigTextStyle bigTextStyle = new NotificationCompat.BigTextStyle(); | ||
337 | + bigTextStyle.bigText(pc.getBigText()); | ||
338 | + if (!TextUtils.isEmpty(pc.getSummaryText())) { | ||
339 | + bigTextStyle.setSummaryText(pc.getSummaryText()); | ||
340 | + } | ||
341 | + | ||
342 | + b.setStyle(bigTextStyle); | ||
343 | + } else if (pc.getNotificationStyle().equalsIgnoreCase(PushCampaign.NOTIFICATION_STYLE_INBOX_STYLE)) { | ||
344 | + NotificationCompat.InboxStyle inboxStyle = new NotificationCompat.InboxStyle(); | ||
345 | + for (int i = 0; i < pc.getInboxLines().size(); i++) { | ||
346 | + inboxStyle.addLine(pc.getInboxLines().get(i)); | ||
347 | + } | ||
348 | + if (!TextUtils.isEmpty(pc.getSummaryText())) { | ||
349 | + inboxStyle.setSummaryText(pc.getSummaryText()); | ||
350 | + } | ||
351 | + b.setStyle(inboxStyle); | ||
352 | + } | ||
353 | + | ||
354 | + b.setDefaults(Notification.DEFAULT_VIBRATE | Notification.DEFAULT_LIGHTS); | ||
355 | + b.setTicker(pc.getTicker()); | ||
356 | + b.setChannelId(CHANNEL_ID); | ||
357 | + b.setContentTitle(pc.getTitle()); | ||
358 | + b.setContentText(pc.getSubtitle()); | ||
359 | + b.setSubText(pc.getContent()); | ||
360 | + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { | ||
361 | + b.setContentIntent(PendingIntent.getActivity(context, uid, newIntent, PendingIntent.FLAG_ONE_SHOT | PendingIntent.FLAG_MUTABLE)); | ||
362 | + } else { | ||
363 | + b.setContentIntent(PendingIntent.getActivity(context, uid, newIntent, PendingIntent.FLAG_ONE_SHOT)); | ||
364 | + } | ||
365 | + b.setAutoCancel(true); | ||
366 | + b.setOngoing(true); | ||
367 | + b.setAutoCancel(true); | ||
368 | + b.setSmallIcon(WarplyProperty.getPushIconResId(context)); | ||
369 | + b.setLargeIcon(loadDrawable(pc.getImageUrl())); | ||
370 | + | ||
371 | + if (remoteViews != null) { | ||
372 | + b.setContent(remoteViews); | ||
373 | + } | ||
374 | + | ||
375 | + if (pc.getSoundUri(context) == null) | ||
376 | + b.setSound(RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION)); | ||
377 | + else | ||
378 | + b.setSound(pc.getSoundUri(context)); | ||
379 | + | ||
380 | + //If push has color | ||
381 | + int color = WarplyProperty.getPushColor(context); | ||
382 | + if (!TextUtils.isEmpty(pc.getColor())) { | ||
383 | + try { | ||
384 | + color = Color.parseColor(pc.getColor()); | ||
385 | + } catch (IllegalArgumentException iae) { | ||
386 | + iae.printStackTrace(); | ||
387 | + } | ||
388 | + } | ||
389 | + b.setColor(color); | ||
390 | + | ||
391 | + //add actions | ||
392 | + if (actions != null) { | ||
393 | + if (actions.size() > 0) { | ||
394 | + for (NotificationCompat.Action action : actions) { | ||
395 | + b.addAction(action); | ||
396 | + } | ||
397 | + } | ||
398 | + } | ||
399 | + | ||
400 | + newIntent.setAction(Long.toString(System.currentTimeMillis())); | ||
401 | + PendingIntent pi; | ||
402 | + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { | ||
403 | + pi = PendingIntent.getActivity(context, uid, newIntent, PendingIntent.FLAG_ONE_SHOT | PendingIntent.FLAG_MUTABLE); | ||
404 | + } else { | ||
405 | + pi = PendingIntent.getActivity(context, uid, newIntent, PendingIntent.FLAG_ONE_SHOT); | ||
406 | + } | ||
407 | + b.setContentIntent(pi); | ||
408 | + | ||
409 | + NotificationManager nm = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); | ||
410 | + | ||
411 | + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && nm != null) { | ||
412 | + NotificationChannel notificationChannel = new NotificationChannel(CHANNEL_ID, "notification_channel", NotificationManager.IMPORTANCE_DEFAULT); | ||
413 | + nm.createNotificationChannel(notificationChannel); | ||
414 | + Notification notification_build = b.setChannelId(CHANNEL_ID).build(); | ||
415 | + notification_build.flags = Notification.FLAG_AUTO_CANCEL; | ||
416 | + nm.notify(pc.getSessionUUID(), uid, notification_build); | ||
417 | + } else { | ||
418 | + Notification notification_build = b.build(); | ||
419 | + notification_build.flags = Notification.FLAG_AUTO_CANCEL; | ||
420 | + if (nm != null) { | ||
421 | + nm.notify(pc.getSessionUUID(), uid, notification_build); | ||
422 | + } | ||
423 | + } | ||
424 | + } | ||
425 | + | ||
426 | + // =========================================================== | ||
427 | + // Helper Methods | ||
428 | + // =========================================================== | ||
429 | + | ||
430 | + public JSONObject getPayload(Bundle data) { | ||
431 | + String payloadStr = data.getString(KEY_PAYLOAD); | ||
432 | + try { | ||
433 | + JSONObject payload = new JSONObject(payloadStr); | ||
434 | + return payload; | ||
435 | + } catch (JSONException e) { | ||
436 | + WarpUtils.log("Error with payload", e); | ||
437 | + return null; | ||
438 | + } | ||
439 | + } | ||
440 | + | ||
441 | + public String getNotificationTitle(Bundle data) { | ||
442 | + return data.getString(KEY_TITLE); | ||
443 | + } | ||
444 | + | ||
445 | + public String getNotificationMessage(Bundle data) { | ||
446 | + return data.getString(KEY_MESSAGE); | ||
447 | + } | ||
448 | + | ||
449 | + public String getNotificationTicker(Bundle data) { | ||
450 | + return data.getString(KEY_TICKER); | ||
451 | + } | ||
452 | + | ||
453 | + public String getNotificationSubtitle(Bundle data) { | ||
454 | + return data.getString(KEY_SUBTITLE); | ||
455 | + } | ||
456 | + | ||
457 | + private static Bitmap loadDrawable(String urlString) { | ||
458 | + if (urlString == null || TextUtils.isEmpty(urlString)) | ||
459 | + return null; | ||
460 | + | ||
461 | + URL url; | ||
462 | + HttpURLConnection urlConnection = null; | ||
463 | + try { | ||
464 | + url = new URL(urlString); | ||
465 | + urlConnection = (HttpURLConnection) url.openConnection(); | ||
466 | + | ||
467 | + if (!(urlConnection.getResponseCode() == HttpStatus.SC_OK)) | ||
468 | + return null; | ||
469 | + | ||
470 | + InputStream is = urlConnection.getInputStream(); | ||
471 | + if (is == null) { | ||
472 | + urlConnection.disconnect(); | ||
473 | + return null; | ||
474 | + } | ||
475 | + | ||
476 | + Bitmap b = BitmapFactory.decodeStream(is); | ||
477 | + is.close(); | ||
478 | + urlConnection.disconnect(); | ||
479 | + return b; | ||
480 | + | ||
481 | + } catch (IOException e) { | ||
482 | + return null; | ||
483 | + } | ||
484 | + } | ||
485 | +} |
1 | +package ly.warp.sdk.utils.managers; | ||
2 | + | ||
3 | +import static ly.warp.sdk.utils.constants.WarpConstants.CHANNEL_ID; | ||
4 | +import static ly.warp.sdk.utils.constants.WarpConstants.RANDOM_MAX; | ||
5 | +import static ly.warp.sdk.utils.constants.WarpConstants.RANDOM_MIN; | ||
6 | + | ||
7 | +import android.app.Notification; | ||
8 | +import android.app.NotificationChannel; | ||
9 | +import android.app.NotificationManager; | ||
10 | +import android.app.PendingIntent; | ||
11 | +import android.content.Context; | ||
12 | +import android.content.Intent; | ||
13 | +import android.content.pm.PackageManager; | ||
14 | +import android.graphics.Bitmap; | ||
15 | +import android.graphics.BitmapFactory; | ||
16 | +import android.graphics.Color; | ||
17 | +import android.media.RingtoneManager; | ||
18 | +import android.os.Build; | ||
19 | +import android.os.Bundle; | ||
20 | +import android.text.TextUtils; | ||
21 | +import android.widget.RemoteViews; | ||
22 | + | ||
23 | +import androidx.annotation.NonNull; | ||
24 | +import androidx.core.app.NotificationCompat; | ||
25 | +import androidx.work.Constraints; | ||
26 | +import androidx.work.NetworkType; | ||
27 | +import androidx.work.OneTimeWorkRequest; | ||
28 | +import androidx.work.WorkManager; | ||
29 | + | ||
30 | +import com.huawei.hms.push.RemoteMessage; | ||
31 | + | ||
32 | +import org.apache.http.HttpStatus; | ||
33 | +import org.json.JSONException; | ||
34 | +import org.json.JSONObject; | ||
35 | + | ||
36 | +import java.io.InputStream; | ||
37 | +import java.net.HttpURLConnection; | ||
38 | +import java.net.URL; | ||
39 | +import java.security.SecureRandom; | ||
40 | +import java.util.Iterator; | ||
41 | +import java.util.List; | ||
42 | +import java.util.concurrent.ThreadLocalRandom; | ||
43 | +import java.util.concurrent.TimeUnit; | ||
44 | + | ||
45 | +import ly.warp.sdk.Warply; | ||
46 | +import ly.warp.sdk.activities.WarpViewActivity; | ||
47 | +import ly.warp.sdk.io.models.PushCampaign; | ||
48 | +import ly.warp.sdk.services.PushEventsWorkerService; | ||
49 | +import ly.warp.sdk.utils.WarpUtils; | ||
50 | +import ly.warp.sdk.utils.WarplyProperty; | ||
51 | + | ||
52 | +/** | ||
53 | + * Delegate class for handling Huawei Mobile Services (HMS) push notifications. | ||
54 | + * This class allows client apps with existing HMS implementations to integrate Warply push handling. | ||
55 | + * | ||
56 | + * Usage: | ||
57 | + * 1. Create an instance in your HmsMessageService | ||
58 | + * 2. Call handleMessage() from onMessageReceived() | ||
59 | + * 3. Call handleNewToken() from onNewToken() | ||
60 | + */ | ||
61 | +public class WarplyHMSPushDelegate { | ||
62 | + | ||
63 | + // =========================================================== | ||
64 | + // Constants | ||
65 | + // =========================================================== | ||
66 | + | ||
67 | + private static final String KEY_TITLE = "alert"; | ||
68 | + private static final String KEY_SUBTITLE = "subtitle"; | ||
69 | + private static final String KEY_TICKER = "alert"; | ||
70 | + private static final String KEY_MESSAGE = "message"; | ||
71 | + private static final String KEY_PAYLOAD = "payload"; | ||
72 | + | ||
73 | + // =========================================================== | ||
74 | + // Fields | ||
75 | + // =========================================================== | ||
76 | + | ||
77 | + private final Context context; | ||
78 | + private static Bitmap bFinal = null; | ||
79 | + | ||
80 | + // =========================================================== | ||
81 | + // URLThread class | ||
82 | + // =========================================================== | ||
83 | + public static class URLThread extends Thread { | ||
84 | + private String urlString = ""; | ||
85 | + | ||
86 | + public URLThread(String url) { | ||
87 | + this.urlString = url; | ||
88 | + } | ||
89 | + | ||
90 | + @Override | ||
91 | + public void run() { | ||
92 | + try { | ||
93 | + URL url; | ||
94 | + HttpURLConnection urlConnection = null; | ||
95 | + url = new URL(urlString); | ||
96 | + urlConnection = (HttpURLConnection) url.openConnection(); | ||
97 | + if (!(urlConnection.getResponseCode() == HttpStatus.SC_OK)) { | ||
98 | + bFinal = null; | ||
99 | + return; | ||
100 | + } | ||
101 | + InputStream is = urlConnection.getInputStream(); | ||
102 | + if (is == null) { | ||
103 | + urlConnection.disconnect(); | ||
104 | + bFinal = null; | ||
105 | + return; | ||
106 | + } | ||
107 | + Bitmap b = BitmapFactory.decodeStream(is); | ||
108 | + is.close(); | ||
109 | + urlConnection.disconnect(); | ||
110 | + bFinal = b; | ||
111 | + } catch (Exception ex) { | ||
112 | + bFinal = null; | ||
113 | + ex.printStackTrace(); | ||
114 | + } | ||
115 | + } | ||
116 | + } | ||
117 | + | ||
118 | + // =========================================================== | ||
119 | + // Constructors | ||
120 | + // =========================================================== | ||
121 | + | ||
122 | + /** | ||
123 | + * Creates a new WarplyHMSPushDelegate | ||
124 | + * @param context Application context | ||
125 | + */ | ||
126 | + public WarplyHMSPushDelegate(@NonNull Context context) { | ||
127 | + this.context = context; | ||
128 | + } | ||
129 | + | ||
130 | + // =========================================================== | ||
131 | + // Public Methods | ||
132 | + // =========================================================== | ||
133 | + | ||
134 | + /** | ||
135 | + * Call this method from your HmsMessageService.onMessageReceived() | ||
136 | + * @param remoteMessage The HMS message | ||
137 | + * @return true if message was handled by Warply, false if it should be processed by your app | ||
138 | + */ | ||
139 | + public boolean handleMessage(@NonNull RemoteMessage remoteMessage) { | ||
140 | + JSONObject data = new JSONObject(remoteMessage.getDataOfMap()); | ||
141 | + | ||
142 | + // Check if this message is for Warply | ||
143 | + if (data == null || !data.has("loyalty-action")) { | ||
144 | + return false; // Not a Warply message, let the client handle it | ||
145 | + } | ||
146 | + | ||
147 | + // This is a Warply message, process it | ||
148 | + PushCampaign pc = new PushCampaign(data); | ||
149 | + | ||
150 | + // Set up analytics tracking | ||
151 | + setUpPushEvents(pc); | ||
152 | + | ||
153 | + WarpUtils.log("Warply received push with action: " + pc.getAction()); | ||
154 | + if (pc.getAction() == 0 && !pc.hasActions()) { | ||
155 | + showCampaignNotification(context, pc); | ||
156 | + } else { | ||
157 | + Bundle bundledData = null; | ||
158 | + try { | ||
159 | + bundledData = jsonToBundle(data); | ||
160 | + } catch (JSONException e) { | ||
161 | + e.printStackTrace(); | ||
162 | + } | ||
163 | + showDefaultNotification(context, bundledData); | ||
164 | + } | ||
165 | + | ||
166 | + return true; // Message was handled by Warply | ||
167 | + } | ||
168 | + | ||
169 | + /** | ||
170 | + * Call this method from your HmsMessageService.onNewToken() | ||
171 | + * @param token The new HMS token | ||
172 | + */ | ||
173 | + public void handleNewToken(@NonNull String token) { | ||
174 | + WarpUtils.setDeviceToken(context, token); | ||
175 | + } | ||
176 | + | ||
177 | + // =========================================================== | ||
178 | + // Private Methods | ||
179 | + // =========================================================== | ||
180 | + | ||
181 | + private void setUpPushEvents(PushCampaign pc) { | ||
182 | + Warply.getInitializer(context).init(); | ||
183 | + WarplyAnalyticsManager.logUserReceivedPush(pc); | ||
184 | + | ||
185 | + Constraints constraints = new Constraints.Builder() | ||
186 | + .setRequiredNetworkType(NetworkType.CONNECTED) | ||
187 | + .build(); | ||
188 | + | ||
189 | + OneTimeWorkRequest sendEvent = new OneTimeWorkRequest.Builder(PushEventsWorkerService.class) | ||
190 | + .setConstraints(constraints) | ||
191 | + .setInitialDelay(defineRandomStart(), TimeUnit.MINUTES) | ||
192 | + .build(); | ||
193 | + | ||
194 | + WorkManager.getInstance(context).enqueue(sendEvent); | ||
195 | + } | ||
196 | + | ||
197 | + private int defineRandomStart() { | ||
198 | + if (Build.VERSION.SDK_INT >= 21) { | ||
199 | + return ThreadLocalRandom.current().nextInt(RANDOM_MIN, RANDOM_MAX + 1); | ||
200 | + } else { | ||
201 | + SecureRandom rand = new SecureRandom(); | ||
202 | + return rand.nextInt((RANDOM_MAX - RANDOM_MIN) + 1) + RANDOM_MIN; | ||
203 | + } | ||
204 | + } | ||
205 | + | ||
206 | + // =========================================================== | ||
207 | + // Notification Methods | ||
208 | + // =========================================================== | ||
209 | + | ||
210 | + /** | ||
211 | + * Shows a campaign notification | ||
212 | + */ | ||
213 | + private void showCampaignNotification(Context context, PushCampaign pc) { | ||
214 | + showCampaignNotification(context, pc, null); | ||
215 | + } | ||
216 | + | ||
217 | + /** | ||
218 | + * Shows a campaign notification with actions | ||
219 | + */ | ||
220 | + private void showCampaignNotification(Context context, PushCampaign pc, List<NotificationCompat.Action> actions) { | ||
221 | + showCampaignNotification(context, pc, null, null); | ||
222 | + } | ||
223 | + | ||
224 | + /** | ||
225 | + * Shows a campaign notification with actions and custom view | ||
226 | + */ | ||
227 | + private void showCampaignNotification(Context context, PushCampaign pc, List<NotificationCompat.Action> actions, RemoteViews remoteViews) { | ||
228 | + WarpUtils.log("Showing campaign with session UUID: " + pc.getSessionUUID()); | ||
229 | + | ||
230 | + SecureRandom randomGenerator = new SecureRandom(); | ||
231 | + | ||
232 | + int uid = randomGenerator.nextInt(1000); | ||
233 | + if (!TextUtils.isEmpty(pc.getSessionUUID())) { | ||
234 | + uid = 0; | ||
235 | + } | ||
236 | + | ||
237 | + Intent newIntent = WarpViewActivity.createIntentFromSessionUUID( | ||
238 | + context, pc.getSessionUUID(), "from_notification_status"); | ||
239 | + newIntent.setAction(Long.toString(System.currentTimeMillis())); | ||
240 | + | ||
241 | + NotificationCompat.Builder b = new NotificationCompat.Builder(context, CHANNEL_ID); | ||
242 | + | ||
243 | + if (pc.getNotificationStyle().equalsIgnoreCase(PushCampaign.NOTIFICATION_STYLE_BIG_PICTURE) | ||
244 | + && !TextUtils.isEmpty(pc.getBigPictureUrl())) { | ||
245 | + //get big picture style | ||
246 | + NotificationCompat.BigPictureStyle bigPictureStyle = new NotificationCompat.BigPictureStyle(); | ||
247 | + bigPictureStyle.bigPicture(loadDrawable(pc.getBigPictureUrl())); | ||
248 | + if (!TextUtils.isEmpty(pc.getSubtitle())) { | ||
249 | + bigPictureStyle.setSummaryText(pc.getSubtitle()); | ||
250 | + } | ||
251 | + b.setStyle(bigPictureStyle); | ||
252 | + } else if (pc.getNotificationStyle().equalsIgnoreCase(PushCampaign.NOTIFICATION_STYLE_BIG_TEXT) | ||
253 | + && !TextUtils.isEmpty(pc.getBigText())) { | ||
254 | + //get big picture style | ||
255 | + NotificationCompat.BigTextStyle bigTextStyle = new NotificationCompat.BigTextStyle(); | ||
256 | + bigTextStyle.bigText(pc.getBigText()); | ||
257 | + if (!TextUtils.isEmpty(pc.getSummaryText())) { | ||
258 | + bigTextStyle.setSummaryText(pc.getSummaryText()); | ||
259 | + } | ||
260 | + | ||
261 | + b.setStyle(bigTextStyle); | ||
262 | + } else if (pc.getNotificationStyle().equalsIgnoreCase(PushCampaign.NOTIFICATION_STYLE_INBOX_STYLE)) { | ||
263 | + NotificationCompat.InboxStyle inboxStyle = new NotificationCompat.InboxStyle(); | ||
264 | + for (int i = 0; i < pc.getInboxLines().size(); i++) { | ||
265 | + inboxStyle.addLine(pc.getInboxLines().get(i)); | ||
266 | + } | ||
267 | + if (!TextUtils.isEmpty(pc.getSummaryText())) { | ||
268 | + inboxStyle.setSummaryText(pc.getSummaryText()); | ||
269 | + } | ||
270 | + b.setStyle(inboxStyle); | ||
271 | + } | ||
272 | + | ||
273 | + b.setDefaults(Notification.DEFAULT_VIBRATE | Notification.DEFAULT_LIGHTS); | ||
274 | + b.setTicker(pc.getTicker()); | ||
275 | + b.setChannelId(CHANNEL_ID); | ||
276 | + b.setContentTitle(pc.getTitle()); | ||
277 | + b.setContentText(pc.getSubtitle()); | ||
278 | + b.setSubText(pc.getContent()); | ||
279 | + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { | ||
280 | + b.setContentIntent(PendingIntent.getActivity(context, uid, newIntent, PendingIntent.FLAG_ONE_SHOT | PendingIntent.FLAG_MUTABLE)); | ||
281 | + } else { | ||
282 | + b.setContentIntent(PendingIntent.getActivity(context, uid, newIntent, PendingIntent.FLAG_ONE_SHOT)); | ||
283 | + } | ||
284 | + b.setAutoCancel(true); | ||
285 | + b.setOngoing(true); | ||
286 | + b.setAutoCancel(true); | ||
287 | + b.setSmallIcon(WarplyProperty.getPushIconResId(context)); | ||
288 | + b.setLargeIcon(loadDrawable(pc.getImageUrl())); | ||
289 | + | ||
290 | + //Add remote view as content if exists | ||
291 | + if (remoteViews != null) { | ||
292 | + b.setContent(remoteViews); | ||
293 | + } | ||
294 | + | ||
295 | + if (pc.getSoundUri(context) == null) | ||
296 | + b.setSound(RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION)); | ||
297 | + else | ||
298 | + b.setSound(pc.getSoundUri(context)); | ||
299 | + | ||
300 | + | ||
301 | + //If push has color | ||
302 | + int color = WarplyProperty.getPushColor(context); | ||
303 | + if (!TextUtils.isEmpty(pc.getColor())) { | ||
304 | + try { | ||
305 | + color = Color.parseColor(pc.getColor()); | ||
306 | + } catch (IllegalArgumentException iae) { | ||
307 | + iae.printStackTrace(); | ||
308 | + } | ||
309 | + } | ||
310 | + b.setColor(color); | ||
311 | + | ||
312 | + //add actions | ||
313 | + if (actions != null) { | ||
314 | + if (actions.size() > 0) { | ||
315 | + for (NotificationCompat.Action action : actions) { | ||
316 | + b.addAction(action); | ||
317 | + } | ||
318 | + } | ||
319 | + } | ||
320 | + | ||
321 | + NotificationManager nm = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); | ||
322 | + | ||
323 | + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && nm != null) { | ||
324 | + NotificationChannel notificationChannel = new NotificationChannel(CHANNEL_ID, "notification_channel", NotificationManager.IMPORTANCE_DEFAULT); | ||
325 | + nm.createNotificationChannel(notificationChannel); | ||
326 | + Notification notification_build_with_largeicon = b.setChannelId(CHANNEL_ID).build(); | ||
327 | + notification_build_with_largeicon.flags = Notification.FLAG_AUTO_CANCEL; //notification with only large icon due to the two build notificaition is not canceled from bar | ||
328 | + nm.notify(pc.getSessionUUID(), uid, notification_build_with_largeicon); | ||
329 | + } else { | ||
330 | + Notification notification_build_with_largeicon = b.build(); | ||
331 | + notification_build_with_largeicon.flags = Notification.FLAG_AUTO_CANCEL; //notification with only large icon due to the two build notificaition is not canceled from bar | ||
332 | + if (nm != null) { | ||
333 | + nm.notify(pc.getSessionUUID(), uid, notification_build_with_largeicon); | ||
334 | + } | ||
335 | + } | ||
336 | + } | ||
337 | + | ||
338 | + /** | ||
339 | + * Shows a default notification for the app | ||
340 | + */ | ||
341 | + private void showDefaultNotification(Context context, Bundle data) { | ||
342 | + String title = getNotificationTitle(data); | ||
343 | + String ticker = getNotificationTicker(data); | ||
344 | + String message = getNotificationMessage(data); | ||
345 | + | ||
346 | + PushCampaign pc = new PushCampaign(data); | ||
347 | + | ||
348 | + if (pc != null) { | ||
349 | + PackageManager pm = context.getPackageManager(); | ||
350 | + Intent newIntent = pm.getLaunchIntentForPackage(context.getPackageName()); | ||
351 | + | ||
352 | + showNotification(context, pc, newIntent, null, null, null, 0); | ||
353 | + } | ||
354 | + } | ||
355 | + | ||
356 | + /** | ||
357 | + * Shows a notification with custom parameters | ||
358 | + */ | ||
359 | + private void showNotification(Context context, PushCampaign pc, Intent newIntent, List<NotificationCompat.Action> actions, RemoteViews remoteViews, String tag, int id) { | ||
360 | + SecureRandom randomGenerator = new SecureRandom(); | ||
361 | + int uid = randomGenerator.nextInt(1000); | ||
362 | + if (id > 0) { | ||
363 | + uid = id; | ||
364 | + } | ||
365 | + WarpUtils.log("Showing notification with tag: " + tag + " and id: " + id); | ||
366 | + | ||
367 | + NotificationCompat.Builder b = new NotificationCompat.Builder(context, CHANNEL_ID); | ||
368 | + | ||
369 | + if (pc.getNotificationStyle().equalsIgnoreCase(PushCampaign.NOTIFICATION_STYLE_BIG_PICTURE) | ||
370 | + && !TextUtils.isEmpty(pc.getBigPictureUrl())) { | ||
371 | + //get big picture style | ||
372 | + NotificationCompat.BigPictureStyle bigPictureStyle = new NotificationCompat.BigPictureStyle(); | ||
373 | + bigPictureStyle.bigPicture(loadDrawable(pc.getBigPictureUrl())); | ||
374 | + if (!TextUtils.isEmpty(pc.getSubtitle())) { | ||
375 | + bigPictureStyle.setSummaryText(pc.getSubtitle()); | ||
376 | + } | ||
377 | + b.setStyle(bigPictureStyle); | ||
378 | + } else if (pc.getNotificationStyle().equalsIgnoreCase(PushCampaign.NOTIFICATION_STYLE_BIG_TEXT) | ||
379 | + && !TextUtils.isEmpty(pc.getBigText())) { | ||
380 | + //get big picture style | ||
381 | + NotificationCompat.BigTextStyle bigTextStyle = new NotificationCompat.BigTextStyle(); | ||
382 | + bigTextStyle.bigText(pc.getBigText()); | ||
383 | + if (!TextUtils.isEmpty(pc.getSummaryText())) { | ||
384 | + bigTextStyle.setSummaryText(pc.getSummaryText()); | ||
385 | + } | ||
386 | + | ||
387 | + b.setStyle(bigTextStyle); | ||
388 | + } else if (pc.getNotificationStyle().equalsIgnoreCase(PushCampaign.NOTIFICATION_STYLE_INBOX_STYLE)) { | ||
389 | + NotificationCompat.InboxStyle inboxStyle = new NotificationCompat.InboxStyle(); | ||
390 | + for (int i = 0; i < pc.getInboxLines().size(); i++) { | ||
391 | + inboxStyle.addLine(pc.getInboxLines().get(i)); | ||
392 | + } | ||
393 | + if (!TextUtils.isEmpty(pc.getSummaryText())) { | ||
394 | + inboxStyle.setSummaryText(pc.getSummaryText()); | ||
395 | + } | ||
396 | + b.setStyle(inboxStyle); | ||
397 | + } | ||
398 | + | ||
399 | + b.setDefaults(Notification.DEFAULT_VIBRATE | Notification.DEFAULT_LIGHTS); | ||
400 | + b.setTicker(pc.getTicker()); | ||
401 | + b.setChannelId(CHANNEL_ID); | ||
402 | + b.setContentTitle(pc.getTitle()); | ||
403 | + b.setContentText(pc.getSubtitle()); | ||
404 | + b.setSubText(pc.getContent()); | ||
405 | + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { | ||
406 | + b.setContentIntent(PendingIntent.getActivity(context, uid, newIntent, PendingIntent.FLAG_ONE_SHOT | PendingIntent.FLAG_MUTABLE)); | ||
407 | + } else { | ||
408 | + b.setContentIntent(PendingIntent.getActivity(context, uid, newIntent, PendingIntent.FLAG_ONE_SHOT)); | ||
409 | + } | ||
410 | + b.setAutoCancel(true); | ||
411 | + b.setOngoing(true); | ||
412 | + b.setAutoCancel(true); | ||
413 | + b.setSmallIcon(WarplyProperty.getPushIconResId(context)); | ||
414 | + b.setLargeIcon(loadDrawable(pc.getImageUrl())); | ||
415 | + | ||
416 | + if (remoteViews != null) { | ||
417 | + b.setContent(remoteViews); | ||
418 | + } | ||
419 | + | ||
420 | + if (pc.getSoundUri(context) == null) | ||
421 | + b.setSound(RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION)); | ||
422 | + else | ||
423 | + b.setSound(pc.getSoundUri(context)); | ||
424 | + | ||
425 | + //If push has color | ||
426 | + int color = WarplyProperty.getPushColor(context); | ||
427 | + if (!TextUtils.isEmpty(pc.getColor())) { | ||
428 | + try { | ||
429 | + color = Color.parseColor(pc.getColor()); | ||
430 | + } catch (IllegalArgumentException iae) { | ||
431 | + iae.printStackTrace(); | ||
432 | + } | ||
433 | + } | ||
434 | + b.setColor(color); | ||
435 | + | ||
436 | + //add actions | ||
437 | + if (actions != null) { | ||
438 | + if (actions.size() > 0) { | ||
439 | + for (NotificationCompat.Action action : actions) { | ||
440 | + b.addAction(action); | ||
441 | + } | ||
442 | + } | ||
443 | + } | ||
444 | + | ||
445 | + newIntent.setAction(Long.toString(System.currentTimeMillis())); | ||
446 | + PendingIntent pi; | ||
447 | + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { | ||
448 | + pi = PendingIntent.getActivity(context, uid, newIntent, PendingIntent.FLAG_ONE_SHOT | PendingIntent.FLAG_MUTABLE); | ||
449 | + } else { | ||
450 | + pi = PendingIntent.getActivity(context, uid, newIntent, PendingIntent.FLAG_ONE_SHOT); | ||
451 | + } | ||
452 | + b.setContentIntent(pi); | ||
453 | + | ||
454 | + NotificationManager nm = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); | ||
455 | + | ||
456 | + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && nm != null) { | ||
457 | + NotificationChannel notificationChannel = new NotificationChannel(CHANNEL_ID, "notification_channel", NotificationManager.IMPORTANCE_DEFAULT); | ||
458 | + nm.createNotificationChannel(notificationChannel); | ||
459 | + Notification notification_build = b.setChannelId(CHANNEL_ID).build(); | ||
460 | + notification_build.flags = Notification.FLAG_AUTO_CANCEL; | ||
461 | + nm.notify(pc.getSessionUUID(), uid, notification_build); | ||
462 | + } else { | ||
463 | + Notification notification_build = b.build(); | ||
464 | + notification_build.flags = Notification.FLAG_AUTO_CANCEL; | ||
465 | + if (nm != null) { | ||
466 | + nm.notify(pc.getSessionUUID(), uid, notification_build); | ||
467 | + } | ||
468 | + } | ||
469 | + } | ||
470 | + | ||
471 | + // =========================================================== | ||
472 | + // Helper Methods | ||
473 | + // =========================================================== | ||
474 | + | ||
475 | + public JSONObject getPayload(Bundle data) { | ||
476 | + String payloadStr = data.getString(KEY_PAYLOAD); | ||
477 | + try { | ||
478 | + JSONObject payload = new JSONObject(payloadStr); | ||
479 | + return payload; | ||
480 | + } catch (JSONException e) { | ||
481 | + WarpUtils.log("Error with payload", e); | ||
482 | + return null; | ||
483 | + } | ||
484 | + } | ||
485 | + | ||
486 | + public String getNotificationTitle(Bundle data) { | ||
487 | + return data.getString(KEY_TITLE); | ||
488 | + } | ||
489 | + | ||
490 | + public String getNotificationMessage(Bundle data) { | ||
491 | + return data.getString(KEY_MESSAGE); | ||
492 | + } | ||
493 | + | ||
494 | + public String getNotificationTicker(Bundle data) { | ||
495 | + return data.getString(KEY_TICKER); | ||
496 | + } | ||
497 | + | ||
498 | + public String getNotificationSubtitle(Bundle data) { | ||
499 | + return data.getString(KEY_SUBTITLE); | ||
500 | + } | ||
501 | + | ||
502 | + private static Bitmap loadDrawable(final String urlString) { | ||
503 | + if (urlString == null || TextUtils.isEmpty(urlString)) | ||
504 | + return null; | ||
505 | + | ||
506 | + URLThread urlThread = new URLThread(urlString); | ||
507 | + try { | ||
508 | + urlThread.start(); | ||
509 | + urlThread.join(); | ||
510 | + } catch (InterruptedException e) { | ||
511 | + e.printStackTrace(); | ||
512 | + } | ||
513 | + | ||
514 | + return bFinal; | ||
515 | + } | ||
516 | + | ||
517 | + /** | ||
518 | + * Convert a JSONObject to a Bundle | ||
519 | + */ | ||
520 | + public static Bundle jsonToBundle(JSONObject jsonObject) throws JSONException { | ||
521 | + Bundle bundle = new Bundle(); | ||
522 | + Iterator<String> iter = jsonObject.keys(); | ||
523 | + while (iter.hasNext()) { | ||
524 | + String key = iter.next(); | ||
525 | + String value = jsonObject.getString(key); | ||
526 | + bundle.putString(key, value); | ||
527 | + } | ||
528 | + return bundle; | ||
529 | + } | ||
530 | +} |
-
Please register or login to post a comment