gdelataillade / alarm

A Flutter plugin to easily manage alarms on iOS and Android
https://pub.dev/packages/alarm
MIT License
132 stars 86 forks source link

iOS Crash EXC_BAD_ACCESS #194

Closed suhailbilalw closed 5 months ago

suhailbilalw commented 6 months ago

Crashed: com.gdelataillade.alarm.resourceAccessQueue EXC_BAD_ACCESS KERN_INVALID_ADDRESS 0x0000000000000000 image

suhailbilalw commented 6 months ago

`StreamController callbackController = StreamController.broadcast();

subscription ??= Alarm.ringStream.stream.listen((event) async { if (await Alarm.isRinging(event.id)) { if (callbackController.hasListener) callbackController.sink.add(event); } });`

gdelataillade commented 6 months ago

Hi @suhailbilalw

1) How often does the crash happen in your Crashlytics ? 2) Do you know if the crash happens at the moment the alarm is set or at the moment the alarm rings ? 3) Do you think it's related to your callbackController ?

suhailbilalw commented 6 months ago

Hi @gdelataillade

  1. I have four testers there are already 10 events.
  2. I think when alarm rings. I'm trying to capture only ring events.
  3. I mentioned my callbackController because I saw a related issue in this package having problem with broadcast stream, I need your help and support to figure out if this can cause crash.
gdelataillade commented 6 months ago

Hi @suhailbilalw

To fix your issue make sure you use the await keyword when you call Alarm.set. I think the issue happens when there are multiple alarms set at the same time. What do you think ?

suhailbilalw commented 6 months ago

hello @gdelataillade void scheduleAlarms() { unawaited(() async { var now = DateTime.now(); for (var alarm in FFAppState().reminders) { if (alarm.repeat == Repeat.once && alarm.dateTime!.isAfter(now)) { await Alarm.set( alarmSettings: AlarmSettings( id: alarm.id, dateTime: alarm.dateTime!, assetAudioPath: 'assets/audios/prayer_end.mp3', loopAudio: true, vibrate: true, volume: 1, fadeDuration: 3.0, notificationTitle: 'Pray Now Reminder', notificationBody: alarm.title, enableNotificationOnKill: true, ), ); } else if (alarm.repeat == Repeat.daily) { for (var i = 0; i < 7; i++) { var dateTime = DateTime.now() .copyWith( hour: alarm.dateTime!.hour, minute: alarm.dateTime!.minute, second: alarm.dateTime!.second, microsecond: 0, millisecond: 0, ) .add(Duration(days: i)); if (dateTime.isAfter(DateTime.now())) { await Alarm.set( alarmSettings: AlarmSettings( id: alarm.id + i, dateTime: dateTime, assetAudioPath: 'assets/audios/prayer_end.mp3', loopAudio: true, vibrate: true, volume: 1, fadeDuration: 3.0, notificationTitle: 'Pray Now Reminder', notificationBody: alarm.title, enableNotificationOnKill: true, ), ); } } } } }()); } this is my code for setting the alarm. Please let me know if you see any problem with it.

gdelataillade commented 6 months ago

@suhailbilalw I don't see any problem with your code. Have you carefully followed the iOS setup steps in the README ?

suhailbilalw commented 6 months ago

Hello @gdelataillade Yeah, I'm sure about it. Because sometimes it's running perfectly fine. Crash is not happening everytime.

gdelataillade commented 6 months ago

@suhailbilalw

Why did you use the unawaited keyword ? It might be the cause of the crash. Here's an updated version of your code:


Future<void> scheduleAlarms() async {
  var now = DateTime.now();
  for (var alarm in FFAppState().reminders) {
  // rest of your code here...
}

What do you think ?

suhailbilalw commented 6 months ago

@gdelataillade I'll try if this solves the problem, will get back to you.

suhailbilalw commented 6 months ago

@gdelataillade Can this be a cause to the crash?

@override
  void didChangeAppLifecycleState(AppLifecycleState state) async {
    super.didChangeAppLifecycleState(state);
    // _appLifecycleState = state;
    switch (state) {
      case AppLifecycleState.resumed:
        final alarms = Alarm.getAlarms();
        for (var alarm in alarms) {
          if (alarm.id > 0) await Alarm.stop(alarm.id);
        }

        break;
      case AppLifecycleState.paused:
        if (!FFAppState().userIsPraying) {
          await scheduleAlarms();
        }
        break;
      case AppLifecycleState.detached:
      case AppLifecycleState.inactive:
      case AppLifecycleState.hidden:
    }
  }
gdelataillade commented 6 months ago

I don't think so.

suhailbilalw commented 6 months ago

@gdelataillade I got same error today even after removing unawaited function. I don't think it is the root cause.

image

suhailbilalw commented 6 months ago

Hello @gdelataillade I removed stream subscription as well. but error still persists. it is on stopSilentSound, setAlarm and stopAlarm functions

image

Screenshot 2024-05-06 091539

gdelataillade commented 6 months ago

Hi @suhailbilalw

Thanks for the details. I'll try to find out what is causing the issue. Maybe I'm wrong but it looks like you are the only one with the issue. Maybe you could keep trying to edit your code to see what part is causing the issue.

Thank you and sorry for the inconvenience.

jhonatan-3a commented 6 months ago

Hi @suhailbilalw

To fix your issue make sure you use the await keyword when you call Alarm.set. I think the issue happens when there are multiple alarms set at the same time. What do you think ?

This definetly happened to me and that should be noted somewhere in the plugin general issues, i fixed it already but its happening again now with the alarm.stop even thou i am awaiting them

jhonatan-3a commented 6 months ago

@gdelataillade Can this be a cause to the crash?

@override
  void didChangeAppLifecycleState(AppLifecycleState state) async {
    super.didChangeAppLifecycleState(state);
    // _appLifecycleState = state;
    switch (state) {
      case AppLifecycleState.resumed:
        final alarms = Alarm.getAlarms();
        for (var alarm in alarms) {
          if (alarm.id > 0) await Alarm.stop(alarm.id);
        }

        break;
      case AppLifecycleState.paused:
        if (!FFAppState().userIsPraying) {
          await scheduleAlarms();
        }
        break;
      case AppLifecycleState.detached:
      case AppLifecycleState.inactive:
      case AppLifecycleState.hidden:
    }
  }

if you lyfecycle method gets called twice, ie, user foreground twice the app fast and the first alarm stop hasnt finished trying to stop it again could be an issue

suhailbilalw commented 6 months ago

@gdelataillade Can this be a cause to the crash?

@override
  void didChangeAppLifecycleState(AppLifecycleState state) async {
    super.didChangeAppLifecycleState(state);
    // _appLifecycleState = state;
    switch (state) {
      case AppLifecycleState.resumed:
        final alarms = Alarm.getAlarms();
        for (var alarm in alarms) {
          if (alarm.id > 0) await Alarm.stop(alarm.id);
        }

        break;
      case AppLifecycleState.paused:
        if (!FFAppState().userIsPraying) {
          await scheduleAlarms();
        }
        break;
      case AppLifecycleState.detached:
      case AppLifecycleState.inactive:
      case AppLifecycleState.hidden:
    }
  }

if you lyfecycle method gets called twice, ie, user foreground twice the app fast and the first alarm stop hasnt finished trying to stop it again could be an issue

Hi @jhonatan-3a ! this issue is emerging from three different functions, check this https://github.com/gdelataillade/alarm/issues/194#issuecomment-2095141323 so I'm sure my code is fine.

also this package documentation says ===> To avoid unexpected behaviours, if you set an alarm for the same time, down to the second, as an existing one, the new alarm will replace the existing one.