gdelataillade/alarm

[iOS] First alarm creation does not emit audio but notification do appears

Closed this issue · 13 comments

Alarm plugin version
3.0.14

Describe the bug

  • When I install my app the first time and create an alarm using this library, I am getting notifications correctly but there is no audio being emitted by the app.
  • When I keep changing the scheduled alarm after the previous alarm, the audio was consistently not emitting.
  • But if I add another alarm schedule, the first alarm will not emit an audio but the second alarm will, and eventually, the first alarm will emit an audio when I reschedule it

To Reproduce
Steps to reproduce the behavior:

  1. Install app in iPhone using this library
  2. Create an alarm
  3. Wait for the alarm to be triggered

Expected behavior
There should be an audio alongside with the notifications

Screenshots
If applicable, add screenshots to help explain your problem.

Device info
iPhone X, iPhone 13

Additional context

  • I use flutter_background_service and awesome_notifications for other matters of the app not sure if it has something to do with that.
  • Alarms were created with volume value of 0.5
  • Logs so far that I got
    flutter: [Alarm] Alarm with id 1 scheduled successfully at 2024-04-04 14:49:00.000
    Could not schedule app refresh: Error Domain=BGTaskSchedulerErrorDomain Code=3 "(null)"
    Could not schedule app refresh: Error Domain=BGTaskSchedulerErrorDomain Code=3 "(null)"
    D/Swift: [AWESOME NOTIFICATIONS] last displayed date registered: 2024-04-04 06:48:19 GMT (DefaultsManager:99)
    D/Swift: [AWESOME NOTIFICATIONS] App is now Background (LifeCycleManager:134)
    [Snapshotting] Snapshotting a view (0x106ef1c00, UIKeyboardImpl) that is not in a visible window requires afterScreenUpdates:YES.
    [BackgroundTask] Background Task 14 ("Flutter debug task"), was created over 30 seconds ago. In applications running in the background, this creates a risk of termination. Remember to call UIApplication.endBackgroundTask(:) for your task in a timely manner to avoid this.
    [BackgroundTask] Background Task 15 ("Flutter debug task"), was created over 30 seconds ago. In applications running in the background, this creates a risk of termination. Remember to call UIApplication.endBackgroundTask(
    :) for your task in a timely manner to avoid this.
    [BackgroundTask] Background Task 8 ("Flutter debug task"), was created over 30 seconds ago. In applications running in the background, this creates a risk of termination. Remember to call UIApplication.endBackgroundTask(:) for your task in a timely manner to avoid this.
    [BackgroundTask] Background Task 10 ("Flutter debug task"), was created over 30 seconds ago. In applications running in the background, this creates a risk of termination. Remember to call UIApplication.endBackgroundTask(
    :) for your task in a timely manner to avoid this.
    [BackgroundTask] Background Task 11 ("Flutter debug task"), was created over 30 seconds ago. In applications running in the background, this creates a risk of termination. Remember to call UIApplication.endBackgroundTask(_:) for your task in a timely manner to avoid this.
    flutter: GOTOSINGLEALRMSTREAM
    D/Swift: [AWESOME NOTIFICATIONS] last displayed date recovered: 2024-04-04 06:48:19 GMT (DefaultsManager:80)
    D/Swift: [AWESOME NOTIFICATIONS] last displayed date registered: 2024-04-04 06:49:22 GMT (DefaultsManager:99)
    D/Swift: [AWESOME NOTIFICATIONS] App is now Foreground (LifeCycleManager:134)
    flutter: -NFCID 0
    flutter: unhandled element <style/>; Picture key: Svg loader
    Another exception was thrown: A RenderFlex overflowed by 8.0 pixels on the bottom.
    flutter: nfc payload: Isa
    flutter: DITO single_alarm_screen

Hi @kydoaod

First, make sure you followed the setup steps in the README.
Then, do you have the issue with the example app ? Also, have you tried to disable awesome_notifications in your app to see if this was the cause of the conflict ?

Thanks in advance for your answers, they will help me identify the issue.

Hi @kydoaod

First, make sure you followed the setup steps in the README. Then, do you have the issue with the example app ? Also, have you tried to disable awesome_notifications in your app to see if this was the cause of the conflict ?

Thanks in advance for your answers, they will help me identify the issue.

Hi @gdelataillade

Yes I did so sharing here my main function

Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();
  MobileAds.instance.initialize();
  await dotenv.load(fileName: ".env");
  await Constants.readLanguageJson();
  // NotificationService().initNotification();
  //await AwesomeNotificationService.initAwesomeNotification();
  await SharedPreferenceService().init();
  await AlarmService.Alarm.init();
  runApp(const ProviderScope(child: MyApp()));
}

And here is how I use your library to set alarm

  Future<bool> createScheduledNotification(
      {int id = 0,
      String? title,
      String? body,
      required DateTime scheduledDate,
      List<String>? days,
      String? alarmIdAsPayLoad,
      String? soundPath,
      bool? isVibrate = false,
      double? volume = 1}) async {
    if(await AlarmService.Alarm.isRinging(id)){
      return false;
    }
    final alarmSettings = AlarmSettings(
        id: id, //VALUE: 1
        dateTime: scheduledDate, //VALUE: 2024-04-04 21:38:00
        assetAudioPath: channelKey??"", //VALUE: assets/sounds/alarm_clock_beep.wav 
        loopAudio: true,
        vibrate: isVibrate??false, //VALUE false
        volume: volume, //VALUE 0.5
        fadeDuration: 0,
        notificationTitle: title??"", //VALUE Isa
        notificationBody: body??"", //VALUE 21:38
        enableNotificationOnKill: true,
      );
    await AlarmService.Alarm.stop(id);
    return await AlarmService.Alarm.set(alarmSettings: alarmSettings);
  }

