Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

The app crashes when an exception occurs inside OneSignal in SDK 4.4.1+ #1444

Closed
ushi3 opened this issue Sep 30, 2021 · 5 comments · Fixed by #1484
Closed

The app crashes when an exception occurs inside OneSignal in SDK 4.4.1+ #1444

ushi3 opened this issue Sep 30, 2021 · 5 comments · Fixed by #1484
Assignees

Comments

@ushi3
Copy link

ushi3 commented Sep 30, 2021

Description:

In version 4.4.1 and above, when OneSignal receives a push notification, an exception that occurs within OneSignal SDK to crashes the app.

We have updated the SDK from 4.4.0 to 4.6.0 and released the app. Since then, we've been receiving a lot of crash reports.
After investigating the cause, it was found that it was due to the changes of #1356. And SDK containing it was released in version 4.4.1.

What's wrong with #1356?

TLDR;
After 4.4.1, The thread being OneSignal notification process is not catching the exception properly.

In #1356, implementation of OSNotificationWorkerManager.NotificationWorker changed Worker to ListenableWorker.
Worker's doWork() runs on worker-thread, while ListenableWorker's startWork() runs on main-thread.
That difference causes a change in the subsequent processing. (probably not intended)

Both processes call processNotificationData(), and then reaches OSNotificationReceivedEvent.complete(). OSNotificationReceivedEvent.complete() is the part that causes this issue.

Here exist code that if call on main-thread, execute process on other thread. code
Below 4.4.1, this if statement is false. So, continue processing on current-thread (= worker-thread).
After 4.4.1, this statement is true, run in other thread made on instant.

If the method OSNotificationReceivedEvent.processNotification() is execute on worker-thread, the exception thrown here will be caught byWorker.startWorker(). However, if the method is execute on instant thread, the exception will not be caught. App crashes when actual exception thrown.

