Skip to content

Commit 849c4e2

Browse files
authored
Crashes seen around OneSignalNotificationManager (#839)
* Crashes seen around OneSignalNotificationManager * Removed all places where we use NotificationManager and NotificationManagerCompat and made static helper methods * getActiveNotifications() and notify() causing issues with Android 6.0.X previously and now with new groupless notifs handling Android 8.0.0 is having some trouble * try-catch implemented similar to Issue #422 reported/fixed in Jan/Feb 2018 for Android 6.0.X Minor additions to demo app for posting notifications with and without groups, also on main thread and async * Decided to remove the try catch and helper for notify() * DeadSystemException being thrown in some cases around notify() thought to be related to previous crashing and then reaching this method * We do not want to silently throw or fail in this case since other things may be causing this issue and not notify()
1 parent 64afe46 commit 849c4e2

File tree

9 files changed

+253
-70
lines changed

9 files changed

+253
-70
lines changed

OneSignalSDK/app/src/main/java/com/onesignal/MainActivity.java

Lines changed: 151 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -31,15 +31,19 @@
3131
import android.app.NotificationManager;
3232
import android.content.Context;
3333
import android.content.SharedPreferences;
34+
import android.os.AsyncTask;
3435
import android.os.Bundle;
3536
import android.os.Looper;
3637
import android.util.Log;
3738
import android.view.Menu;
3839
import android.view.MenuItem;
3940
import android.view.View;
4041
import android.widget.Button;
42+
import android.widget.CheckBox;
43+
import android.widget.CompoundButton;
4144
import android.widget.TextView;
4245
import android.os.Handler;
46+
import android.widget.Toast;
4347

4448
import com.onesignal.OneSignal.NotificationOpenedHandler;
4549

@@ -56,13 +60,26 @@ public class MainActivity extends Activity implements OSEmailSubscriptionObserve
5660

5761
IabHelper mHelper;
5862

59-
private int[] interactiveViewIds = new int[] {com.onesignal.example.R.id.subscribe, com.onesignal.example.R.id.unsubscribe, com.onesignal.example.R.id.sendTags, com.onesignal.example.R.id.getTags, com.onesignal.example.R.id.setEmail};
63+
private int[] interactiveViewIds = new int[]{
64+
R.id.subscribe,
65+
R.id.unsubscribe,
66+
R.id.sendTags,
67+
R.id.getTags,
68+
R.id.setEmail,
69+
R.id.postNotification,
70+
R.id.postNotificationAsync,
71+
R.id.postNotificationGroupCheckBox,
72+
R.id.postNotificationAsyncGroupCheckBox};
6073

6174
private TextView debugTextView;
6275
private TextView emailTextView;
6376
private Button consentButton;
6477
private Button setEmailButton;
6578
private Button logoutEmailButton;
79+
private Button postNotifButton;
80+
private Button postNotifAsyncButton;
81+
private CheckBox postNotifGroupCheckBox;
82+
private CheckBox postNotifAsyncGroupCheckBox;
6683

6784
private int sendTagsCounter = 1;
6885
private boolean addedObservers = false;
@@ -71,14 +88,39 @@ public class MainActivity extends Activity implements OSEmailSubscriptionObserve
7188
private TextView triggerValueTextView;
7289
private String SHARDPRES_KEY_IAM_HOST = "SHARDPRES_KEY_IAM_HOST";
7390

91+
@Override
92+
public boolean onCreateOptionsMenu(Menu menu) {
93+
// Inflate the menu; this adds items to the action bar if it is present.
94+
getMenuInflater().inflate(com.onesignal.example.R.menu.menu_main, menu);
95+
return true;
96+
}
97+
98+
@Override
99+
public boolean onOptionsItemSelected(MenuItem item) {
100+
// Handle action bar item clicks here. The action bar will
101+
// automatically handle clicks on the Home/Up button, so long
102+
// as you specify a parent activity in AndroidManifest.xml.
103+
int id = item.getItemId();
104+
105+
//noinspection SimplifiableIfStatement
106+
if (id == R.id.action_settings)
107+
return true;
108+
109+
return super.onOptionsItemSelected(item);
110+
}
111+
74112
@Override
75113
protected void onCreate(Bundle savedInstanceState) {
76114
super.onCreate(savedInstanceState);
77115
setContentView(com.onesignal.example.R.layout.activity_main);
78116

79-
this.consentButton = (Button)this.findViewById(com.onesignal.example.R.id.consentButton);
80-
this.setEmailButton = (Button)this.findViewById(com.onesignal.example.R.id.setEmail);
81-
this.logoutEmailButton = (Button)this.findViewById(com.onesignal.example.R.id.logoutEmail);
117+
this.consentButton = this.findViewById(R.id.consentButton);
118+
this.setEmailButton = this.findViewById(R.id.setEmail);
119+
this.logoutEmailButton = this.findViewById(R.id.logoutEmail);
120+
this.postNotifButton = this.findViewById(R.id.postNotification);
121+
this.postNotifAsyncButton = this.findViewById(R.id.postNotificationAsync);
122+
this.postNotifGroupCheckBox = this.findViewById(R.id.postNotificationGroupCheckBox);
123+
this.postNotifAsyncGroupCheckBox = this.findViewById(R.id.postNotificationAsyncGroupCheckBox);
82124
this.iamHost = this.findViewById(R.id.iamHost);
83125
this.triggerKeyTextView = this.findViewById(R.id.triggerKey);
84126
this.triggerValueTextView = this.findViewById(R.id.triggerValue);
@@ -115,6 +157,8 @@ public void onIabSetupFinished(IabResult result) {
115157
// Hooray, IAB is fully set up!
116158
}
117159
});
160+
161+
setupGroupingNotificationCheckBoxes();
118162
}
119163