I added some comments for the values being placed there and this code works fine with Android as I tested it and audio do really being emitted in Android but in iOS, its occasionally just throwing a notification without audio

By the way adding here Info.plist

	<key>BGTaskSchedulerPermittedIdentifiers</key>
	<array>
		<string>dev.flutter.background.refresh</string>
		<string>com.gdelataillade.fetch</string>
	</array>

And my AppDelegate.swift

import UIKit
import Flutter
import flutter_background_service_ios
import UserNotifications
import alarm
// import awesome_notifications
// import shared_preferences_ios
// import flutter_local_notifications

@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
  override func application(
    _ application: UIApplication,
    didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
  ) -> Bool {

    // FlutterLocalNotificationsPlugin.setPluginRegistrantCallback { (registry) in
    //   GeneratedPluginRegistrant.register(with: registry)
    // }

    

    if #available(iOS 10.0, *) {
      UNUserNotificationCenter.current().delegate = self as? UNUserNotificationCenterDelegate
    }
    SwiftAlarmPlugin.registerBackgroundTasks()

    SwiftFlutterBackgroundServicePlugin.taskIdentifier = "com.tagawake.app"

    GeneratedPluginRegistrant.register(with: self)

    // SwiftAwesomeNotificationsPlugin.setPluginRegistrantCallback { (registry) in          
    //       SwiftAwesomeNotificationsPlugin.register(
    //         with: registry.registrar(forPlugin: "io.flutter.plugins.awesomenotifications.AwesomeNotificationsPlugin")!)          
    // }

    return super.application(application, didFinishLaunchingWithOptions: launchOptions)
  }

  override func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
    completionHandler([.alert, .sound])
  }
}

@kydoaod Thanks for the details.

Do you use different ids for your alarms ? I ask because if you set an alarm with the same id of a previously scheduled alarm, it will override it.

@kydoaod Thanks for the details.

Do you use different ids for your alarms ? I ask because if you set an alarm with the same id of a previously scheduled alarm, it will override it.

@gdelataillade Yes especially if I set multiple alarms for different time occasions. But the issue normally occurs when there is only one alarm to be triggered.

@kydoaod well it looks difficult to me to find the reason of your issue because it looks specific to your project. I recommend you to test different configurations until you find out what part is causing a conflict or something. Please let me know if you find some relevant information. I'll do the same.

@kydoaod well it looks difficult to me to find the reason of your issue because it looks specific to your project. I recommend you to test different configurations until you find out what part is causing a conflict or something. Please let me know if you find some relevant information. I'll do the same.

@gdelataillade Thanks for this and may I ask as well if in iOS, does the audio extension matter? Because we use .wav for this but is not an issue with Android. I am not sure if it is in iOS

@kydoaod well it looks difficult to me to find the reason of your issue because it looks specific to your project. I recommend you to test different configurations until you find out what part is causing a conflict or something. Please let me know if you find some relevant information. I'll do the same.

@gdelataillade Thanks for this and may I ask as well if in iOS, does the audio extension matter? Because we use .wav for this but is not an issue with Android. I am not sure if it is in iOS

Yes, in iOS I use AVAudioPlayer which supports .wav audio files, but feel free to test with another file format (mp3 for example) to make sure the issue is not from your audio file.

Hi @gdelataillade not sure if related but I noticed that this part always tells pos2 and pos1 are both zero when there is an alarm being triggered with or without sound being emitted. Is there a way here to check the AVAudioPlayer status if it is playing or not aside from isRinging function?
image

By the way, aside from awesome_notification, I also use flutter_background_service for handling the periodic changes of alarm time, I am not sure if this somewhat causing an issue here. But I tried to disable it in a sense that I make it available only for android but no avail although they were at the AppDelegate.swift.

Hi @kydoaod

Thanks for reporting this issue about the checkIfRinging method. It could be related, I'll take a look as soon as possible.

Hi @kydoaod

I'm not able to reproduce the checkIfRinging issue for iOS...
Have you tried with the package example app ? It could help us identify if the issue comes from the package or from your code.

Hi @kydoaod

I'm not able to reproduce the checkIfRinging issue for iOS... Have you tried with the package example app ? It could help us identify if the issue comes from the package or from your code.

Hi @gdelataillade thanks for responses and yes both my app and the example app. So here is my observation, I dont think awesome_notifications has something to do with this but what I noticed is that when I check the isRinging function in the background timer using flutter_background_service, it is always false no matter what, but for the same alarm id in other widgets where in I placed a Timer function there similar on the example of that, the isRinging function throws a correct values if the alarm is ringing or not. I did try to create a static class wrapper to try to overcome that but no avail. Is this something that is intentionally implemented or it should throw correct responses regardless where you call them?

By the way in relation to the topic why I am saying this is that I can't still figure out why the scheduled alarm is randomly not emitting a sound or not and so, I had to try to compensate that by checking the alarm if ringing or not in the background then try to play an audio if it fails. But I encountered that issue. The no sound usually occurs if scheduling an alarm for a long time or sometimes for first installation of the app that uses that.

Hi @kydoaod

  • The flutter_background_service operates in a separate isolate, which means it does not share memory with the main thread. As a result, the isRinging function might not work as expected from the background service due to this isolation.
  • I'm not entirely sure why your alarm sometimes fails to emit sound. This issue could be influenced by a variety of factors related to how iOS handles background processes and audio sessions.
  • Let's continue testing under different conditions and configurations. Please keep us updated with any findings or patterns you observe. We'll work together to pinpoint and resolve this issue.

Hi @kydoaod

Do you still experience this kind of issue in the latest releases ? I'm closing the issue but please let me know if you have any problem.