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

Crash: Attempt to invoke virtual method 'boolean com.dexterous.flutterlocalnotifications.models.ScheduleMode.useAllowWhileIdle()' on a null object reference #2136

Closed
RuchiPurohit opened this issue Oct 27, 2023 · 6 comments · Fixed by #2199

Comments

@RuchiPurohit
Copy link
Contributor

I have updated to version 16.1.0 from version 9.9.1, and I am getting hundreds of background crashes everyday. I am using zonedSchedule method. I have followed all the android setup guidelines in the readme section and have added the Proguard rules.

I am in a fix, can't think of anything else to do. Please help.

This is the background crash I am getting.

Exception java.lang.RuntimeException: Unable to start receiver com.dexterous.flutterlocalnotifications.ScheduledNotificationBootReceiver: java.lang.NullPointerException: Attempt to invoke virtual method 'boolean com.dexterous.flutterlocalnotifications.models.ScheduleMode.useAllowWhileIdle()' on a null object reference
  at android.app.ActivityThread.handleReceiver (ActivityThread.java:4556)
  at android.app.ActivityThread.-$$Nest$mhandleReceiver
  at android.app.ActivityThread$H.handleMessage (ActivityThread.java:2304)
  at android.os.Handler.dispatchMessage (Handler.java:106)
  at android.os.Looper.loopOnce (Looper.java:240)
  at android.os.Looper.loop (Looper.java:351)
  at android.app.ActivityThread.main (ActivityThread.java:8377)
  at java.lang.reflect.Method.invoke
  at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run (RuntimeInit.java:584)
  at com.android.internal.os.ZygoteInit.main (ZygoteInit.java:1013)
Caused by java.lang.NullPointerException: Attempt to invoke virtual method 'boolean com.dexterous.flutterlocalnotifications.models.ScheduleMode.useAllowWhileIdle()' on a null object reference
  at com.dexterous.flutterlocalnotifications.FlutterLocalNotificationsPlugin.setupAlarm
  at com.dexterous.flutterlocalnotifications.FlutterLocalNotificationsPlugin.zonedScheduleNotification
  at com.dexterous.flutterlocalnotifications.FlutterLocalNotificationsPlugin.rescheduleNotifications
  at com.dexterous.flutterlocalnotifications.ScheduledNotificationBootReceiver.onReceive
  at android.app.ActivityThread.handleReceiver (ActivityThread.java:4540)

In the current version of my app with 16.1.0 version of this library, I have added USE_EXACT_ALARM permission as below. Have followed the android guidelines. [Previous version of my app was using 9.9.1 version of this library, and never faced any crashes.]

<uses-permission android:name="android.permission.USE_EXACT_ALARM" />
 <uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM"
 	 android:maxSdkVersion="32" />

multiDexEnabled is true and targeting sdk 33

       minSdkVersion 22
        targetSdkVersion 33
        multiDexEnabled true

My zonedSchedule method looks like this

var timezonedTime = tz.TZDateTime.from(
    notificationTime,
    tz.local,
  );

  await flutterLocalNotificationsPlugin.zonedSchedule(
      getNotificationIdFromDB(notificationId),
      title,
      body,
      timezonedTime,
      platformChannelSpecifics,
      uiLocalNotificationDateInterpretation:
          UILocalNotificationDateInterpretation.absoluteTime,
      androidScheduleMode: AndroidScheduleMode.exactAllowWhileIdle, // <- changed from androidAllowWhileIdle: true
      payload: habitId);

AndroidManifest.xml looks like this

<receiver android:name="com.dexterous.flutterlocalnotifications.ScheduledNotificationBootReceiver" android:exported="false">
            <intent-filter>
                <action android:name="android.intent.action.BOOT_COMPLETED"/>
                <action android:name="android.intent.action.MY_PACKAGE_REPLACED"/>
                <action android:name="android.intent.action.QUICKBOOT_POWERON" />
                <action android:name="com.htc.intent.action.QUICKBOOT_POWERON"/>
            </intent-filter>
        </receiver>
        <receiver android:name="com.dexterous.flutterlocalnotifications.ScheduledNotificationReceiver" android:exported="false" />
        <receiver android:exported="false" android:name="com.dexterous.flutterlocalnotifications.ActionBroadcastReceiver" />