120164
private void updateIamhost() {
@@ -294,41 +338,115 @@ public void onFullScreenClicked(View v) {
294338
updateIamhost();
295339
}
296340

297-
@Override
298-
public boolean onCreateOptionsMenu(Menu menu) {
299-
// Inflate the menu; this adds items to the action bar if it is present.
300-
getMenuInflater().inflate(com.onesignal.example.R.menu.menu_main, menu);
301-
return true;
302-
}
341+
public void onPostNotifClicked(View v) {
303342

304-
@Override
305-
public boolean onOptionsItemSelected(MenuItem item) {
306-
// Handle action bar item clicks here. The action bar will
307-
// automatically handle clicks on the Home/Up button, so long
308-
// as you specify a parent activity in AndroidManifest.xml.
309-
int id = item.getItemId();
343+
String userId = OneSignal.getUserId();
310344

311-
//noinspection SimplifiableIfStatement
312-
if (id == R.id.action_settings)
313-
return true;
345+
JSONObject notifPayload = null;
346+
try {
314347

315-
return super.onOptionsItemSelected(item);
348+
notifPayload = new JSONObject("{'contents': " + "{'en':'Test Message'}, 'include_player_ids': ['" + userId + "']}");
349+
350+
if (postNotifGroupCheckBox.isChecked())
351+
notifPayload.put("android_group", "group_1");
352+
353+
} catch (JSONException e) {
354+
e.printStackTrace();
355+
}
356+
357+
OneSignal.postNotification(notifPayload, new OneSignal.PostNotificationResponseHandler() {
358+
@Override
359+
public void onSuccess(JSONObject response) {
360+
OneSignal.onesignalLog(OneSignal.LOG_LEVEL.DEBUG, response.toString());
361+
}
362+
363+
@Override
364+
public void onFailure(JSONObject response) {
365+
OneSignal.onesignalLog(OneSignal.LOG_LEVEL.ERROR, response.toString());
366+
}
367+
});
316368
}
317369

318-
// NotificationOpenedHandler is implemented in its own class instead of adding implements to MainActivity so we don't hold on to a reference of our first activity if it gets recreated.
319-
private class ExampleNotificationOpenedHandler implements NotificationOpenedHandler {
320-
/**
321-
* Callback to implement in your app to handle when a notification is opened from the Android status bar or
322-
* a new one comes in while the app is running.
323-
* This method is located in this activity as an example, you may have any class you wish implement NotificationOpenedHandler and define this method.
324-
*
325-
* @param openedResult The message string the user seen/should see in the Android status bar.
326-
*/
370+
public void onPostNotifAsyncClicked(View v) {
371+
new AsyncTaskRunner().execute(
372+
postNotifAsyncGroupCheckBox.isChecked()
373+
);
374+
}
375+
376+
private class AsyncTaskRunner extends AsyncTask<Object, Void, Void> {
377+
378+
@Override
379+
protected Void doInBackground(Object... params) {
380+
381+
try {
382+
Thread.sleep(1000);
383+
} catch (InterruptedException e) {
384+
e.printStackTrace();
385+
}
386+
387+
String userId = OneSignal.getUserId();
388+
389+
JSONObject notifPayload = null;
390+
try {
391+
392+
notifPayload = new JSONObject("{'contents': " + "{'en':'Test Message'}, 'include_player_ids': ['" + userId + "']}");
393+
394+
Boolean addGroup = (Boolean) params[0];
395+
if (addGroup)
396+
notifPayload.put("android_group", "group_1");
397+
398+
} catch (JSONException e) {
399+
e.printStackTrace();
400+
}
401+
402+
OneSignal.postNotification(notifPayload, new OneSignal.PostNotificationResponseHandler() {
403+
@Override
404+
public void onSuccess(JSONObject response) {
405+
OneSignal.onesignalLog(OneSignal.LOG_LEVEL.DEBUG, response.toString());
406+
}
407+
408+
@Override
409+
public void onFailure(JSONObject response) {
410+
OneSignal.onesignalLog(OneSignal.LOG_LEVEL.ERROR, response.toString());
411+
}
412+
});
413+
414+
return null;
415+
}
416+
417+
327418
@Override
328-
public void notificationOpened(OSNotificationOpenResult openedResult) {
329-
Log.e("OneSignalExample", "body: " + openedResult.notification.payload.body);
330-
Log.e("OneSignalExample", "additional data: " + openedResult.notification.payload.additionalData);
331-
//Log.e("OneSignalExample", "additionalData: " + additionalData.toString());
419+
protected void onPostExecute(Void result) {
420+
421+
}
422+
423+
424+
@Override
425+
protected void onPreExecute() {
426+
427+
}
428+
429+
430+
@Override
431+
protected void onProgressUpdate(Void... entry) {
432+
332433
}
333434
}
435+
436+
private void setupGroupingNotificationCheckBoxes() {
437+
this.postNotifGroupCheckBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
438+
@Override
439+
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
440+
Toaster.makeToast(MainActivity.this, "Main thread Notifications will be grouped: " + isChecked, Toast.LENGTH_SHORT);
441+
}
442+
});
443+
444+
this.postNotifAsyncGroupCheckBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
445+
@Override
446+
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
447+
Toaster.makeToast(MainActivity.this, "Async notifications will be grouped: " + isChecked, Toast.LENGTH_SHORT);
448+
}
449+
});
450+
}
451+
334452
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package com.onesignal;
2+
3+
import android.content.Context;
4+
import android.widget.Toast;
5+
6+
public class Toaster {
7+
8+
static public void makeToast(Context context, String message, int time) {
9+
Toast.makeText(context, message, time).show();
10+
}
11+
12+
}

