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

Clicking on notification does not invoke a callback in ringStream #153

Closed arungopalan closed 6 months ago

arungopalan commented 9 months ago

Alarm plugin version Latest version

Describe the bug If the app has been sent to the background, sometimes clicking on an alarm notification does not call the Stream subscription callback

Instead I see the following error in the logcat W/FlutterJNI(13027): Tried to send a platform message to Flutter, but FlutterJNI was detached from native C++. Could not send. Channel: com.gdelataillade.alarm/alarm. Response ID: 3

Has anyone seen this behavior?

I am trying to make a small project to reproduce this behavior. But just wanted to see if someone else has seen this?

gdelataillade commented 9 months ago

Hi @arungopalan

Thanks for your interest in the plugin.

I never heard of this issue before. I'll take a close look at it as soon as I find the time. Let me know if you if you find something.

vitalii-t12 commented 8 months ago

I'm using Firebase services in my app with FirebaseMessaging. I found out, that the ringStream doesn't get invokend when I'm setting up the background message handler FirebaseMessaging.onBackgroundMessage(_firebaseMessagingBackgroundHandler).

I did a small test:

  1. I'm running the app with FirebaseMessaging.onBackgroundMessage(_firebaseMessagingBackgroundHandler) in main function. In logs I even get I/FLTFireMsgService(10382): FlutterFirebaseMessagingBackgroundService started!.
  2. I trigger the alarm and get notification only. ringStream doesn't receive any data, as a result no RingScreen is triggered.
  3. Alarm is still on.
  4. I Remove the app from app manager with alarm still ON.
  5. I click on alarm notification and app opens with the RingScreen on. (This time I don't get the I/FLTFireMsgService(10382): FlutterFirebaseMessagingBackgroundService started! message, which means, that onBackgroundMessage handler was set up on the first run. If I close the app and restart it the FlutterFirebaseMessagingBackgroundService gets restarted as well and I have to do the same procedure again to get data in ringStream. Spent multiple hours trying to figure out what went wrong, but no result.
gdelataillade commented 8 months ago

Hi @vitalii-t12

Thanks for sharing your issue.

It looks like there is a conflict between my plugin and Firebase Messaging. If you could answer the following questions it could help me a lot identify the issue:

1) Does the ringStream work properly if you don't call FirebaseMessaging.onBackgroundMessage ? 2) Do you have any relevant logs ? Any error or warning ? 3) What device do you use exactly ? And what Android version ? 4) Have you tried to schedule the alarm with different ids ? 5) Do you initialize FMC first ? Or alarm service first ? Have you tried both cases ?

Thanks in advance.

vitalii-t12 commented 8 months ago

Hi, @gdelataillade Sorry for late reply. Have been very busy the whole week. So, let's go one by one:

  1. Yes, it works perfectly good when I don't call FirebaseMessaging.onBackgroundMessage.

  2. No errors or warnings. The only log I get is when I call FirebaseMessaging.onBackgroundMessage:

    I/FLTFireMsgService( 5549): FlutterFirebaseMessagingBackgroundService started!
  3. Device: Pixel 6 Pro Android version: 13 I think, it could be relevat for other devices as well.

  4. Yes, but it didn't help

  5. I have tried initializing in different order and from different places (main function or Widgets). But i got the same result.

I'm using the example app and just added Firebase to it, nothing else. Here is a sample video describing the bug: Screencast from 03-09-2024 08:03:10 PM.webm

Video timing 2:00 when I kill the app WITH ALARM RINGING and then click on notification, it works perfectly well. But in this case I don't get the log that FlutterFirebaseMessagingBackgroundService is initialized:

I/FLTFireMsgService( 5549): FlutterFirebaseMessagingBackgroundService started!