<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
    <uses-permission android:name="android.permission.INTERNET"/>
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.USE_EXACT_ALARM" />
    <uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM"
 	 android:maxSdkVersion="32" />
    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
    <uses-permission android:name="android.permission.USE_FULL_SCREEN_INTENT" />
    <uses-permission android:name="com.google.android.gms.permission.AD_ID" tools:node="remove"/>
@MaikuB
Copy link
Owner

MaikuB commented Nov 9, 2023

Do you have info on what is the earliest version of the plugin that your app used? I can't see how this is has happened unless at some point, your app didn't configure Proguard rules properly and caused the value for androidAllowWhileIdle to not be saved properly, hence the null exceptions. Should this be the case, it may be possible you need to consider forking this plugin to catch and deal with this scenario

@RuchiPurohit
Copy link
Contributor Author

Do you have info on what is the earliest version of the plugin that your app used? I can't see how this is has happened unless at some point, your app didn't configure Proguard rules properly and caused the value for androidAllowWhileIdle to not be saved properly, hence the null exceptions. Should this be the case, it may be possible you need to consider forking this plugin to catch and deal with this scenario

As far as I could see in my releases, the very first version added was 3.0.3.

I have forked the plugin and and handled the null case, same as you had done for #2033 and #2041. This solved my issue. Currently not getting any crashes with the forked plugin.

I have added null check in setupAlarm() method which is being called from zonedScheduleNotification() in FlutterLocalNotificationsPlugin.java. It would be really helpful if this null check code can be added in setupAlarm method in future release of the plugin.

private static void setupAlarm(
      NotificationDetails notificationDetails,
      AlarmManager alarmManager,
      long epochMilli,
      PendingIntent pendingIntent) {
    
    // ************ added null check here ***********//
    if (notificationDetails.scheduleMode == null) {
      notificationDetails.scheduleMode = ScheduleMode.inexact;
    }
   // ****************//

    if (notificationDetails.scheduleMode.useAllowWhileIdle()) {
      setupAllowWhileIdleAlarm(notificationDetails, alarmManager, epochMilli, pendingIntent);
    } else {
      if (notificationDetails.scheduleMode.useExactAlarm()) {
        checkCanScheduleExactAlarms(alarmManager);
        AlarmManagerCompat.setExact(
            alarmManager, AlarmManager.RTC_WAKEUP, epochMilli, pendingIntent);
      } else if (notificationDetails.scheduleMode.useAlarmClock()) {
        AlarmManagerCompat.setAlarmClock(alarmManager, epochMilli, pendingIntent, pendingIntent);
      } else {
        alarmManager.set(AlarmManager.RTC_WAKEUP, epochMilli, pendingIntent);
      }
    }
  }

@MaikuB
Copy link
Owner

MaikuB commented Nov 11, 2023

It would be really helpful if this null check code can be added in setupAlarm method in future release of the plugin

Whilst I understand the reason why you say that, this won't be done as this is an issue due to misconfiguration that shouldn't have happened otherwise as the allow while idle property was required and code was added that would have mapped an existing value to the new schedule mode property. Trying to add it to the plugin affects all users of the plugin where it's not possible to know whether they had set it to true or false. Putting a code change in would also hide that there was a misconfiguration that should devs should be testing in an app before releasing to users as well and testing that updating one version of an app to a new version should be part of this process.

By the way you will need to revisit your code change to ensure it correctly maps the schedule mode property based on your app's choice for the allow while idle property

@MaikuB
Copy link
Owner

MaikuB commented Nov 12, 2023

Hmm on second thought, open to having this change in as there use to be logic to coalesce a null allow while idle value though in theory that shouldn't happen. Would you be open to submitting a PR on this?

@RuchiPurohit
Copy link
Contributor Author

Hmm on second thought, open to having this change in as there use to be logic to coalesce a null allow while idle value though in theory that shouldn't happen. Would you be open to submitting a PR on this?

Thanks a lot. This will be super helpful. I will submit a PR on this.

@RuchiPurohit
Copy link
Contributor Author

I have created a PR for this.
#2199

Sorry for the delay. I was stuck with few issues. Really appreciate your help.

Hmm on second thought, open to having this change in as there use to be logic to coalesce a null allow while idle value though in theory that shouldn't happen. Would you be open to submitting a PR on this?

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