OneSignalSDK/app/src/main/java/com/onesignal/example/OneSignalExampleApp.java

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -47,10 +47,17 @@ public class OneSignalExampleApp extends Application {
4747
public void onCreate() {
4848
super.onCreate();
4949

50-
StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder().detectAll().build());
51-
StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder().detectAll().build());
50+
StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
51+
.detectAll()
52+
.penaltyLog()
53+
.build());
5254

53-
OneSignal.setLogLevel(OneSignal.LOG_LEVEL.VERBOSE, OneSignal.LOG_LEVEL.ERROR);
55+
StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder()
56+
.detectAll()
57+
.penaltyLog()
58+
.build());
59+
60+
OneSignal.setLogLevel(OneSignal.LOG_LEVEL.VERBOSE, OneSignal.LOG_LEVEL.NONE);
5461

5562
String currentAppId = getOneSignalAppId(this);
5663
if (currentAppId == null)

OneSignalSDK/app/src/main/res/layout/activity_main.xml

Lines changed: 51 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
11
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
22
xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
3-
android:layout_height="match_parent" android:paddingLeft="@dimen/activity_horizontal_margin"
4-
android:paddingRight="@dimen/activity_horizontal_margin"
5-
android:paddingTop="@dimen/activity_vertical_margin"
6-
android:paddingBottom="@dimen/activity_vertical_margin" tools:context="com.onesignal.MainActivity">
3+
android:layout_height="match_parent"
4+
tools:context="com.onesignal.MainActivity">
75

86
<ScrollView
97
android:layout_width="match_parent"
@@ -15,6 +13,7 @@
1513
<LinearLayout
1614
android:layout_width="match_parent"
1715
android:layout_height="wrap_content"
16+
android:padding="16dp"
1817
android:orientation="vertical" >
1918