You can see this at timing 3:27 the message with FlutterFirebaseMessagingBackgroundService and when I close the app from task manager and click on notification I get only my test log (timing 3:40 the logs with #myTest) I could conclude, that it gets broken only when FlutterFirebaseMessagingBackgroundService is initialized. When you start the app normally it is, so ringStream doesn't work.

Feel free to ask any questions, I would be happy to help resolving this issue.

gdelataillade commented 8 months ago

Hi @arungopalan

Thanks a lot for the detailed answer.

I might have a workaround you can try: change the plugin's code and in the Alarm class in alarm.dart, change this (line 25):

static final ringStream = StreamController<AlarmSettings>();

to:

static final ringStream = StreamController<AlarmSettings>.broadcast();

Let me know if it changes something. Thanks in advance.

vitalii-t12 commented 8 months ago

@gdelataillade Hi. You tagged the wrong person in your last comment :sweat_smile:

Thanks for suggested fix. I tried it, but didn't help.

When using broadcast() I don't even get the ringing screen after killing the app and starting it from notification.

I also noticed, that when FlutterFirebaseMessagingBackgroundService is initialized the handleMethodCall method from android_alarm.dart isn't called

gdelataillade commented 8 months ago

Hi @vitalii-t12

Thanks for your answer !

It seems the issue lies with the alarmRinging invokeMethod not being triggered from AlarmService. My suspicion is that there's a conflict with the firebase_messaging package. To address this, I'm working in PR #166 on a solution that involves utilizing an EventChannel instead of a MethodChannel for sending ring events from the native side to Flutter. This change aims to mitigate potential conflicts. Unfortunately, I'm unable to replicate the issue on my device, so I'd greatly appreciate it if you could test the fix on your end.

For testing the proposed fix, you'll need to modify your pubspec.yaml to use the alarm plugin from a specific branch where the fix has been applied. Here's how you can do it:

alarm:
    git:
      url: https://github.com/gdelataillade/alarm.git
      ref: fix/android-ring-stream-issue

Please let me know if this resolves the issue for you. Your feedback will be invaluable.

vitalii-t12 commented 8 months ago

Hi, @gdelataillade

I'm happy to help! I love your lib, and will do anything I can to make it better.

I tried running it with your fix, but the app doesn't run. Do you have any idea why I'm getting this issue?

image

vitalii-t12 commented 8 months ago

@gdelataillade hello again :)

I managed to fix the issue above by pulling the project from your branch and setting up firebase again. Probably, was some caching issue.

This fix brought some very interesting behavior to the app: alarm screen works ONE TIME when app is freshly installed. I install the app, app starts, FirebaseMessagingService is initialized, and when I start alarm instantly and IT WORKS :fireworks:, but then when I do it again, it doesn't work. Even when I kill the app and start it from notification, it doesn't display the alarm screen. But it also removes the alarm, when I start it from notification.

I tried it on my real device as well, and it's the same behavior, except, if I wait some time (like 5min.) and do a cold start, the alarm screen works one time as well, and then doesn't work again.

Here is a short video, describing the case: Screencast from 03-16-2024 05:45:09 PM.webm

gdelataillade commented 8 months ago

Hi @vitalii-t12

Thanks for the feedback !

I just pushed a commit on the fix/android-ring-stream-issue branch. It should fix the issue with the ring screen that shows only the first time. Let me know if it works !

vitalii-t12 commented 8 months ago

Hi, @gdelataillade

That's amazing! It works well now!!!

The only thing is, that when I open the app from notification I get the RingScreen twice. I've added a timestamp on RingScreen and you can see a difference at milliseconds.

Here is a short video describing how it works and the bug I described above:

Screencast from 03-18-2024 05:14:54 PM.webm

gdelataillade commented 8 months ago

Hi again @vitalii-t12

Glad to see it works !

I'll take a look a this. In the meantime you can avoid the double navigation by checking if the navigation to the ring screen was already done once.

Let me know if you think I can merge this branch to the main branch and make a release, and if you think I can close this issue.

vitalii-t12 commented 8 months ago

Hi, @gdelataillade

We're almost there, but the side effect we're getting with double ring screen is a bit concerning.

It looks, like it's called twice independently, while hasNavigatedToRingScreen is still false

Screencast from 03-19-2024 05:35:15 PM.webm

gdelataillade commented 8 months ago

Hi @vitalii-t12

I've been unable to reproduce the double navigation issue... Have you been able to find a fix or a workaround ?

vitalii-t12 commented 8 months ago

HI, @gdelataillade

I didn't have time recently to play around with it. I tried it without FirebaseMessaging, and it works perfectly well. But when I initialize FirebaseMessagingService it shows the double ring screen. I will try to find a workaround for it the next days. At least, it works pretty good now

vitalii-t12 commented 7 months ago

Hello, @gdelataillade

Sorry for taking so long, was busy recently. I found a solution for the ringing screen taht appears twice. In home.dart I modified the initState:

  void initState() {
    super.initState();
    if (Alarm.android) {
      checkAndroidNotificationPermission();
      checkAndroidScheduleExactAlarmPermission();
    }
    loadAlarms();
    DateTime? dateAlarmCalled;
    subscription ??= Alarm.ringStream.stream.listen(
      (alarmSettings) {
        if (dateAlarmCalled != alarmSettings.dateTime) {
          navigateToRingScreen(alarmSettings);
          dateAlarmCalled = alarmSettings.dateTime;
        }
      },
    );
  }

It worked now. I tried earlier doing something similar with state varialbe, but it didn't work (I really don't wanna investigate why, I'm happy it works now). Now it works perfecly well, and there are no other side effects.

I can confirm that it works perfectly well, and you can close this discussion and merge your fix into main branch! Thank you very much for your work! I'm very happy to have the opportunity to use your library. Wish you all the best in future :rocket:

gdelataillade commented 7 months ago

Hi @vitalii-t12

Awesome ! I'm glad that it works now and that you like the library. Thank you so much and I wish you all the best too !