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

Inconsistent behavior in Android #184

Closed younesouhbi closed 1 month ago

younesouhbi commented 7 months ago

Alarm plugin version 3.0.14

Describe the bug The plugin behaves a little bit differently across various Android contexts:

Android simulator

Samsung Galaxy A33

To Reproduce Just deploy and test

Expected behavior I'm not sure what is supposed to be the ideal behavior of the plugin, as there seems to be some differences between iOS & Android. As far as I'm concerned, it should be something like this:

Screenshots No screenshots needed.

Device info Android simulator, Samsung Galaxy A33... Will update with more devices.

Additional context None

younesouhbi commented 7 months ago

I have tested on another Android device. It's similar to the Galaxy A33.

Honor PCT

gdelataillade commented 7 months ago

Hi @younesouhbi

Thank you so much for your feedback ! It's very helpful.

About stream issues, I recently released v3.1.0 with some fixes. Some users had issues with their stream due to conflicts with other packages they used, like Firebase Messaging. More details here: #110 #122.

About the notification icon, it's a known issue I need to fix: #54.

About the alarm that is stopped on notification tap, it's also a known issue: #177.

About the notification on kill that doesn't always shows, I will work on it, but in my opinion it's not really necessary because the alarm will ring even if the app was killed.

A lot of work needs to be done ! Unfortunately I'm mostly alone working on the plugin so it can take a while. I hope some developers will contribute someday so issues can be resolved faster.

gdelataillade commented 7 months ago

About the notification icon issue, I just released version 3.1.1 with a potential fix. Let me know if it works for you.

younesouhbi commented 7 months ago

I do want to help, however seeing that native Android development is new to me, I'm going to need time to understand top level concepts before being of any help.

One of my Android testers reported not being able to turn off the alarm at all. Tapping the notification didn't stop the sound, and when they got into the app, the stream didn't receive the event, which means that there were no screen to let them stop the alarm. So they had to restart their phone.

I would say that the plugin works pretty well in iOS, but in Android, its behavior is too inconsistent. I will be spending the next few days reading and trying to understand how the Android version works. If you can offer some general idea how the various classes work and interact, it would be great.

Thank you for all your work on this!

younesouhbi commented 7 months ago

I'm trying to understand how the plugin works. This is the process that supposedly executes when "setAlarm" is called. Is this correct? alarm_plugin___set_alarm

gdelataillade commented 7 months ago

Hi @younesouhbi

Yes your diagram looks correct !

Furthermore, in the AlarmService, AlarmPlugin.eventSink is called to send the information to the Flutter side (listenToAlarmEvents in AndroidAlarm) to tell that the alarm started ringing and to add the event to the ringStream.

It's true that the Android behavior is inconsistent. It looks like every device manufacturer (Samsung, Xiaomi, ...) has different behaviors with the plugin.

Really don't hesitate if you have any other question on the code. I'll try to answer as quickly as possible. Thanks a lot for your willingness to contribute, it’s great !

younesouhbi commented 7 months ago

After having studied the native Android plugin and learned a lot about Android development, I have found some potential bugs and hopefully corrected them. I'm interested in your thoughts regarding this. Here is a list of what I did:

I would like to continue refactoring things. For example merging VolumeService into AudioService since it's the same functionality. Renaming things (quite anal about how things are named :D). I also added a lot of documentation and comments. Moreover, ideally, it would be great if the Alarm plugin used static properties and methods sparingly, as they are evil. A singleton would be better, but such a rewrite is quite huge. Maybe if my app ends up being reasonably successful, so probably no :)

I will share the code after I finish everything and clean up the code. Now, I'll be moving to the iOS plugin to see if there is a way to reduce battery usage. I especially want to test an idea: while the upcoming alarm is more than 15 minutes away, only do background refreshes. Once it gets close, then play the audio to keep the app active in the background. Rinse and repeat. In all honesty, I have absolutely NO idea how background fetch works on iOS, for all I know, the plugin already does this, or it might be impossible to do. I simply won't know until I research, so might be a stupid idea.

Thank you again!

gdelataillade commented 7 months ago

Hi @younesouhbi,

Thank you so much for your work. I'm aware that the codebase could be improved significantly. Unfortunately, sometimes I've had to prioritize releasing features and fixing issues over maintaining quality. Your improvements would be incredibly helpful, and I'm looking forward to your pull request! I'm confident that the alarm plugin will be successful if we work together to enhance it. It's a big relief to know that someone with your skills is willing to contribute to the native code. I started learning Kotlin and Swift through this plugin.

Regarding the iOS part of the plugin, I'm currently experimenting with battery consumption by testing various silent audio lengths. I’m also developing a method to play silent audio for just one second every ten seconds to minimize active playback while ensuring the app remains operational in the background. I'll keep you informed on this. It’s important to note that iOS background fetch intervals can vary significantly, especially when the system is handling other intensive tasks like gaming or downloads. The techniques I’m using, like silent audio and background fetch, are the result of multiple experiments to maintain app activity in the background, ensuring the alarm sounds precisely when scheduled, even days later.

Thanks again for everything, and please reach out if you have any questions!

ApplySci commented 6 months ago

@younesouhbi I'd be particularly interested in getCurrentlyRingingAlarmId

I've got an app using this package, and it behaves perfectly fine in the android emulator, but on two Moto android devices, it's impossible to dismiss the alarms unless I kill the app. If I can getCurrentlyRingingAlarmId when the app is opened, I could at least stop the alarm there

gdelataillade commented 1 month ago

I'm closing this issue because in the meantime version 4.0.0 was released including a significant refactoring of the code and many bug fixes. Feel free to reopen if needed !