2019
<Button
@@ -136,6 +135,54 @@
136135
android:onClick="onLogoutEmailClicked"
137136
android:text="Logout Email" />
138137

138+
<RelativeLayout
139+
android:layout_width="match_parent"
140+
android:layout_height="wrap_content"
141+
android:orientation="horizontal">
142+
143+
<CheckBox
144+
android:id="@+id/postNotificationGroupCheckBox"
145+
android:layout_width="wrap_content"
146+
android:layout_height="wrap_content"
147+
android:layout_alignParentEnd="true"
148+
android:layout_centerVertical="true"/>
149+
150+
<Button
151+
android:id="@+id/postNotification"
152+
android:layout_width="match_parent"
153+
android:layout_height="wrap_content"
154+
android:layout_alignParentStart="true"
155+
android:layout_centerVertical="true"
156+
android:layout_toStartOf="@id/postNotificationGroupCheckBox"
157+
android:onClick="onPostNotifClicked"
158+
android:text="Post Notification" />
159+
160+
</RelativeLayout>
161+
162+
<RelativeLayout
163+
android:layout_width="match_parent"
164+
android:layout_height="wrap_content"
165+
android:orientation="horizontal">
166+
167+
<CheckBox
168+
android:id="@+id/postNotificationAsyncGroupCheckBox"
169+
android:layout_width="wrap_content"
170+
android:layout_height="wrap_content"
171+
android:layout_alignParentEnd="true"
172+
android:layout_centerVertical="true"/>
173+
174+
<Button
175+
android:id="@+id/postNotificationAsync"
176+
android:layout_width="match_parent"
177+
android:layout_height="wrap_content"
178+
android:layout_alignParentStart="true"
179+
android:layout_centerVertical="true"
180+
android:layout_toStartOf="@id/postNotificationAsyncGroupCheckBox"
181+
android:onClick="onPostNotifAsyncClicked"
182+
android:text="Post Notification Async" />
183+
184+
</RelativeLayout>
185+
139186
<TextView
140187
android:id="@+id/debugTextView"
141188
android:layout_width="match_parent"

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

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -86,8 +86,7 @@ static void update(SQLiteDatabase readableDb, Context context) {
8686

8787
@RequiresApi(api = Build.VERSION_CODES.M)
8888
private static void updateStandard(Context context) {
89-
NotificationManager notifManager = OneSignalNotificationManager.getNotificationManager(context);
90-
StatusBarNotification[] activeNotifs = notifManager.getActiveNotifications();
89+
StatusBarNotification[] activeNotifs = OneSignalNotificationManager.getActiveNotifications(context);
9190

9291
int runningCount = 0;
9392
for (StatusBarNotification activeNotif : activeNotifs) {

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -374,7 +374,7 @@ private static void showNotification(NotificationGenerationJob notifJob) {
374374
// Create PendingIntents for notifications in a groupless or defined summary
375375
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N &&
376376
group.equals(OneSignalNotificationManager.getGrouplessSummaryKey()))
377-
createGrouplessSummaryNotification(notifJob, oneSignalNotificationBuilder, grouplessNotifs.size() + 1);
377+
createGrouplessSummaryNotification(notifJob, grouplessNotifs.size() + 1);
378378
else
379379
createSummaryNotification(notifJob, oneSignalNotificationBuilder);
380380
}
@@ -706,7 +706,7 @@ private static void createSummaryNotification(NotificationGenerationJob notifJob
706706
}
707707

708708
@RequiresApi(api = Build.VERSION_CODES.M)
709-
private static void createGrouplessSummaryNotification(NotificationGenerationJob notifJob, OneSignalNotificationBuilder notifBuilder, int grouplessNotifCount) {
709+
private static void createGrouplessSummaryNotification(NotificationGenerationJob notifJob, int grouplessNotifCount) {
710710
JSONObject gcmBundle = notifJob.jsonPayload;
711711

712712
Notification summaryNotification;
@@ -744,7 +744,7 @@ private static void createGrouplessSummaryNotification(NotificationGenerationJob
744744
summaryBuilder.setGroupAlertBehavior(NotificationCompat.GROUP_ALERT_SUMMARY);
745745
}
746746
catch (Throwable t) {
747-
//do nothing in this case...Android support lib 26 isn't in the project
747+
// Do nothing in this case... Android support lib 26 isn't in the project
748748
}
749749

750750
NotificationCompat.InboxStyle inboxStyle = new NotificationCompat.InboxStyle();

0 commit comments

Comments
 (0)