Skip to content

Commit 91928f8

Browse files
authored
Notification Open should use Activity instead of Broadcast (#1192)
* Notification Open should use Activity instead of Broadcast * Switch to using NotificationOpenedActivity.class in GenerateNotification.java * Remove Intent flags from startOrResumeApp and use Activity Context instead of the normal context * Update tests to account for the new behavior * Handle delete intent with broadcast receiver * Using activities for handling delete can end on some weird behavior on the UI
1 parent 93d255c commit 91928f8

File tree

8 files changed

+124
-103
lines changed

8 files changed

+124
-103
lines changed

OneSignalSDK/onesignal/src/main/AndroidManifest.xml

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -71,8 +71,10 @@
7171
</intent-filter>
7272
</service>
7373

74-
<activity android:name="com.onesignal.NotificationOpenedActivityHMS"
75-
android:theme="@android:style/Theme.Translucent.NoTitleBar">
74+
<activity
75+
android:name="com.onesignal.NotificationOpenedActivityHMS"
76+
android:noHistory="true"
77+
android:theme="@android:style/Theme.Translucent.NoTitleBar">
7678
<intent-filter>
7779
<action android:name="android.intent.action.VIEW" />
7880
</intent-filter>
@@ -100,7 +102,7 @@
100102
<activity android:name="com.onesignal.PermissionsActivity"
101103
android:theme="@android:style/Theme.Translucent.NoTitleBar" />
102104

103-
<receiver android:name="com.onesignal.NotificationOpenedReceiver" />
105+
<receiver android:name="com.onesignal.NotificationDismissReceiver" />
104106

105107
<receiver android:name="com.onesignal.BootUpReceiver">
106108
<intent-filter>
@@ -114,7 +116,10 @@
114116
</intent-filter>
115117
</receiver>
116118

117-
<activity android:name="com.onesignal.NotificationOpenedActivity"/>
119+
<activity
120+
android:name="com.onesignal.NotificationOpenedReceiver"
121+
android:noHistory="true"
122+
android:theme="@android:style/Theme.Translucent.NoTitleBar" />
118123

119124
</application>
120125

OneSignalSDK/onesignal/src/main/java/com/onesignal/GenerateNotification.java

Lines changed: 26 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@
3333
import android.content.ContentValues;
3434
import android.content.Context;
3535
import android.content.Intent;
36-
import android.content.pm.PackageManager;
3736
import android.content.res.Resources;
3837
import android.database.Cursor;
3938
import android.graphics.Bitmap;
@@ -78,11 +77,11 @@ class GenerateNotification {
7877
// notification Intent.
7978
public static final String BUNDLE_KEY_ONESIGNAL_DATA = "onesignalData";
8079

80+
private static Class<?> notificationOpenedClass = NotificationOpenedReceiver.class;
81+
private static Class<?> notificationDismissedClass = NotificationDismissReceiver.class;
82+
private static Resources contextResources = null;
8183
private static Context currentContext = null;
8284
private static String packageName = null;
83-
private static Resources contextResources = null;
84-
private static Class<?> notificationOpenedClass;
85-
private static boolean openerIsBroadcast;
8685

8786
private static class OneSignalNotificationBuilder {
8887
NotificationCompat.Builder compatBuilder;
@@ -93,16 +92,6 @@ private static void setStatics(Context inContext) {
9392
currentContext = inContext;
9493
packageName = currentContext.getPackageName();
9594
contextResources = currentContext.getResources();
96-
97-
PackageManager packageManager = currentContext.getPackageManager();
98-
Intent intent = new Intent(currentContext, NotificationOpenedReceiver.class);
99-
intent.setPackage(currentContext.getPackageName());
100-
if (packageManager.queryBroadcastReceivers(intent, 0).size() > 0) {
101-
openerIsBroadcast = true;
102-
notificationOpenedClass = NotificationOpenedReceiver.class;
103-
}
104-
else
105-
notificationOpenedClass = NotificationOpenedActivity.class;
10695
}
10796

10897
@WorkerThread
@@ -132,29 +121,29 @@ private static CharSequence getTitle(JSONObject fcmJson) {
132121
return currentContext.getPackageManager().getApplicationLabel(currentContext.getApplicationInfo());
133122
}
134123

124+
125+
/**
126+
* Notification delete is processed by Broadcast Receiver to avoid creation of activities that can end
127+
* on weird UI interaction
128+
*/
135129
private static PendingIntent getNewActionPendingIntent(int requestCode, Intent intent) {
136-
if (openerIsBroadcast)
137-
return PendingIntent.getBroadcast(currentContext, requestCode, intent, PendingIntent.FLAG_UPDATE_CURRENT);
138130
return PendingIntent.getActivity(currentContext, requestCode, intent, PendingIntent.FLAG_UPDATE_CURRENT);
139131
}
140132

141-
private static Intent getNewBaseIntent(int notificationId) {
142-
Intent intent = new Intent(currentContext, notificationOpenedClass)
143-
.putExtra(BUNDLE_KEY_ANDROID_NOTIFICATION_ID, notificationId);
144-
145-
if (openerIsBroadcast)
146-
return intent;
147-
return intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP);
133+
private static PendingIntent getNewDismissActionPendingIntent(int requestCode, Intent intent) {
134+
return PendingIntent.getBroadcast(currentContext, requestCode, intent, PendingIntent.FLAG_UPDATE_CURRENT);
148135
}
149136

150-
private static Intent getNewBaseDeleteIntent(int notificationId) {
151-
Intent intent = new Intent(currentContext, notificationOpenedClass)
152-
.putExtra(BUNDLE_KEY_ANDROID_NOTIFICATION_ID, notificationId)
153-
.putExtra("dismissed", true);
137+
private static Intent getNewBaseIntent(int notificationId) {
138+
return new Intent(currentContext, notificationOpenedClass)
139+
.putExtra(BUNDLE_KEY_ANDROID_NOTIFICATION_ID, notificationId)
140+
.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP);
141+
}
154142

155-
if (openerIsBroadcast)
156-
return intent;
157-
return intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_MULTIPLE_TASK | Intent.FLAG_ACTIVITY_NO_ANIMATION);
143+
private static Intent getNewBaseDismissIntent(int notificationId) {
144+
return new Intent(currentContext, notificationDismissedClass)
145+
.putExtra(BUNDLE_KEY_ANDROID_NOTIFICATION_ID, notificationId)
146+
.putExtra("dismissed", true);
158147
}
159148

160149
private static OneSignalNotificationBuilder getBaseOneSignalNotificationBuilder(OSNotificationGenerationJob notificationJob) {
@@ -324,10 +313,9 @@ private static void showNotification(OSNotificationGenerationJob notificationJob
324313
createGrouplessSummaryNotification(notificationJob, grouplessNotifs.size() + 1);
325314
else
326315
createSummaryNotification(notificationJob, oneSignalNotificationBuilder);
327-
}
328-
else
316+
} else {
329317
notification = createGenericPendingIntentsForNotif(notifBuilder, fcmJson, notificationId);
330-
318+
}
331319
// NotificationManagerCompat does not auto omit the individual notification on the device when using
332320
// stacked notifications on Android 4.2 and older
333321
// The benefits of calling notify for individual notifications in-addition to the summary above it is shows
@@ -344,7 +332,7 @@ private static Notification createGenericPendingIntentsForNotif(NotificationComp
344332
Random random = new SecureRandom();
345333
PendingIntent contentIntent = getNewActionPendingIntent(random.nextInt(), getNewBaseIntent(notificationId).putExtra(BUNDLE_KEY_ONESIGNAL_DATA, gcmBundle.toString()));
346334
notifBuilder.setContentIntent(contentIntent);
347-
PendingIntent deleteIntent = getNewActionPendingIntent(random.nextInt(), getNewBaseDeleteIntent(notificationId));
335+
PendingIntent deleteIntent = getNewDismissActionPendingIntent(random.nextInt(), getNewBaseDismissIntent(notificationId));
348336
notifBuilder.setDeleteIntent(deleteIntent);
349337
return notifBuilder.build();
350338
}
@@ -353,14 +341,13 @@ private static void createGenericPendingIntentsForGroup(NotificationCompat.Build
353341
Random random = new SecureRandom();
354342
PendingIntent contentIntent = getNewActionPendingIntent(random.nextInt(), getNewBaseIntent(notificationId).putExtra(BUNDLE_KEY_ONESIGNAL_DATA, gcmBundle.toString()).putExtra("grp", group));
355343
notifBuilder.setContentIntent(contentIntent);
356-
PendingIntent deleteIntent = getNewActionPendingIntent(random.nextInt(), getNewBaseDeleteIntent(notificationId).putExtra("grp", group));
344+
PendingIntent deleteIntent = getNewDismissActionPendingIntent(random.nextInt(), getNewBaseDismissIntent(notificationId).putExtra("grp", group));
357345
notifBuilder.setDeleteIntent(deleteIntent);
358346
notifBuilder.setGroup(group);
359347

360348
try {
361349
notifBuilder.setGroupAlertBehavior(NotificationCompat.GROUP_ALERT_SUMMARY);
362-
}
363-
catch (Throwable t) {
350+
} catch (Throwable t) {
364351
//do nothing in this case...Android support lib 26 isn't in the project
365352
}
366353
}
@@ -457,7 +444,7 @@ private static void createSummaryNotification(OSNotificationGenerationJob notifi
457444
String group = fcmJson.optString("grp", null);
458445

459446
SecureRandom random = new SecureRandom();
460-
PendingIntent summaryDeleteIntent = getNewActionPendingIntent(random.nextInt(), getNewBaseDeleteIntent(0).putExtra("summary", group));
447+
PendingIntent summaryDeleteIntent = getNewDismissActionPendingIntent(random.nextInt(), getNewBaseDismissIntent(0).putExtra("summary", group));
461448

462449
Notification summaryNotification;
463450
Integer summaryNotificationId = null;
@@ -660,7 +647,7 @@ private static void createGrouplessSummaryNotification(OSNotificationGenerationJ
660647
int summaryNotificationId = OneSignalNotificationManager.getGrouplessSummaryId();
661648

662649
PendingIntent summaryContentIntent = getNewActionPendingIntent(random.nextInt(), createBaseSummaryIntent(summaryNotificationId, fcmJson, group));
663-
PendingIntent summaryDeleteIntent = getNewActionPendingIntent(random.nextInt(), getNewBaseDeleteIntent(0).putExtra("summary", group));
650+
PendingIntent summaryDeleteIntent = getNewDismissActionPendingIntent(random.nextInt(), getNewBaseDismissIntent(0).putExtra("summary", group));
664651

665652
NotificationCompat.Builder summaryBuilder = getBaseOneSignalNotificationBuilder(notificationJob).compatBuilder;
666653
if (notificationJob.getOverriddenSound() != null)
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
1-
/**
2-
* Modified MIT License
3-
*
1+
/*
42
* Copyright 2017 OneSignal
53
*
64
* Permission is hereby granted, free of charge, to any person obtaining a copy
@@ -27,25 +25,14 @@
2725

2826
package com.onesignal;
2927

30-
import android.app.Activity;
28+
import android.content.BroadcastReceiver;
29+
import android.content.Context;
3130
import android.content.Intent;
32-
import android.os.Bundle;
33-
34-
public class NotificationOpenedActivity extends Activity {
35-
36-
@Override
37-
protected void onCreate(Bundle savedInstanceState) {
38-
super.onCreate(savedInstanceState);
39-
NotificationOpenedProcessor.processFromContext(this, getIntent());
40-
finish();
41-
}
42-
43-
@Override
44-
protected void onNewIntent(Intent intent) {
45-
super.onNewIntent(intent);
46-
NotificationOpenedProcessor.processFromContext(this, getIntent());
47-
finish();
48-
}
4931

32+
public class NotificationDismissReceiver extends BroadcastReceiver {
5033

51-
}
34+
@Override
35+
public void onReceive(Context context, Intent intent) {
36+
NotificationOpenedProcessor.processFromContext(context, intent);
37+
}
38+
}

OneSignalSDK/onesignal/src/main/java/com/onesignal/NotificationOpenedProcessor.java

Lines changed: 44 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -27,14 +27,15 @@
2727

2828
package com.onesignal;
2929

30+
import android.app.Activity;
3031
import android.app.NotificationManager;
3132
import android.content.ContentValues;
3233
import android.content.Context;
3334
import android.content.Intent;
3435
import android.database.Cursor;
35-
import android.database.sqlite.SQLiteDatabase;
36-
import androidx.annotation.NonNull;
3736
import android.os.Build;
37+
38+
import androidx.annotation.NonNull;
3839
import androidx.core.app.NotificationManagerCompat;
3940

4041
import com.onesignal.OneSignalDbContract.NotificationTable;
@@ -78,33 +79,19 @@ private static void handleDismissFromActionButtonPress(Context context, Intent i
7879
}
7980

8081
static void processIntent(Context context, Intent intent) {
82+
OneSignalDbHelper dbHelper = OneSignalDbHelper.getInstance(context);
8183
String summaryGroup = intent.getStringExtra("summary");
8284

8385
boolean dismissed = intent.getBooleanExtra("dismissed", false);
8486

85-
JSONArray dataArray = null;
86-
JSONObject jsonData = null;
87+
OSNotificationIntentExtras intentExtras = null;
8788
if (!dismissed) {
88-
try {
89-
jsonData = new JSONObject(intent.getStringExtra(BUNDLE_KEY_ONESIGNAL_DATA));
90-
91-
if (handleIAMPreviewOpen(context, jsonData))
92-
return;
89+
intentExtras = processToOpenIntent(context, intent, dbHelper, summaryGroup);
9390

94-
jsonData.put(BUNDLE_KEY_ANDROID_NOTIFICATION_ID, intent.getIntExtra(BUNDLE_KEY_ANDROID_NOTIFICATION_ID, 0));
95-
intent.putExtra(BUNDLE_KEY_ONESIGNAL_DATA, jsonData.toString());
96-
dataArray = NotificationBundleProcessor.newJsonArray(new JSONObject(intent.getStringExtra(BUNDLE_KEY_ONESIGNAL_DATA)));
97-
} catch (JSONException e) {
98-
e.printStackTrace();
99-
}
91+
if (intentExtras == null)
92+
return;
10093
}
10194

102-
OneSignalDbHelper dbHelper = OneSignalDbHelper.getInstance(context);
103-
104-
// We just opened a summary notification.
105-
if (!dismissed && summaryGroup != null)
106-
addChildNotifications(dataArray, summaryGroup, dbHelper);
107-
10895
markNotificationsConsumed(context, intent, dbHelper, dismissed);
10996

11097
// Notification is not a summary type but a single notification part of a group.
@@ -114,12 +101,44 @@ static void processIntent(Context context, Intent intent) {
114101
NotificationSummaryManager.updateSummaryNotificationAfterChildRemoved(context, dbHelper, group, dismissed);
115102
}
116103

117-
if (!dismissed)
118-
OneSignal.handleNotificationOpen(context, dataArray,
119-
intent.getBooleanExtra("from_alert", false), OSNotificationFormatHelper.getOSNotificationIdFromJson(jsonData));
104+
OneSignal.onesignalLog(OneSignal.LOG_LEVEL.DEBUG, "processIntent from context: " + context + " and intent: " + intent);
105+
if (intent.getExtras() != null)
106+
OneSignal.onesignalLog(OneSignal.LOG_LEVEL.DEBUG, "processIntent intent extras: " + intent.getExtras().toString());
107+
108+
if (!dismissed) {
109+
if (!(context instanceof Activity))
110+
OneSignal.onesignalLog(OneSignal.LOG_LEVEL.ERROR, "NotificationOpenedProcessor processIntent from an non Activity context: " + context);
111+
else OneSignal.handleNotificationOpen((Activity) context, intentExtras.getDataArray(),
112+
intent.getBooleanExtra("from_alert", false), OSNotificationFormatHelper.getOSNotificationIdFromJson(intentExtras.getJsonData()));
113+
}
114+
}
115+
116+
static OSNotificationIntentExtras processToOpenIntent(Context context, Intent intent, OneSignalDbHelper dbHelper, String summaryGroup) {
117+
JSONArray dataArray = null;
118+
JSONObject jsonData = null;
119+
try {
120+
jsonData = new JSONObject(intent.getStringExtra(BUNDLE_KEY_ONESIGNAL_DATA));
121+
122+
if (!(context instanceof Activity))
123+
OneSignal.onesignalLog(OneSignal.LOG_LEVEL.ERROR, "NotificationOpenedProcessor processIntent from an non Activity context: " + context);
124+
else if (handleIAMPreviewOpen((Activity) context, jsonData))
125+
return null;
126+
127+
jsonData.put(BUNDLE_KEY_ANDROID_NOTIFICATION_ID, intent.getIntExtra(BUNDLE_KEY_ANDROID_NOTIFICATION_ID, 0));
128+
intent.putExtra(BUNDLE_KEY_ONESIGNAL_DATA, jsonData.toString());
129+
dataArray = NotificationBundleProcessor.newJsonArray(new JSONObject(intent.getStringExtra(BUNDLE_KEY_ONESIGNAL_DATA)));
130+
} catch (JSONException e) {
131+
e.printStackTrace();
132+
}
133+
134+
// We just opened a summary notification.
135+
if (summaryGroup != null)
136+
addChildNotifications(dataArray, summaryGroup, dbHelper);
137+
138+
return new OSNotificationIntentExtras(dataArray, jsonData);
120139
}
121140

122-
static boolean handleIAMPreviewOpen(@NonNull Context context, @NonNull JSONObject jsonData) {
141+
static boolean handleIAMPreviewOpen(@NonNull Activity context, @NonNull JSONObject jsonData) {
123142
String previewUUID = NotificationBundleProcessor.inAppPreviewPushUUID(jsonData);
124143
if (previewUUID == null)
125144
return false;

OneSignalSDK/onesignal/src/main/java/com/onesignal/NotificationOpenedReceiver.java

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,14 +27,24 @@
2727

2828
package com.onesignal;
2929

30-
import android.content.BroadcastReceiver;
31-
import android.content.Context;
30+
import android.app.Activity;
3231
import android.content.Intent;
32+
import android.os.Bundle;
3333

34-
public class NotificationOpenedReceiver extends BroadcastReceiver {
34+
public class NotificationOpenedReceiver extends Activity {
3535

3636
@Override
37-
public void onReceive(Context context, Intent intent) {
38-
NotificationOpenedProcessor.processFromContext(context, intent);
37+
protected void onCreate(Bundle savedInstanceState) {
38+
super.onCreate(savedInstanceState);
39+
NotificationOpenedProcessor.processFromContext(this, getIntent());
40+
finish();
3941
}
42+
43+
@Override
44+
protected void onNewIntent(Intent intent) {
45+
super.onNewIntent(intent);
46+
NotificationOpenedProcessor.processFromContext(this, getIntent());
47+
finish();
48+
}
49+
4050
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
package com.onesignal
2+
3+
import org.json.JSONArray
4+
import org.json.JSONObject
5+
6+
data class OSNotificationIntentExtras(var dataArray: JSONArray?, var jsonData: JSONObject?)

0 commit comments

Comments
 (0)