Android app crash behavior
from the CommonsWare Community archivesAt July 10, 2019, 1:58pm, rd7773 asked:
I have a foreground service running with a START_STICKY intent returned. Along with it i am also setting periodic alarm in reccuring pattern using setExact and then from the broadcast receiver again setting it.
Problem occurs when app crashes, the service destroys, alarms don’t fire anymore. I can smell that my process is killed that is why the alarm that might have fired didn’t find the classes in pendingIntent.
Could help me out in this approach where i need to keep my service running or reopen app if process killed by crash.
At July 10, 2019, 2:13pm, mmurphy replied:
Alarms normally are not removed when an app crashes. Also, an app crashing does not eliminate that app’s classes. The only way that I can thin of that a PendingIntent
might stop working after a crash is if it is a broadcast PendingIntent
using an implicit Intent
, designed to be received by a dynamically-registered receiver, and that receiver is no longer around after a crash.
If you already have a foreground service, there is no value in AlarmManager
, since your service is already running. Use in-process periodic work solutions, such as a ScheduledExecutorService
. Reserve your use of AlarmManager
or JobScheduler
for cases where your service may or may not be running.
Beyond that, use adb shell dumpsys alarm
to confirm that you can see your alarm during normal operations, then see what happens after the crash. My guess is that the alarm will still be there.
At July 11, 2019, 7:39am, rd7773 replied:
So basically i just want my socket to be connected all the time (i know FCM is recommended) for which i am running a foreground sticky service which connects the socket in onStartCommand. And as you said, i will be using Handlers for periodically checking if the socket is still connected or not (instead of AlramManager).
But what about the case when my process is killed (crashed) and my service isn’t there and i still want to receive msgs on the socket and keep my service running ?
At July 11, 2019, 12:22pm, mmurphy replied:
You can use AlarmManager
with a PendingIntent.getService()
that starts your service. That will not cover all scenarios, though — if the user uses Force Stop in Settings to stop your app, nothing of your app will run again until the user launches your app from the launcher or something else uses an explicit Intent
to start one of your components.
In your original post, you wrote “alarms don’t fire anymore”. I suggested that you use adb shell dumpsys alarm
to confirm that you can see your alarm during normal operations, then see what happens after the crash. My guess is that the alarm will still be there. If the alarm is gone, and you did not use Force Stop yourself, that indicates that the device manufacturer may have tied crashing to Force Stop-style behavior. While I have not heard of that, some device manufacturers have tied their own task manager apps to Force Stop-style behavior. There is nothing we can do about that, just as there is nothing that we can do about users using Force Stop directly from Settings.
At July 12, 2019, 5:05am, rd7773 replied:
Something (weird) i find out, i am firing this alarm every 15 secs, now when my app crashes, the system shows the ‘App has stopped’ dialog and if i wait for 15 seconds (alarm firing time) before i dismiss that dialog, the alarm doesn’t get fired. It is working fine if i dismiss that crash dialog within the next alarm firing time window.
I am using PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT) and the intent is a explicit intent with the broadcast receiver class that has been registered in the manifest.
Using this pendingIntent with alarmManager.setExact method and then in the onReceive method, checking if service is running or not, socket is connected or not and re-set the alarm for periodic check. Meanwhile i check the adb shell command, could you confirm that the approach is correct.
At July 12, 2019, 12:06pm, mmurphy replied:
AlarmManager
has a minimum period of one minute, as of Android 5.1. And invoking an alarm that frequently is very user-hostile. Behavior like this is why Doze mode and app standby were added in Android 6.0 and why things get worse and worse for all Android developers with each passing release.
I have never tried this and do not know if that is the expected behavior or not. You might try running your experiments on a few device models from different manufacturers — if the behavior is consistent, then most likely the behavior is expected.
At July 16, 2019, 4:21pm, rd7773 replied:
You are right that behavior like this should totally be avoided, and we also won’t be publishing this kind of behavior in production. It was just to experiment various approaches before i reach the optimal solution for production.
Use case is that the app is receiving some events on socket on which user has to act upon within a stipulated time and a missed event is a monetary loss.
Didn’t want to start a new thread for the same, so my final question is, how to keep my foreground sticky service running all the time even if app cleared from recent Tasks by user, or a crash (Force stop is fine whether by user by OEMs).
And i guess that’s where alarm Manager is required, to check whether my service is running or not, as we don’t have a callback to know when our process in which service is running dies.
Looking forward for your help.
At July 16, 2019, 4:51pm, mmurphy replied:
Sorry, but I have avoided needing to worry about this, so I do not know if there is a recommended solution.
You might consider looking into open source apps with similar characteristics and see how they approach the problem of having an always-available socket, such as:
- Signal
- Mattermost
- Telegram
- Briar