MaikuB / flutter_local_notifications

A Flutter plugin for displaying local notifications on Android, iOS, macOS and Linux
2.46k stars 1.4k forks source link

Unable to start receiver com.dexterous.flutterlocalnotifications.ScheduledNotificationReceiver #2223

Open gibbsvjy007 opened 9 months ago

gibbsvjy007 commented 9 months ago

We are getting the same error suddenly, we did not change any code since many versions regarding scheduling local notification. Since last two version after upgrading the plugin to 16.0.0 we are getting the crash event for many users in firebase crashlytics. Any idea how to solve this error ? this is very important error as it has decreased our crash free users to almost 50%. Let me know if you have any idea on this.

Fatal Exception: java.lang.RuntimeException Unable to start receiver com.dexterous.flutterlocalnotifications.ScheduledNotificationBootReceiver: java.lang.RuntimeException: Missing type parameter.

image

_Originally posted by @gibbsvjy007 in https://github.com/MaikuB/flutter_local_notifications/issues/408#issuecomment-1903549411_

Fatal Exception: java.lang.RuntimeException: Unable to start receiver com.dexterous.flutterlocalnotifications.ScheduledNotificationBootReceiver: java.lang.RuntimeException: Missing type parameter.
       at android.app.ActivityThread.handleReceiver(ActivityThread.java:4903)
       at android.app.ActivityThread.-$$Nest$mhandleReceiver()
       at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2420)
       at android.os.Handler.dispatchMessage(Handler.java:106)
       at android.os.Looper.loopOnce(Looper.java:226)
       at android.os.Looper.loop(Looper.java:313)
       at android.app.ActivityThread.main(ActivityThread.java:8757)
       at java.lang.reflect.Method.invoke(Method.java)
       at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:571)
       at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1067)
Caused by java.lang.RuntimeException: Missing type parameter.
       at dc.a.d(SourceFile:1)
       at dc.a.<init>(SourceFile:1)
       at com.dexterous.flutterlocalnotifications.FlutterLocalNotificationsPlugin$a.<init>()
       at com.dexterous.flutterlocalnotifications.FlutterLocalNotificationsPlugin.loadScheduledNotifications(:25)
       at com.dexterous.flutterlocalnotifications.FlutterLocalNotificationsPlugin.rescheduleNotifications()
       at com.dexterous.flutterlocalnotifications.ScheduledNotificationBootReceiver.onReceive(:38)
       at android.app.ActivityThread.handleReceiver(ActivityThread.java:4894)
       at android.app.ActivityThread.-$$Nest$mhandleReceiver()
       at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2420)
       at android.os.Handler.dispatchMessage(Handler.java:106)
       at android.os.Looper.loopOnce(Looper.java:226)
       at android.os.Looper.loop(Looper.java:313)
       at android.app.ActivityThread.main(ActivityThread.java:8757)
       at java.lang.reflect.Method.invoke(Method.java)
       at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:571)
       at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1067)

@MaikuB

dluksza commented 9 months ago

This turned out to be a misconfiguration of progurd rules. After adding:

# Retain generic signatures of TypeToken and its subclasses with R8 version 3.0 and higher.
-keep,allowobfuscation,allowshrinking class com.google.gson.reflect.TypeToken
-keep,allowobfuscation,allowshrinking class * extends com.google.gson.reflect.TypeToken

The error was not occurring anymore. The whole proguard configuration can be found here: https://github.com/MaikuB/flutter_local_notifications/blob/master/flutter_local_notifications/example/android/app/proguard-rules.pro

MaikuB commented 9 months ago

Thanks @dluksza. My initial thought was it was to do with the rules given the error on missing type though I noticed you weren't the original poster. Did you help @gibbsvjy007 on this? Wanted to confirm to see if the issue can be closed

dluksza commented 9 months ago

I've just noticed the same problem in my app and found this issue in google. Haven't helped anyone, just solved it for myself and updated on the issue.

gibbsvjy007 commented 9 months ago

@dluksza i will apply above solution and let you know

MaikuB commented 9 months ago

Note that my understanding is that if it was indeed an issue to do with Proguard rules then it's not a retroactive fix as it would mean you have corrupt data that would still remain. Perhaps @dluksza can confirm having had firsthand experience

dluksza commented 9 months ago

Unfortunately, I did reinstall the app during my testing, so can't confirm if it's persistent. None of my users has complained (yet) about the issue, so can't tell how bad it is.

dluksza commented 9 months ago

IMO, serialization should not be a problem, as JSON does not have any type of information. Only deserialization requires matching types. I hope we're here on a safe site and won't need any "data migration" to recover from this issue.

under3415 commented 9 months ago

I am getting this issue since upgrading AGP to 8. From what I could understand It has to do with AGP8 enabling R8 full mode by default. This article is also helpful.

Adding different suggested rules to proguard-rules.pro did not resolve the issue, so I had to resort to adding below to gradle.properties:

android.enableR8.fullMode = false

This fixes the issue but is probably not ideal.

I was trying to replicate the issue in the flutter_local_notifications example project, but I get a different issue from my project.

Steps to replicate:

  1. In settings.gradle upgrade Kotlin and AGP (if you are using the old buildscript syntax then do it in build.gradle instead or migrate away from buildscript syntax).
plugins {
    id "dev.flutter.flutter-plugin-loader" version "1.0.0"
     id "com.android.application" version "8.2.2" apply false
    id "org.jetbrains.kotlin.android" version "1.9.22" apply false
}
  1. In gradle-wrapper.properties upgrade Gradle:

    distributionUrl=https\://services.gradle.org/distributions/gradle-8.2.1-all.zip
  2. In "app" build.gradle add this to buildTypes so you can test it in debug mode:

    debug {
        //added so I can test this in debug
        minifyEnabled true 
    }
  3. Run the project

The error

In example project I am getting this build error

ERROR: R8: Library class android.content.res.XmlResourceParser implements program class org.xmlpull.v1.XmlPullParser

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':app:minifyDebugWithR8'.
> A failure occurred while executing com.android.build.gradle.internal.tasks.R8Task$R8Runnable
   > Compilation failed to complete

* Try:
> Run with --stacktrace option to get the stack trace.
> Run with --info or --debug option to get more log output.
> Run with --scan to get full insights.
> Get more help at https://help.gradle.org.

BUILD FAILED in 5s

In my project I am not getting this issue. Instead the project builds, but attempting to set up notifications results in below error. In this case calling await flutterLocalNotificationsPlugin.cancelAll();:

PlatformException (PlatformException(error, Missing type parameter., null, java.lang.RuntimeException: Missing type parameter.
    at com.google.gson.reflect.TypeToken.getSuperclassTypeParameter(TypeToken.java:84)
    at com.google.gson.reflect.TypeToken.<init>(TypeToken.java:62)
    at com.dexterous.flutterlocalnotifications.FlutterLocalNotificationsPlugin$1.<init>(FlutterLocalNotificationsPlugin.java:497)
    at com.dexterous.flutterlocalnotifications.FlutterLocalNotificationsPlugin.loadScheduledNotifications(FlutterLocalNotificationsPlugin.java:497)
    at com.dexterous.flutterlocalnotifications.FlutterLocalNotificationsPlugin.cancelAllNotifications(FlutterLocalNotificationsPlugin.java:1748)
    at com.dexterous.flutterlocalnotifications.FlutterLocalNotificationsPlugin.onMethodCall(FlutterLocalNotificationsPlugin.java:1451)
    at io.flutter.plugin.common.MethodChannel$IncomingMethodCallHandler.onMessage(MethodChannel.java:267)
    at io.flutter.embedding.engine.dart.DartMessenger.invokeHandler(DartMessenger.java:295)
    at io.flutter.embedding.engine.dart.DartMessenger.lambda$dispatchMessageToQueue$0(DartMessenger.java:322)
    at io.flutter.embedding.engine.dart.DartMessenger.$r8$lambda$2j2MERcK825A5j1fv5sZ7xB2Iuo(DartMessenger.java:0)
    at io.flutter.embedding.engine.dart.DartMessenger$$ExternalSyntheticLambda0.run(R8$$SyntheticClass:0)
    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)
))

The workaround

Adding this line to gradle.properties resolves the issue in both cases:

android.enableR8.fullMode = false

Conclusion

I don't understand how this all hangs together in flutter, but perhaps the plugin should make changes or request changes to default proguard rules from R8 guys so that the plugin can be compatible with AGP8 more aggressive R8?

Let me know if you want me to raise a separate bug.

vbuberen commented 8 months ago

Yes, the issue comes from AGP 8 which indeed has R8's fullMode turned on by default. So the project needs an update for ProGuard rules.

ERROR: R8: Library class android.content.res.XmlResourceParser implements program class org.xmlpull.v1.XmlPullParser

For this issue you need to add the following line into ProGuard rules:

-keep class org.xmlpull.** { *; }

PlatformException (PlatformException(error, Missing type parameter., null, java.lang.RuntimeException: Missing type parameter. at com.google.gson.reflect.TypeToken.getSuperclassTypeParameter(TypeToken.java:84)

As to this one be sure to check that your ProGuard rules include all rules provided by Gson library: https://github.com/google/gson/blob/main/examples/android-proguard-example/proguard.cfg

Specifically, be sure to add these 2 lines into your set or ProGuard rules. They were already mentioned above by another person:

# Retain generic signatures of TypeToken and its subclasses with R8 version 3.0 and higher.
-keep,allowobfuscation,allowshrinking class com.google.gson.reflect.TypeToken
-keep,allowobfuscation,allowshrinking class * extends com.google.gson.reflect.TypeToken

With correct set of rules you won't need to turn off fullMode for R8.