Do you really throw some exception in this method? to anwer YES.
Many of the exceptions are caused by Android NotificationManager API and device platform bugs.
For example, on some devices such as Samsung, LG, the system notification service was killed (reason don't know why), NotificationManager throw DeadSystemException.

Environment

Device OS : Android 7.0, 7.1.1, 8.0, 8.1 (at least)
OneSignal SDK : 4.4.1+

Steps to Reproduce Issue:

Confirm that execution-thread has changed around 4.4.1 before-after.

  1. Enabled Debug
  2. mark breakpointOSNotificationReceivedEvent.complete()#L71~
  3. monitor Looper.getMainLooper().isCurrentThread()
  4. send OneSignal push notification (ex. OneSignal dashboard)
  5. below 4.4.1 monitoring value is false, above 4.4.1 is true
Below 4.4.1 After 4.4.1
image image

It is difficult to raise an exception, but you can see the app behavior by throw exception using the debugger during this process.

Anything else:

A simple fix is to try-catch exception into the Runnable at OSNotificationReceivedEvent.complete()#L81-88.

@jkasten2
Copy link
Member

jkasten2 commented Oct 5, 2021

@ushi3 Thanks for reporting with all this detail. Could you also include the stacktraces of the crashes you are seeing? We would like to know which exceptions we should be correctly handling instead catching everything here.

@ushi3
Copy link
Author

ushi3 commented Oct 6, 2021

@jkasten2

OK, Below is examples we've receiving.

Fatal Exception: java.lang.RuntimeException: android.os.DeadSystemException
       at android.app.NotificationManager.notifyAsUser(NotificationManager.java:320)
       at android.app.NotificationManager.notify(NotificationManager.java:289)
       at androidx.core.app.NotificationManagerCompat.notify(NotificationManagerCompat.java:223)
       at androidx.core.app.NotificationManagerCompat.notify(NotificationManagerCompat.java:205)
       at com.onesignal.OneSignalNotificationManager.assignGrouplessNotifications(OneSignalNotificationManager.java:118)
       at com.onesignal.GenerateNotification.showNotification(GenerateNotification.java:275)
       at com.onesignal.GenerateNotification.displayNotification(GenerateNotification.java:103)
       at com.onesignal.NotificationBundleProcessor.processJobForDisplay(NotificationBundleProcessor.java:156)
       at com.onesignal.NotificationBundleProcessor.processJobForDisplay(NotificationBundleProcessor.java:133)
       at com.onesignal.OSNotificationController.processNotification(OSNotificationController.java:97)
       at com.onesignal.OSNotificationReceivedEvent.processNotification(OSNotificationReceivedEvent.java:95)
       at com.onesignal.OSNotificationReceivedEvent.access$000(OSNotificationReceivedEvent.java:35)
       at com.onesignal.OSNotificationReceivedEvent$2.run(OSNotificationReceivedEvent.java:84)
       at java.lang.Thread.run(Thread.java:764)
Fatal Exception: java.lang.RuntimeException: android.os.DeadSystemException
       at android.app.NotificationManager.notifyAsUser(NotificationManager.java:511)
       at android.app.NotificationManager.notify(NotificationManager.java:458)
       at androidx.core.app.NotificationManagerCompat.notify(NotificationManagerCompat.java:223)
       at androidx.core.app.NotificationManagerCompat.notify(NotificationManagerCompat.java:205)
       at com.onesignal.GenerateNotification.showNotification(GenerateNotification.java:345)
       at com.onesignal.GenerateNotification.displayNotification(GenerateNotification.java:103)
       at com.onesignal.NotificationBundleProcessor.processJobForDisplay(NotificationBundleProcessor.java:156)
       at com.onesignal.NotificationBundleProcessor.processJobForDisplay(NotificationBundleProcessor.java:133)
       at com.onesignal.OSNotificationController.processNotification(OSNotificationController.java:97)
       at com.onesignal.OSNotificationReceivedEvent.processNotification(OSNotificationReceivedEvent.java:95)
       at com.onesignal.OSNotificationReceivedEvent.access$000(OSNotificationReceivedEvent.java:35)
       at com.onesignal.OSNotificationReceivedEvent$2.run(OSNotificationReceivedEvent.java:84)
       at java.lang.Thread.run(Thread.java:919)
Fatal Exception: java.lang.RuntimeException: Could not read bitmap blob.
       at android.graphics.Bitmap.nativeCreateFromParcel(Bitmap.java)
       at android.graphics.Bitmap.-wrap0(Bitmap.java)
       at android.graphics.Bitmap$1.createFromParcel(Bitmap.java:1788)
       at android.graphics.Bitmap$1.createFromParcel(Bitmap.java:1781)
       at android.graphics.drawable.Icon.<init>(Icon.java:732)
       at android.graphics.drawable.Icon.<init>(Icon.java)
       at android.graphics.drawable.Icon$1.createFromParcel(Icon.java:798)
       at android.graphics.drawable.Icon$1.createFromParcel(Icon.java:797)
       at android.os.Parcel.readParcelable(Parcel.java:2824)
       at android.os.Parcel.readValue(Parcel.java:2718)
       at android.os.Parcel.readArrayMapInternal(Parcel.java:3085)
       at android.os.BaseBundle.unparcel(BaseBundle.java:257)
       at android.os.Bundle.getParcelable(Bundle.java:888)
       at android.app.Notification$Builder.recoverBuilder(Notification.java:4830)
       at com.onesignal.OneSignalNotificationManager.assignGrouplessNotifications(OneSignalNotificationManager.java:108)
       at com.onesignal.GenerateNotification.showNotification(GenerateNotification.java:275)
       at com.onesignal.GenerateNotification.displayNotification(GenerateNotification.java:103)
       at com.onesignal.NotificationBundleProcessor.processJobForDisplay(NotificationBundleProcessor.java:156)
       at com.onesignal.NotificationBundleProcessor.processJobForDisplay(NotificationBundleProcessor.java:133)
       at com.onesignal.OSNotificationController.processNotification(OSNotificationController.java:97)
       at com.onesignal.OSNotificationReceivedEvent.processNotification(OSNotificationReceivedEvent.java:95)
       at com.onesignal.OSNotificationReceivedEvent.access$000(OSNotificationReceivedEvent.java:35)
       at com.onesignal.OSNotificationReceivedEvent$2.run(OSNotificationReceivedEvent.java:84)
       at java.lang.Thread.run(Thread.java:764)
Fatal Exception: java.lang.RuntimeException: Could not copy bitmap to parcel blob.
       at android.graphics.Bitmap.nativeWriteToParcel(Bitmap.java)
       at android.graphics.Bitmap.writeToParcel(Bitmap.java:2026)
       at android.graphics.drawable.Icon.writeToParcel(Icon.java:773)
       at android.app.Notification.writeToParcelImpl(Notification.java:2296)
       at android.app.Notification.writeToParcel(Notification.java:2233)
       at android.app.INotificationManager$Stub$Proxy.enqueueNotificationWithTag(INotificationManager.java:1263)
       at android.app.NotificationManager.notifyAsUser(NotificationManager.java:340)
       at android.app.NotificationManager.notify(NotificationManager.java:300)
       at androidx.core.app.NotificationManagerCompat.notify(NotificationManagerCompat.java:223)
       at androidx.core.app.NotificationManagerCompat.notify(NotificationManagerCompat.java:205)
       at com.onesignal.GenerateNotification.createGrouplessSummaryNotification(GenerateNotification.java:745)
       at com.onesignal.GenerateNotification.showNotification(GenerateNotification.java:321)
       at com.onesignal.GenerateNotification.displayNotification(GenerateNotification.java:103)
       at com.onesignal.NotificationBundleProcessor.processJobForDisplay(NotificationBundleProcessor.java:156)
       at com.onesignal.NotificationBundleProcessor.processJobForDisplay(NotificationBundleProcessor.java:133)
       at com.onesignal.OSNotificationController.processNotification(OSNotificationController.java:97)
       at com.onesignal.OSNotificationReceivedEvent.processNotification(OSNotificationReceivedEvent.java:95)
       at com.onesignal.OSNotificationReceivedEvent.access$000(OSNotificationReceivedEvent.java:35)
       at com.onesignal.OSNotificationReceivedEvent$2.run(OSNotificationReceivedEvent.java:84)
       at java.lang.Thread.run(Thread.java:784)

@ushi3
Copy link
Author

ushi3 commented Oct 6, 2021

According to our findings, when calling NotificationManager.notify(), cause exception maybe.
These are just a few, and you won't know what exceptions will be thrown until realy throw. In fact, the same line raises different exceptions.

By the way, I think the implementation of androidx.Worker will be helpful us.

https://android.googlesource.com/platform/frameworks/support/+/refs/heads/androidx-work-release/work/work-runtime/src/main/java/androidx/work/Worker.java#88

Worker catches all exceptions and marks them as Failed.

@ushi3
Copy link
Author

ushi3 commented Nov 16, 2021

Maybe, fixed by v4.6.3 🎉 🎉 🎉

@nan-li
Copy link
Contributor

nan-li commented Nov 16, 2021

@ushi3, please reopen or comment if you're having any more issues. I closed it for now with our new release.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants