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

Crash on Android "ForegroundServiceDidNotStartInTimeException" #230

Open pbouttier opened 3 months ago

pbouttier commented 3 months ago

Alarm plugin version 3.1.5

Describe the bug Play Store and Sentry report the same bug, a crash

android.app.RemoteServiceException$ForegroundServiceDidNotStartInTimeException: Context.startForegroundService() did not then call Service.startForeground(): ServiceRecord{b388286 u0 com.pbouttier.sptraining/com.gdelataillade.alarm.alarm.AlarmService}
    at android.app.ActivityThread.generateForegroundServiceDidNotStartInTimeException(ActivityThread.java:2261)
    at android.app.ActivityThread.throwRemoteServiceException(ActivityThread.java:2232)
    at android.app.ActivityThread.-$$Nest$mthrowRemoteServiceException
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2526)
    at android.os.Handler.dispatchMessage(Handler.java:106)
    at android.os.Looper.loopOnce(Looper.java:222)
    at android.os.Looper.loop(Looper.java:314)
    at android.app.ActivityThread.main(ActivityThread.java:8602)
    at java.lang.reflect.Method.invoke(Method.java)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:565)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1081)

To Reproduce Steps to reproduce the behavior: I didn't reproduce it myself, I only have the data from the play store, from sentry

Expected behavior No crash :)

Screenshots I didn't reproduce it myself

Device info Provide device info (Manufacturer, OS version, ...) Happen mostly on Android 14, but also and 13, 12, 10. And on multiple devices : samsung, xiaomi, redmi ...

Additional context I have the "await" on most of my functions.

void main() async {
  // [...] others plugins
  await Alarm.init();

How i have set the alarm

  Future<void> setAlarm(DateTime dateTime) async {
    UserSettingsModel userSettings = await ref.read(userSettingsProvider.future);

    final alarmSettings = AlarmSettings(
      id: alarmId,
      dateTime: dateTime,
      assetAudioPath: 'assets/audio/alarm.mp3',
      loopAudio: false,
      vibrate: userSettings.noticeEndCountdown == NoticeEndCountdown.vibrate,
      // Le son est indépendant du son configuré à l'instant T sur Android, ça le remet brieffement à cette valeur
      volume: userSettings.noticeEndCountdown == NoticeEndCountdown.sound ? userSettings.countdownVolume : 0.0, 
      notificationTitle: tr('workout.ongoing.notification_countdown.title'),
      notificationBody: tr('workout.ongoing.notification_countdown.body'),
      enableNotificationOnKill: false,
      androidFullScreenIntent: false,
    );
    await Alarm.set(alarmSettings: alarmSettings);
  }

I didn't have await on the stop, I'll add it in the next version of my app, just in case. Edit : not solve with the await on stop.

Thanks for your time, this bug apart from the package is great :)

gdelataillade commented 2 months ago

Hi @pbouttier

Thank you for your interest in the plugin!

I’ve just released version 4.0.0-dev.1, which includes some updates to the Android native code. This isn’t the final 4.0.0 release, as further testing is needed, but I hope it resolves the issue you’re experiencing.

pbouttier commented 2 months ago

I've tried the 4.0.0-dev.1, on dev (so I couldn't see if my users had the initial crash) :

I need to add -keep class com.gdelataillade.alarm.models.** { *; } to proguard-rules.pro. Otherwise in --release i got this error

See https://github.com/google/gson/blob/main/Troubleshooting.md#r8-abstract-class, null, java.lang.RuntimeException: AlarmSettings Error parsing JSON to AlarmSettings: Abstract classes can't be instantiated! Adjust the R8 configuration or register an InstanceCreator or a TypeAdapter for this type. Class name: h0.b

in models/AlarmSettings.kt

val gson = Gson()
val jsonString = gson.toJson(modifiedJson)
val result = gson.fromJson(jsonString, AlarmSettings::class.java)

And I've seen other minor things. I don't know if it's directly related to 4.0.0, or to the scope you wanted to integrate, but I'll put them here anyway just in case:

gdelataillade commented 2 months ago

Hi @pbouttier

Thanks for your feedback !

1) About the error parsing JSON to AlarmSettings, I added the proguard-rules.pro to the plugin and released version 4.0.0-dev.2.

2) About the notification icon, I should indeed do something so developers can customize it. I'll add it to my to do list.

3) This behavior occurs because, for alarms set to trigger within 5 seconds or less, I bypass the AlarmManager and directly start the AlarmService. The reason for this is that triggering the AlarmManager is a resource-intensive operation that can take a few seconds to execute, which is impractical for such short intervals. However, I can optimize this by reducing the threshold from 5 seconds to 3 seconds.

pbouttier commented 2 months ago

Nice !

For 3, I don't think it's necessary to do anything specific. I was testing it in brute force mode, but it's unlikely to have a real case where it needs to alarm less than 5s later.

pbouttier commented 2 months ago

Re,

The problem persist on lastest version

Exception android.app.RemoteServiceException$ForegroundServiceDidNotStartInTimeException:
  at android.app.ActivityThread.generateForegroundServiceDidNotStartInTimeException (ActivityThread.java:2262)
  at android.app.ActivityThread.throwRemoteServiceException (ActivityThread.java:2233)
  at android.app.ActivityThread.-$$Nest$mthrowRemoteServiceException
  at android.app.ActivityThread$H.handleMessage (ActivityThread.java:2527)
  at android.os.Handler.dispatchMessage (Handler.java:106)
  at android.os.Looper.loopOnce (Looper.java:222)
  at android.os.Looper.loop (Looper.java:314)
  at android.app.ActivityThread.main (ActivityThread.java:8610)
  at java.lang.reflect.Method.invoke
  at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run (RuntimeInit.java:565)
  at com.android.internal.os.ZygoteInit.main (ZygoteInit.java:1081)

And a second one (few cases) :

Exception java.lang.RuntimeException:
  at android.app.ActivityThread.handleServiceArgs (ActivityThread.java:5071)
  at android.app.ActivityThread.-$$Nest$mhandleServiceArgs
  at android.app.ActivityThread$H.handleMessage (ActivityThread.java:2435)
  at android.os.Handler.dispatchMessage (Handler.java:106)
  at android.os.Looper.loopOnce (Looper.java:224)
  at android.os.Looper.loop (Looper.java:318)
  at android.app.ActivityThread.main (ActivityThread.java:8762)
  at java.lang.reflect.Method.invoke
  at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run (RuntimeInit.java:561)
  at com.android.internal.os.ZygoteInit.main (ZygoteInit.java:1013)
Caused by java.lang.NullPointerException: Attempt to invoke virtual method 'int java.lang.String.length()' on a null object reference
  at org.json.JSONTokener.nextCleanInternal (JSONTokener.java:121)
  at org.json.JSONTokener.nextValue (JSONTokener.java:98)
  at org.json.JSONObject.<init> (JSONObject.java:168)
  at org.json.JSONObject.<init> (JSONObject.java:185)
  at com.gdelataillade.alarm.alarm.AlarmService.onStartCommand (AlarmService.kt:71)
  at android.app.ActivityThread.handleServiceArgs (ActivityThread.java:5053)
gdelataillade commented 2 months ago

Hi @pbouttier

I've been unable to reproduce your issue. Are you sure you followed the installation steps ?

pbouttier commented 2 months ago

Re, sorry for my late reply.

I was missing the scheduleExactAlarm permission but I can't find a configuration where it would be disabled, nor can I reproduce the problem on an emulator.

My hope was that you had an idea of what might be blocking it, but if we're both lost, we'll be sailing blind.

Maybe something like this ? https://stackoverflow.com/questions/77415459/android-13-foregroundservicedidnotstartintimeexception, https://github.com/androidx/media/issues/112 ?

gdelataillade commented 2 months ago

I'm aware of the 5 seconds rule, I run startForeground almost instantly when alarm is triggered. Maybe there's an error before it is called. Do you have more logs to share ?

pbouttier commented 1 month ago

I have these json from sentry. Android 13 & 14, differents permissions.

schedule, post notif not granted us.sentry.io.json playback not granted us.sentry.io.json

gdelataillade commented 1 month ago

Hi @pbouttier

Sorry for the late reply. Do you ask for the scheduleExactAlarm permission ? If we can't reproduce the issue maybe it's because this permission is not granted by default in some devices. Maybe you could try to add it (see doc step 5) and see if the issue still appears in your Sentry.

What do you think ?

pbouttier commented 1 month ago

In the second error log, the permissions were :

‘SCHEDULE_EXACT_ALARM": “granted”,
‘USE_EXACT_ALARM": “granted”,

So the problem must not be there

Sorry, I only saw afterwards that it was a raw file, with no indentation or line feeds. Here they are, in readable format :

schedule not granted.txt play back not granted beautiful.json.txt

And thanks for the custom notification icon, it's great

gdelataillade commented 1 month ago

I saw something interesting in the second error log:

"FOREGROUND_SERVICE_MEDIA_PLAYBACK": "not_granted"

I believe this permission is necessary. The weird thing is that it should be granted by default when I added it in the plugin's manifest here:

<uses-permission android:name="android.permission.FOREGROUND_SERVICE_MEDIA_PLAYBACK"/>

Did you disable it manually ? Does you other logs have this permission not granted ?

If so, log 1 may crash because of SCHEDULE_EXACT_ALARM and log 2 because of FOREGROUND_SERVICE_MEDIA_PLAYBACK. What do you think ?

gdelataillade commented 1 month ago

Hi @pbouttier

Do you still have the issue ?

pbouttier commented 1 month ago

Sorry for my late reply.

I haven't had time to test the request for the SCHEDULE_EXACT_ALARM permission. I'll include it in my next update but it's a big one, I've still got other points to finish.

I don't understand FOREGROUND_SERVICE_MEDIA_PLAYBACK either. The permission is in the .xml file, so it ‘should work’.

gdelataillade commented 1 month ago

No problem. Let me know how it goes in your next update !

synstin commented 4 weeks ago

I often report the same crash.

POCO peridot (POCO F6) - Android 14(SDK 34)

android.app.RemoteServiceException$ForegroundServiceDidNotStartInTimeException
Exception android.app.RemoteServiceException$ForegroundServiceDidNotStartInTimeException:
  at android.app.ActivityThread.generateForegroundServiceDidNotStartInTimeException (ActivityThread.java:2250)
  at android.app.ActivityThread.throwRemoteServiceException (ActivityThread.java:2221)
  at android.app.ActivityThread.-$$Nest$mthrowRemoteServiceException
  at android.app.ActivityThread$H.handleMessage (ActivityThread.java:2515)
  at android.os.Handler.dispatchMessage (Handler.java:106)
  at android.os.Looper.loopOnce (Looper.java:224)
  at android.os.Looper.loop (Looper.java:318)
  at android.app.ActivityThread.main (ActivityThread.java:8790)
  at java.lang.reflect.Method.invoke
  at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run (RuntimeInit.java:561)
  at com.android.internal.os.ZygoteInit.main (ZygoteInit.java:1013)
gdelataillade commented 3 weeks ago

Hi @synstin,

Do you have the Android permissions set up as outlined earlier in this conversation?

synstin commented 3 weeks ago

I've set all permissions. This is my current list of permissions. Thank you.

<!-- PERMISSION -->
    <uses-permission android:name="android.permission.INTERNET"/>
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="28"/>
    <!-- /PERMISSION -->

    <!-- ALARM -->
    <uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
    <uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" android:maxSdkVersion="32"/>
    <uses-permission android:name="android.permission.FOREGROUND_SERVICE_MEDIA_PLAYBACK"/>
    <!-- /ALARM -->

    <!-- AWESOME NOTIFICATION PERMISSION -->
    <uses-permission android:name="android.permission.VIBRATE"/>
    <uses-permission android:name="android.permission.WAKE_LOCK"/>
    <uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM"/>
    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
    <uses-permission android:name="android.permission.ACCESS_NOTIFICATION_POLICY"/>
    <!-- /AWESOME NOTIFICATION PERMISSION -->
riqtech90 commented 1 week ago
Screenshot 2024-11-10 at 8 16 35 PM

My app also received daily crash report from firebase crashlytic. Haven't experience the crash personally, but from what i see, the crash report most of it is android 8 to android 11 devices