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

Android 13 BadParcelableException: Parcel android.os.Parcel: Unmarshalling unknown type code #515

Closed
liamjones opened this issue Sep 7, 2022 · 41 comments

Comments

@liamjones
Copy link
Contributor

We've been seeing this a reasonable amount since our app was updated to Notifee 5.5.0 (86 instances across 10 users in the last 8 days), any ideas?

It seems to be happening purely on Android 13. It's also only happening on various models of Pixel phones but I assume that's because it's the only one with Android 13 available so far...

This is on React Native 0.66.3 and our top-level build.gradle contains:

buildscript {
    ext {
        buildToolsVersion = "30.0.2"
        minSdkVersion = 24
        compileSdkVersion = 31
        targetSdkVersion = 30
        ndkVersion = "21.4.7075529"
    }
    dependencies {
        // ...
        classpath("com.google.gms:google-services:4.3.10")
    }

Stack trace (it's always the same type code and offset):

android.os.BadParcelableException: Parcel android.os.Parcel@21652a5: Unmarshalling unknown type code 1107296256 at offset 217
    at android.os.Parcel.readValue(Parcel.java:4658)
    at android.os.Parcel.readValue(Parcel.java:4490)
    at android.os.Parcel.readLazyValue(Parcel.java:4361)
    at android.os.Parcel.readArrayMap(Parcel.java:5208)
    at android.os.BaseBundle.initializeFromParcelLocked(BaseBundle.java:441)
    at android.os.BaseBundle.unparcel(BaseBundle.java:313)
    at android.os.BaseBundle.unparcel(BaseBundle.java:305)
    at android.os.BaseBundle.keySet(BaseBundle.java:737)
    at com.facebook.react.bridge.Arguments.fromBundle(Arguments.java:295)
    at com.facebook.react.bridge.Arguments.fromBundle(Arguments.java:312)
    at com.facebook.react.bridge.Arguments.fromBundle(Arguments.java:312)
    at io.invertase.notifee.NotifeeReactUtils.promiseResolver(NotifeeReactUtils.java:71)
    at io.invertase.notifee.NotifeeApiModule.lambda$getTriggerNotifications$5(NotifeeApiModule.java:88)
    at io.invertase.notifee.-$$Lambda$NotifeeApiModule$PNm3RTDT9NuO15y5400FmZ8sOic.onComplete
    at app.notifee.core.c.b(SourceFile:204)
    at app.notifee.core.-$$Lambda$wP11Zzh_Q5K2vywg80aCSDBhofU.onComplete
    at com.google.android.gms.tasks.zzi.run(com.google.android.gms:play-services-tasks@@18.0.1:1)
    at android.os.Handler.handleCallback(Handler.java:942)
    at android.os.Handler.dispatchMessage(Handler.java:99)
    at android.os.Looper.loopOnce(Looper.java:201)
    at android.os.Looper.loop(Looper.java:288)
    at android.app.ActivityThread.main(ActivityThread.java:7898)
    at java.lang.reflect.Method.invoke(Method.java)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:936)
@mikehardy
Copy link
Contributor

Interesting - sorry this is happening -

since our app was updated to Notifee 5.5.0

Updated from what to 5.5.0? This would help bisect and see what happened. It appears that this is likely a serialization/de-serialization issue where types mismatch or are in wrong order, and bisecting the diff between your started-at and ended-up-at versions would be useful

@mikehardy
Copy link
Contributor

If you were updating from 5.3.0 then I think it is the alteration in timestamp handling from here: https://github.com/invertase/notifee/pull/449/files

Specifically I think the handling of "mTimestamp" in the trigger notification model is suspect, and may not be in sync between serialization / deserialization now.

Just a hypothesis though, until I know what range we're looking for I can't be sure.

For reference
https://android.googlesource.com/platform/frameworks/base/+/refs/heads/android13-release/core/java/android/os/Parcel.java#4658

@mikehardy
Copy link
Contributor

Proguard may also have relevance (see https://issuetracker.google.com/issues/177246248) with regards to serializing from one version of an app to another, and since you indicate this is only happening on Android 13 (which has a Parcelable substantially rewritten from Android 12 - https://android.googlesource.com/platform/frameworks/base/+/refs/heads/android12-release/core/java/android/os/Parcel.java ) it may be serialization from one version of Android to another.

Does this keep happening on Android 13 phones every time? Or for each Android phone that throws this stack, are they able to run successfully after?

This one could be really subtle

@liamjones
Copy link
Contributor Author

Updated from what to 5.5.0?

Unfortunately, it's a big range, the last release of our app before this one was using 3.0.4.

Proguard may also have relevance

Currently, we have it disabled. There's very little native code that's not a public RN native module in our app so we hadn't considered it necessary (though we may enable it soon for space-saving reasons).

Does this keep happening on Android 13 phones every time? Or for each Android phone that throws this stack, are they able to run successfully after?

Not 100% sure yet, I've been getting the reports to Sentry but I'm not aware that we've had a user contact support yet in relation to this. I'm checking with our support team.

It's certainly happening repeatedly for some users:
image

The pattern of errors varies between users too, some have a burst in one go and may be okay again after that (I need to get someone to investigate the prod environment to see if the user in question has sent us data since that point, I'll let you know):
image

Others seem to have had it on different days which implies they're still using the app between these issues:
image

@mikehardy mikehardy changed the title android.os.BadParcelableException: Parcel android.os.Parcel: Unmarshalling unknown type code 1107296256 at offset 217 Android 13 BadParcelableException: Parcel android.os.Parcel: Unmarshalling unknown type code Sep 7, 2022
@mikehardy
Copy link
Contributor

Hmm. That's simplifying, that proguard is disabled, good to know.

So it's down to (I think...) either

1- "Android 12 to Android 13 introduces something such that notifications are incorrect across that transition on a specific user device, or
2- Something in Android 13s largely-new Parcelable implementation is triggered by something in the code on Notifee between 3.0.4 and 5.5.0 versions here

I suspect 1 is not the root cause, as you indicate some users on Android 13 see it, then don't see it, then see it again.

So I suspect there is either

2a - a bug in the Parcelable code for Android 13 (though I did not see any in the android issuetracker...) or
2b - we have a subtle thing here that Android 13 points out.

My working hypothesis is 2b.

How are you setting / using the APIs here? A reproducer would be most excellent especially if it showed the issue on an Android 13 emulator, because it is a big diff @notifee/react-native@3.0.4...@notifee/react-native@5.50

These look suspect
0384ea9
6e9c2e5
905f3c7

Most of those were on 5.4.0, I wonder if < 5.4.0 would work without reproducing? Not sure if you can do a build like that (intentionally dropping to 5.3.0) but I believe 5.3.0 will work well on Android 13 still, just maybe with a timestamp repeat frequency trigger regression

@liamjones
Copy link
Contributor Author

I've done a bit more investigation:

Someone in the office has a Pixel w/ Android 13 - I got them to install the old app, schedule a notification then upgrade it. No issue there - no error to Sentry, notification was delivered after the upgrade. Don't really want to ask them to downgrade their OS to 12 (is that even possible anymore?) as it's their personal device.

As far as looking at the data for some of the users who have hit this in prod:

None of them has contacted support about notification issues - so far anyway. It might take them a while to notice however (some of our notifications are weekly or monthly).

The user who had the big burst of these errors on Sep 5th has used the app again on the 6th, 7th and 8th, so the problem seems to have cleared for them. Their installation ID remains consistent so they don't seem to have reinstalled the app. They were on Android 12 with the previous version of our app AND were still on 12 when they first upgraded to, and used, the latest version of our app. The first time they used the app on Android 13 was when the burst of errors came through.

The user who has had repeated instances of this on Aug 30th, Aug 31st, Sep 1st, Sep 6th, and Sep 7th seems to be having it happen every time they use the app (cross-referencing with other data we have). This user was on Android 12 with the previous version of the app but both the app and the OS upgraded at the same time.

How are you setting / using the APIs here?

Channel creation is done on app startup, every app startup, pretty much every channel is setup like this due to being largely templated:

notifee.createChannel({
    id: 'unique-id',
    name: 'Unique name',
    lightColor: 'App common color',
    description: 'Unique description',
    importance: AndroidImportance.HIGH,
    visibility: AndroidVisibility.PRIVATE,
    lights: true,
    sound: 'default',
})

One thing that is possibly relevant? We were missing sound: 'default' in our last release (and all earlier ones). We corrected this in the latest release but have not added code yet to say 'delete channel and recreate it' for existing users so this new property will only be applied to new users (and we're seeing this in prod with existing ones). So, the channel definition changed between our app releases.

Notification creation/scheduling is largely templated too.

Every time a module in our app needs a notification scheduled we currently do the following (essentially):

// Check permissions first
const settings = yield notifee.requestPermission()
if (settings.authorizationStatus >= AuthorizationStatus.AUTHORIZED) {
    // schedule notifications
} else {
    // abandon trying to schedule
}

// Not the most efficient but right now, we kill and reschedule all notifications whenever a module in the app wants a change done
yield notifee.cancelTriggerNotifications()

// osNotification.notification is the Notifee notification
for (const osNotification of osNotifications) {
    if (osNotification.schedule.fireDate.isBefore(LocalDateTime.now(clock))) {
        throw new NotificationScheduledInPastError('Notification is scheduled in the past.', osNotification.notification.id, LocalDateTime.now(clock)) // handled elsewhere
    }
    yield notifee.createTriggerNotification(osNotification.notification, {
        type: TriggerType.TIMESTAMP,
        timestamp: 12345,
        repeatFrequency: schedule.repeatInterval ? RepeatFrequency.RELEVANT_VALUE : undefined,
    }
}

The thing that confuses me about the user who has had this happen in every session since they upgraded to Android 13 - we reschedule all our notifications when the app is launched. So, I would have expected the problem to disappear the first time yield notifee.cancelTriggerNotifications() happened... 🤔 Hmm, maybe the app is remaining in memory day-to-day for that user so it's not been 'relaunched' yet.

I'm trying to come up with a repro but I've been unable to reproduce it so far. 😞

@topi-identio
Copy link

We've been noticing the same error with Pixel users upgrading their Android versions to 13. Users have told that the app crashes and won't reopen, but reinstalling works. One user feedback stated that on Android 13 notifications will only be shown after reopening the app instead of when they should be. Not sure if this is before or after a reinstallation or if it's even related to this same issue.

Our Google Play Console has logged around 3k instances of the Exception android.os.BadParcelableException crash for around 400 users, all using Android 13.

Here are our relevant dependency versions:

"@notifee/react-native": "^5.1.0",
"react-native": "0.64.2",

@mikehardy
Copy link
Contributor

mikehardy commented Sep 8, 2022

This is evil! Not your fault of course, just I have a hunch this is going to be really subtle.
@topi-identio thanks for providing your versions, sorry it is crashing for you as well. Can you tell me what your actual version in use is (for example: cat yarn.lock | grep @notifee/react-native, as the ^ indicates to me that you could be on a higher version, all the way up to 5.7.0 so I'm not sure what if any versions are potentially removed from the set of versions to consider

@mikehardy
Copy link
Contributor

Just to be clear on "most rapid path forward", these are I think the options, but all require a reproduction you can trigger or it's just guess work:

  • careful code inspection of things going in to and out of the parcelables to make sure types and write/read order are the same
  • app rebuild with careful bisect of versions of notifee in place, between the lower and upper version ranges that are "known good" and "not working"

With no reproduction (ideally in an android 13 emulator...) this will be really hard though, I would focus everything on a repro if possible

@susonthapa
Copy link

We are having the same issue in production. We are currently using 5.3.0 version of the library. We tried reproducing this on an emulator but couldn't. Everything works fine on the emulator. We are seeing a lot of crashes for Pixel users with Android 13. We are actively trying to reproduce the issue.

@mikehardy
Copy link
Contributor

mikehardy commented Sep 8, 2022

Just offering that I actually have a Pixel 4a (which I may update to Android 13, currently it is on 12) in my household (not my phone, but I have access to it) if there was any reproduction that triggered on a real device reliably, I could also work with it. Not as easy as an emulator of course but feasible since this appears to be a serious issue.

@princekurt
Copy link

princekurt commented Sep 8, 2022

A stack trace in case that will help get to the bottom of this!

Fatal Exception: android.os.BadParcelableException
Parcel android.os.Parcel@95c784e: Unmarshalling unknown type code 301989887 at offset 533
android.os.Parcel.readValue (Parcel.java:4658)
android.os.Parcel.readValue (Parcel.java:4490)
android.os.Parcel.readLazyValue (Parcel.java:4361)
android.os.Parcel.readArrayMap (Parcel.java:5208)
android.os.BaseBundle.initializeFromParcelLocked (BaseBundle.java:441)
android.os.BaseBundle.unparcel (BaseBundle.java:313)
android.os.BaseBundle.unparcel (BaseBundle.java:305)
android.os.BaseBundle.keySet (BaseBundle.java:737)
com.facebook.react.bridge.Arguments.fromBundle (Arguments.java:291)
com.facebook.react.bridge.Arguments.fromBundle (Arguments.java:308)
com.facebook.react.bridge.Arguments.fromBundle (Arguments.java:308)
io.invertase.notifee.NotifeeReactUtils.promiseResolver (NotifeeReactUtils.java:71)
io.invertase.notifee.NotifeeApiModule.lambda$getTriggerNotifications$5 (NotifeeApiModule.java:88)
io.invertase.notifee.-$$Lambda$NotifeeApiModule$L4wCzZM2Sl_3tMHsB4AF2b9d2cI.onComplete (Unknown Source:4)
app.notifee.core.c.b (SourceFile:204)
app.notifee.core.-$$Lambda$NDsXhW2NagZ14z2bYfXj4Llokwc.onComplete (Unknown Source:2)
com.google.android.gms.tasks.zzi.run (com.google.android.gms:play-services-tasks@@18.0.1:1)

@princekurt
Copy link

@mikehardy So from the stack trace above, it looks like when using the getTriggerNotification() call that it throws the error. Might be able to create a reproduction through that.

@topi-identio
Copy link

This is evil! Not your fault of course, just I have a hunch this is going to be really subtle. @topi-identio thanks for providing your versions, sorry it is crashing for you as well. Can you tell me what your actual version in use is (for example: cat yarn.lock | grep @notifee/react-native, as the ^ indicates to me that you could be on a higher version, all the way up to 5.7.0 so I'm not sure what if any versions are potentially removed from the set of versions to consider

Ah sorry, our version in yarn.lock is indeed 5.1.0.

@liamjones
Copy link
Contributor Author

@mikehardy So from the stack trace above, it looks like when using the getTriggerNotification() call that it throws the error. Might be able to create a reproduction through that.

Oh, this might possibly be the trigger for us too. I simplified the code I posted above - one thing I omitted - just before we call notifee.cancelTriggerNotifications() we do have a notifiee.getTriggerNotifications() in a log statement.

@mikehardy
Copy link
Contributor

mikehardy commented Sep 8, 2022

Okay, so we think we know (pending repro)

  • some kind of data in a trigger notification may cause BadParcelableException (what's this data?)
  • on Android 13 real devices (Pixel 4a and 6 pro at least - I have a 4a so should be able to see this with a repro)
  • when getTriggerNotifications is called (it is in all the stacks...)

We need the specific data + Notifee API call to set the trigger notification followed by the getTriggerNotifications call that blows up the repro and then we can all have it under the microscope I think

@liamjones
Copy link
Contributor Author

FYI we're still trying to find a way to reproduce this with our app in an emulator based on the app configuration of users who are hitting the issue. No luck so far.

@ayman-kouzayha
Copy link

Hello Mike, I am Liam's colleague, I was trying to reproduce this bug but unfortunately my attempts were unsuccessful, I tried the following:

  • Generated the data we believe it caused the issue on a virtual device with Android 13
  • Attempted to find a way to upgrade an Android virtual device from Android 12 to 13 but there was no way to do that
  • Attempted to go through an Android 12 virtual device app data files to copy the suspected problematic data to an Android 13 virtual device

We are considering getting a device that we can upgrade and downgrade between Android 12 and 13.

@liamjones
Copy link
Contributor Author

@mikehardy I know Java but I'm not that familiar with the Android APIs - is it possible to retrieve this data from the OS without having to unmarshal it (either via Notifee or directly)? Or is the unmarshalling an automatic part of retrieval from the OS?

I'm just wondering if we could do a new build which retrieves the raw data so we can start having it in the Sentry reports and hopefully get to the bottom of what the trigger is...

@topi-identio
Copy link

topi-identio commented Oct 6, 2022

We got a Pixel 6a for testing the Android 12 to 13 upgrade.

Before Android 13 upgrade

  • We had 2 versions of our app installed on the device:
    • App 1
      • Equal to our production app that our users have gotten the BadParcelableException crash with
    • App 2
      • The same as App 1, but calls cancelAllNotifications on app start before calling getScheduledNotifications getTriggerNotifications
  • Both apps had local notifications scheduled before the upgrade

Results after Android 13 upgrade

  • App 1:

    • Crashed with BadParcelableException as expected
    • The crashing goes away after reinstalling the app
    • When the reinstalled app starts for the first time it immediately displays the new Android 13 notification permission dialog
    • Newly scheduled local notifications work as expected after reinstall
  • App 2:

    • Did not crash
    • Did not ask for the new Android 13 notification permission, likely because notifications were allowed on Android 12
    • Newly scheduled local notifications work as expected
    • Naturally this doesn't test the situation where scheduled local notifications span across sessions

Our conclusion

  • Trying to call getScheduledNotifications with notifications scheduled on Android 12 causes the crash on Android 13
  • Notification objects in Android 12 and 13 look to be identical, so no idea why this happens
  • Downgrading Android from 13 back to 12 to then upgrade again to 13 doesn't seem to be an easy feat because of the Android 13 bootloader upgrade, which means we might not be able to re-reproduce the issue with our phone
  • Our planned workaround for this issues is to check if the user has updated their phone to Android 13 and to then cancel and reschedule all notifications on app start

@mikehardy
Copy link
Contributor

mikehardy commented Oct 6, 2022

Maddening!
Going way back up to my comment here #515 (comment)

I'm still not able to differentiate between cases 2a / 2b but at this point it seems that all Notifee versions are affected, and it's just the Android API 12->13 transition that's the trigger.

One correction: in your conclusion you mention getScheduledNotifications but that API does not exist, I believe you mean getTriggerNotifications?

Possible avenues of pursuit:
1- google issuetracker seems like it should have something by now if Android 13's Parcelable implementation was really at fault, and it does not (I just searched, also stackoverflow still not turning up anything fresh). Very low probability in terms of "useful" as possible avenue
2- Notifee code needs a Parcelable / Serializable audit, where all serializable and parcelable items are checked to make sure they have a CREATOR (per stackoverflow advice?), that they read+write the exact same times in the exact same order. Highest probability of actual solution, but also a fair bit of detail-oriented work, not complicated just detail-oriented
3- Notifee code needs some defensive programming in the error - crashing is always bad form, the exception should result in a promise reject at javascript layer I think? High probably of stopping crash, at least

2 is the real fix I think but would rely on careful implementation and careful inspection of what is going in and out of here

triggerNotificationBundle.putBundle(
"notification", ObjectUtils.bytesToBundle(workDataEntity.getNotification()));
triggerNotificationBundle.putBundle(
"trigger", ObjectUtils.bytesToBundle(workDataEntity.getTrigger()));

3 is mitigation, and should be done as well. How is the crash triggered? It's lazy - the error is in the serialized byte structure somehow but it remains latent until it deserialization is forced to push the object information across the Java / Javascript bridge.

It's happening here - https://github.com/facebook/react-native/blob/40567c21e949ef686367bb39fdb48e34236cbd82/ReactAndroid/src/main/java/com/facebook/react/bridge/Arguments.java#L295

(or, matching the stack above exactly, version located to react-native 0.64: https://github.com/facebook/react-native/blob/400902093aa3ccfc05712a996c592a86f342253a/ReactAndroid/src/main/java/com/facebook/react/bridge/Arguments.java#L291)

And more specifically https://github.com/facebook/react-native/blob/400902093aa3ccfc05712a996c592a86f342253a/ReactAndroid/src/main/java/com/facebook/react/bridge/Arguments.java#L308 where it recursively de-serializes the sub-bundles

So it seems that in our code here:

triggerNotifications.add(triggerNotificationBundle);

...we can trigger the issue while still in a place we can handle errors by probing deserialization in place, specifically copying / reimplementing this

https://github.com/facebook/react-native/blob/400902093aa3ccfc05712a996c592a86f342253a/ReactAndroid/src/main/java/com/facebook/react/bridge/Arguments.java#L289-L308

with the rough idea of "until no more values are Bundles, get all bundle keys, foreach key check type, if type is bundle (recur...)

Then, while still in NotifeeCore's android java code, you catch the exception and bubble it up as Task failure here

result.onComplete(task.getException(), triggerNotifications);

It will come through here

(e, aBundleList) -> NotifeeReactUtils.promiseResolver(promise, e, aBundleList));

and it will reject here

At which point app is not going to crash, and calling code knows that scheduled notifications are broken somehow

Design question for API users: at this point, is it best to purge the offending data? Hard to say. This is effectively data loss, you likely need to educate the user, and if we auto-purge the bad data there is no way to detect the data loss again so you cannot necessarily educate the user.

So it seems best to maybe implement this bad-Bundle-detection, alter the docs to say getTriggerNotifications may reject in rare circumstances such as Android 12 -> Android 13 upgrade, indicating the scheduled trigger database is corrupt. You should notify any users they may need to recreate scheduled notifications, then call cancelTriggerNotifications to clear the corrupt data prior to creating new trigger notifications.

Thoughts?

@mikehardy
Copy link
Contributor

Unfortunately - I need to be clear that my ability to implement+test anything here is limited to comment-based collaboration, just to avoid doubt. I don't have time to engage with this at the code level, but the above comment represents the best thinking I've got on it in available time. Cheers

@mikehardy
Copy link
Contributor

I realize I did not answer these directly:

@mikehardy I know Java but I'm not that familiar with the Android APIs - is it possible to retrieve this data from the OS without having to unmarshal it (either via Notifee or directly)? Or is the unmarshalling an automatic part of retrieval from the OS?

The unmarshal/deserialize is required to go across the react-native bridge from Java to Javascript, it is unavoidable, however it is possible at the Android code level to probe it and/or log it prior to hitting the react-native bridge. Sentry likely has ways to log things so it could be possible to do that - unknown - I know crashlytics does have ways to do it at any rate. Requires some native code, but is possible

It is so painful that this only happens on android 12 -> 13 update. The only way to reliably reproduce this will be to have a never-upgraded-to-13 phone, put trigger notifications in while it's on 12, then update to 13 and DO NOT CANCEL THE NOTIFICATIONS OR UNINSTALL. At that point you've got a reliable source of bad data to probe, but if you uninstall the app or cancel the notifications they'll go poof.

Or I suppose you could find the workmanager database in the device data and pull it out for storage, at which point you could manually copy it in at any time 🤔

Anyway, other than at the native Android level there's no way to probe this data, and it has to be done post-data-fetch / pre-react-native-bridge

@liamjones
Copy link
Contributor Author

We're about to do a new release - for now, we've removed our getTriggerNotifications call as a workaround (it was only for debug logging). We'll at least see if we get any more instances of this error in the new build.

@JK0N
Copy link

JK0N commented Nov 14, 2022

Steps to reproduce:

  1. Launch your app with android 12 emulator, make sure your app schedules some notifications.
  2. Open Android studio / Device File Explorer and copy notifee_core_database, notifee_core_database-shm and notifee_core_database-wal from your emulator (/data/data/< appId >/databases/)
  3. Launch your app in android 13 emulator and upload those step 2. files to the same location using Device File Explorer
  4. getTriggerNotifications should cause crash.. - Profit!

@mikehardy
Copy link
Contributor

@JK0N can you perhaps attach a copy of those notifee databases you have reserved in testing?

@JK0N
Copy link

JK0N commented Nov 15, 2022

notifee-databases.zip

@nateshmbhat
Copy link
Contributor

any solution for this issue ? we're seeing a lot of such crashes lately as more and more devices upgrade to 13

@topi-identio
Copy link

Our temporary workaround for this is to check if the user has Android 13 (API level 33) and if so cancel all notifications on app start. We store a value in LocalStorage so that the cancellation will only be done once. In our case we can then reschedule the notifications since we know what they were supposed to be.

@mikehardy
Copy link
Contributor

None so far - mostly for lack of time. It appears we have the databases you can just drop on to a phone that will reproduce the crash above - it needs triage + workaround based on those

@helenaford helenaford self-assigned this Dec 12, 2022
@helenaford
Copy link
Member

I can take a look this week to see if I can reproduce the error

@batuhansahan
Copy link

So its happening only if we use getTriggerNotifications right. If we get rid of it will be solve the problem for now and the notifications actions like sending/canceling will work without problem ? @liamjones @JK0N

@liamjones
Copy link
Contributor Author

liamjones commented Dec 16, 2022

@batuhansahan Yes, we've been setting and cancelling fine.

Edit: clarification - cancelling all notifications in one go, I haven't tried individual notification cancelling.

@batuhansahan
Copy link

batuhansahan commented Dec 16, 2022

@liamjones after removing getTriggerNotifications app is opened fine except the local notifications not coming anymore and i give the new android 13 feature(allow request permission option with notifee.requestpermissions()) a yes. I dont know why. Gonna debug it. Thanks

@liamjones
Copy link
Contributor Author

@batuhansahan the notifications may be failing to deliver because they're still present and Notifee can't decode them. If you cancel them and reschedule them they should then be in a readable format again.

@batuhansahan
Copy link

batuhansahan commented Dec 16, 2022

@liamjones i did that already, i even tried uninstalling app and installing again than schedule notifications again no change. I will debug hope to find any error logs on debug mode.

edit: Android 13: Creating notification with custom led light blocking notification displaying

@Minishlink
Copy link

A temporary workaround if your logic is to upsert missing notifications after calling getTriggerNotifications is the following patch and function:

export const safeGetTriggerNotifications: typeof notifee.getTriggerNotifications = async () => {
  // https://github.com/invertase/notifee/issues/515
  const userMightHaveBug = Platform.OS === 'android' && Platform.Version >= 33;
  if (!userMightHaveBug) {
    return notifee.getTriggerNotifications();
  }

  try {
    return await notifee.getTriggerNotifications();
  } catch (error) {
    const alreadyTriedNotifeeAndroid13Workaround = await AsyncStorage.getItem(
      AsyncStorageKey.android_triedNotifeeAndroid13Workaround
    );
    if (alreadyTriedNotifeeAndroid13Workaround) {
      throw error;
    }

    await notifee.cancelAllNotifications();
    await AsyncStorage.setItem(
      AsyncStorageKey.android_triedNotifeeAndroid13Workaround,
      new Date().toISOString()
    );
    return notifee.getTriggerNotifications();
  }
};
diff --git a/node_modules/@notifee/react-native/android/src/main/java/io/invertase/notifee/NotifeeReactUtils.java b/node_modules/@notifee/react-native/android/src/main/java/io/invertase/notifee/NotifeeReactUtils.java
index b60e6d4..eed80fe 100644
--- a/node_modules/@notifee/react-native/android/src/main/java/io/invertase/notifee/NotifeeReactUtils.java
+++ b/node_modules/@notifee/react-native/android/src/main/java/io/invertase/notifee/NotifeeReactUtils.java
@@ -66,11 +70,15 @@ class NotifeeReactUtils {
       // TODO custom error class with message/code
       promise.reject(e);
     } else {
-      WritableArray writableArray = Arguments.createArray();
-      for (Bundle bundle : bundleList) {
-        writableArray.pushMap(Arguments.fromBundle(bundle));
+      try {
+        WritableArray writableArray = Arguments.createArray();
+        for (Bundle bundle : bundleList) {
+          writableArray.pushMap(Arguments.fromBundle(bundle));
+        }
+        promise.resolve(writableArray);
+      } catch (Exception error) {
+        promise.reject(error);
       }
-      promise.resolve(writableArray);
     }
   }
 

@github-actions
Copy link

Hello 👋, to help manage issues we automatically close stale issues.

This issue has been automatically marked as stale because it has not had activity for quite some time.Has this issue been fixed, or does it still require attention?

This issue will be closed in 15 days if no further activity occurs.

Thank you for your contributions.

@github-actions github-actions bot closed this as not planned Won't fix, can't repro, duplicate, stale Feb 15, 2023
@N-Pu
Copy link

N-Pu commented May 1, 2023

Good day. I have an issue with my project - suddenly when I turn off my app and opened it - it crashes and gives me this error:

FATAL EXCEPTION: main
                                                                                                    Process: com.example.animeapp, PID: 6468
                                                                                                    java.lang.IllegalArgumentException: Parcel: unknown type for value Color(0.8, 0.13333334, 0.96862745, 1.0, sRGB IEC61966-2.1)
                                                                                                    	at android.os.Parcel.getValueType(Parcel.java:2409)
                                                                                                    	at android.os.Parcel.writeValue(Parcel.java:2308)
                                                                                                    	at android.os.Parcel.writeList(Parcel.java:1382)
                                                                                                    	at android.os.Parcel.writeValue(Parcel.java:2460)
                                                                                                    	at android.os.Parcel.writeValue(Parcel.java:2316)
                                                                                                    	at android.os.Parcel.writeList(Parcel.java:1382)
                                                                                                    	at android.os.Parcel.writeValue(Parcel.java:2460)
                                                                                                    	at android.os.Parcel.writeValue(Parcel.java:2316)
                                                                                                    	at android.os.Parcel.writeMapInternal(Parcel.java:1233)
                                                                                                    	at android.os.Parcel.writeMap(Parcel.java:1215)
                                                                                                    	at android.os.Parcel.writeValue(Parcel.java:2430)
                                                                                                    	at android.os.Parcel.writeValue(Parcel.java:2316)
                                                                                                    	at android.os.Parcel.writeMapInternal(Parcel.java:1233)
                                                                                                    	at android.os.Parcel.writeMap(Parcel.java:1215)
                                                                                                    	at android.os.Parcel.writeValue(Parcel.java:2430)
                                                                                                    	at android.os.Parcel.writeValue(Parcel.java:2316)
                                                                                                    	at android.os.Parcel.writeList(Parcel.java:1382)
                                                                                                    	at android.os.Parcel.writeValue(Parcel.java:2460)
                                                                                                    	at android.os.Parcel.writeValue(Parcel.java:2316)
                                                                                                    	at android.os.Parcel.writeMapInternal(Parcel.java:1233)
                                                                                                    	at android.os.Parcel.writeMap(Parcel.java:1215)
                                                                                                    	at android.os.Parcel.writeValue(Parcel.java:2430)
                                                                                                    	at android.os.Parcel.writeValue(Parcel.java:2316)
                                                                                                    	at android.os.Parcel.writeList(Parcel.java:1382)
                                                                                                    	at android.os.Parcel.writeValue(Parcel.java:2460)
                                                                                                    	at android.os.Parcel.writeValue(Parcel.java:2316)
                                                                                                    	at android.os.Parcel.writeMapInternal(Parcel.java:1233)
                                                                                                    	at android.os.Parcel.writeMap(Parcel.java:1215)
                                                                                                    	at android.os.Parcel.writeValue(Parcel.java:2430)
                                                                                                    	at android.os.Parcel.writeValue(Parcel.java:2316)
                                                                                                    	at android.os.Parcel.writeMapInternal(Parcel.java:1233)
                                                                                                    	at android.os.Parcel.writeMap(Parcel.java:1215)
                                                                                                    	at android.os.Parcel.writeValue(Parcel.java:2430)
                                                                                                    	at android.os.Parcel.writeValue(Parcel.java:2316)
                                                                                                    	at android.os.Parcel.writeList(Parcel.java:1382)
                                                                                                    	at android.os.Parcel.writeValue(Parcel.java:2460)
                                                                                                    	at android.os.Parcel.writeValue(Parcel.java:2316)
                                                                                                    	at android.os.Parcel.writeArrayMapInternal(Parcel.java:1265)
                                                                                                    	at android.os.BaseBundle.writeToParcelInner(BaseBundle.java:1802)
                                                                                                    	at android.os.Bundle.writeToParcel(Bundle.java:1389)
                                                                                                    	at android.os.Parcel.writeBundle(Parcel.java:1334)
                                                                                                    	at android.os.Parcel.writeValue(Parcel.java:2433)
                                                                                                    	at android.os.Parcel.writeValue(Parcel.java:2323)
                                                                                                    	at android.os.Parcel.writeArrayMapInternal(Parcel.java:1265)
                                                                                                    	at android.os.BaseBundle.writeToParcelInner(BaseBundle.java:1802)
                                                                                                    	at android.os.Bundle.writeToParcel(Bundle.java:1389)
                                                                                                    	at android.os.Parcel.writeBundle(Parcel.java:1334)
                                                                                                    	at android.os.Parcel.writeValue(Parcel.java:2433)
                                                                                                    	at android.os.Parcel.writeValue(Parcel.java:2323)
                                                                                                    	at android.os.BaseBundle.dumpStats(BaseBundle.java:1874)
                                                                                                    	at android.os.BaseBundle.dumpStats(BaseBundle.java:1911)
                                                                                                    	at android.app.servertransaction.PendingTransactionActions$StopInfo.run(PendingTransactionActions.java:150)
                                                                                                    	at android.os.Handler.handleCallback(Handler.java:942)
                                                                                                    	at android.os.Handler.dispatchMessage(Handler.java:99)
                                                                                                    	at android.os.Looper.loopOnce(Looper.java:201)
                                                                                                    	at android.os.Looper.loop(Looper.java:288)
                                                                                                    	at android.app.ActivityThread.main(ActivityThread.java:7872)
                                                                                                    	at java.lang.reflect.Method.invoke(Native Method)
                                                                                                    	at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548)
                                                                                                    	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:936)

Maybe somebody had the same problem.

@alwex
Copy link

alwex commented Jun 10, 2023

Still having this issue at this date, as a workaround I have implemented a simple hook that cancel scheduled notifications when android 13 is detected for the first time on the app. Here it is in case it can help:

import {useEffect} from 'react'
import {Platform} from 'react-native'
import {cancelAllNotifications} from '~/components/notifications/notifications'
import {getStorage, setStorage} from '~/utils/storage'

const STORAGE_KEY = 'hasDeletedAllNotificationsBecauseOfAndroid13'

export const useFixAndroid13NotificationIssue = () => {
  useEffect(() => {
    if (Platform.OS === 'android' && Platform.Version >= 33) {
      const done = getStorage(STORAGE_KEY, false)
      if (!done) {
        console.log('cancel pending notifications')
        cancelAllNotifications()
        setStorage(STORAGE_KEY, true)
      }
    }
  }, [])
}

for the utility functions, I am using MMKV and a simple wrapper around notifee:

const storage = new MMKV()

export const getStorage = <T>(key: string, defaultValue: T) => {
  const value = storage.getString(key) as any
  if (value === undefined) {
    return defaultValue
  }

  return JSON.parse(value) as T
}

export const setStorage = (key: string, value: any) => {
  storage.set(key, JSON.stringify(value))
}
export const cancelAllNotifications = async () => {
  await notifee.cancelAllNotifications()
}

Tested with the database provided by @JK0N, thank you all for the investigations on this annoying issue.

@Pingou
Copy link

Pingou commented Aug 5, 2023

@mikehardy Can we reopen? Same issue on last version. Perhaps we could add something to the doc if it can't be fixed in the library.

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

No branches or pull requests