Scope: Hi, I am developing a Service in Android API. I need this Service for running whole time (while device is running), so receiver for BOOT
android.intent.action.BOOT_COMPLETED
was setup and Service is scheduled by AlarmManager every 10 minutes.
Problem: My OS got some updates and after updating, it kill my service, unschedule Service from AlarmManager. And as far as I do not reboot my device, Service is not started/scheduled.
Question: Is there any event for receivers, that OS is restarted but device is not? Or updates are installed, OS is resumed etc.?
EDIT
Hello, thanks for links and advice.
Nowadays, I'm using library Evernote for scheduling background jobs.
see https://github.com/evernote/android-job
I accepted the truth, that long-living Service is antipattern and BOOT broadcast can be tricky. As result, I used Evernote to schedule simple jobs to repeatly "do my needs". It nice works as expected, resumes after device restart & is compatible with "Android alarm planning" management.
Just a great library.
I am developing a Service in Android API. I need this Service for running whole time (while device is running)
That is generally an anti-pattern on Android.
Is there any event for receivers, that OS is restarted but device is not?
Not in the Android SDK, because there is no concept of "OS is restarted but device is not" in standard Android. When the OS updates, the entire device reboots (at least twice) as part of the update process.
Your device manufacturer must have done something that has the behavior your describe. You may wish to contact that manufacturer to see if they have advice regarding your scenario.
Note that these results ("it kill my service, unschedule Service from AlarmManager") will also occur when the user taps "Force Stop" on your app's screen in Settings. Your code will not run again, even after a reboot, until the user launches your app from the home screen, or something else explicitly invokes one of your components.
Related
I have read the Android documentation regarding the new background restrictions in Android API Level 26, and with those in mind, I have designed my app as follows:
The app has a BroadcastReceiver listening for the "SMS_RECEIVED" broadcast. This is an implicit broadcast, which are now restricted in Oreo, however it is one of those in their exceptions list.
When this BroadcastReceiver runs, it enqueues a new task to be performed by a JobIntentService. When receiving the broadcast, the app should be temporarily whitelisted and therefore, the JobIntentService given a window of opportunity to do its thing.
All of this seems to be working just fine, even if I close the app from the "recent apps" list. However, I'm getting reports from some users that apparently every few days, they have to open the app again because it suddenly stops working in the background.
Why does the OS suddenly stop sending the "SMS_RECEIVED" broadcast to my app? If it is not that, then it must be the JobIntentService not being allowed to run. Why not? The app should be whitelisted immediately after receiving the SMS. What am I misunderstanding?
Besides Doze, Android also contains functionality called App Standby. As per the documentation:
App Standby defers background network activity for apps with which the user has not recently interacted.
The default 'recently interacted' time frame is 3 days, which corresponds with your reports of things stopping 'apparently every few days'.
Therefore what seems to be happening is your JobIntentService fires (your app is indeed still whitelisted after receiving the broadcast), but App Standby is preventing your JobIntentService from connecting to the network.
You can confirm this is the case by following the Testing your app with App Standby instructions:
adb shell dumpsys battery unplug
adb shell am set-inactive <packageName> true
You might consider looking through the Acceptable use cases for whitelisting to see if asking to ignore battery optimizations is an option for your use case.
Context
We are developing an android app that is supposed to do the following:
the user installs the app, registers and closes the app
once or twice a year an admin sends a Firebase data message with priority high to the user containing a geo fence
the FCM message starts a JobService that locates where the phone is
if the phone is inside the given area an Activity is started and user interaction starts
if the phone is outside the area the service is stopped and the user is never disturbed
I developed the app based on the Firebase push example found here
The problem
The application works fine on my older phones but on my new test phone (android 8.1.0, LineageOS 15.1) we have a problem when the phone is in sleep mode. In this case the FCM message arrives instantly but the service is first started once the phone is unlocked. So the message is stuck between 2. and 3.
We need the app to respond at once - not when the user decides to use his phone 2 hours later.
I assume the problem is due to the Doze mode introduced with android 6. I tried to solve it by adding the app to the whitelist in settings->battery->battery optimization but this did not solve the problem.
Questions
Is it Doze mode that delays my app between 2. and 3.? If so why is it not solved when the app is in the whitelist?
Is there any other way to start the location service at once? This post suggests that a foreground service can do it but this requires that a notification is shown which breaks with 5.
Is there another way to start my service at once besides whitelist and foreground service?
Yes! you are right this may be due to the Doze and App Standby features introduced in API 23 Marshmallow.
As mentioned in the documentation, the system do ignore wakelocks and system doesn't allow JobScheduler to run, which effectively prevents your app from running the Job.
An easy and effective workaround would be to run Location detecting routine inside a normal background service and start it using startService() when you receive FCM push.
Note that you might still need to white-list your app because as mentioned in another post here, only a whitelisted app can use the network and hold partial wake locks.
Is it Doze mode that delays my app between 2. and 3.?
From the documentation Doze mode affect Network access and blocks JobScheduler.
If so why is it not solved when the app is in the whitelist?
Also from the documentation: An app that is whitelisted can use the network and hold partial wake locks during Doze and App Standby. However, other restrictions still apply to the whitelisted app, just as they do to other apps.
So the blocking of JobScheduler still applies.
Is there any other way to start the location service at once? This
post suggests that a foreground service can do it but this requires
that a notification is shown which breaks with 5.
Ignore Battery Optimizations (for Internet access) in combination with an AlarmManager with setAndAllowWhileIdle() or setExactAndAllowWhileIdle() should work.
Be careful with Ignore Battery Optimizations
Google Play policies prohibit apps from requesting direct exemption from Power Management features in Android 6.0+ (Doze and App Standby) unless the core function of the app is adversely affected.
I think an important question here is: Do you really need to execute the JobScheduler immediately.
If a user leaves a device unplugged and stationary for a period of time, with the screen off, the device enters Doze mode.
If the device is in Doze mode, it means the user is not using it.
if the phone is inside the given area an Activity is started and user interaction starts
This is the step Doze blocks
We need the app to respond at once - not when the user decides to use his phone 2 hours later.
If the device is in Doze it means the user is not interacting with it. Even if you show the Activity the user is not using the phone, he will see it when he starts using it 2 hours later :)
I still didn't try that,
but you might use a WakefulBroadcastReceiver:
https://developer.android.com/training/scheduling/wakelock.html
https://developer.android.com/reference/android/support/v4/content/WakefulBroadcastReceiver.html
According with this links, you should declare your receiver as:
public class YourReceiver extends WakefulBroadcastReceiver {
Probably your receiver is already a WakefulBroadcastReceiver because notifications are showing..
In the receiver, you start the service (your service has to be an IntentService) using:
startWakefulService(context, your service);
Finally, remember to release the wake lock in the service:
#Override
protected void onHandleIntent(Intent intent) {
<Your_broadcast_receiver_class>.completeWakefulIntent(intent);
}
I hope it helped
We have an Android app that gets Push Notifications via FCM and Background Service that is working even when the app is not active.
We are experiencing some issues with Android Operating System killing the background service and in other cases automatically closing the Notifications for our app. ( By automatically turning off Notifications for our app ).
Our first suspect was Doze mode introduced in Android 6 and later but we are using AlarmManager with setAndAllowWhileIdle() for scheduling the process and this should be enough for firing even during the doze mode as documented here.
In addition we found out that in certain devices like Xiaomi and Huawei devices there is a known issue of Push Notifications not working and background services not running and we handle it.
But the issue still remains in different device types and Android Versions.
Any ideas for the reason this can happen? Thanks!
The System sometimes kills the service when the memory is low.
In your background Service, override onStartCommand() and return START_STICKY as the result.
It will tell the system that even if it will want to kill your service due to low memory, it should re-create it as soon as memory will be back to normal.
I'm developing an application that uses a Bound Service to query information from a server and provide notifications when conditions are met. At the moment, the user must execute the application from their home screen in order to begin receiving updates. But, for example, applications like the Facebook Messenger and Llama run from the moment the phone starts in the background. How do I achieve similar functionality for my long-term application? Also, even when my application is run from the home screen, it will still ocationally quit in the background from what I assume to be the system quitting the application for additional resources. Even though my application is made to restore the service when it begins again, it never seems to restart after it quits (usually after 3 to 4 hours of background activity).
Thanks for your help.
You can register a BroadcastReceiver for the ACTION_BOOT_COMPLETED Intent to detect when the device is booted. This requires the RECEIVE_BOOT_COMPLETED permission.
Instead of using a bound Service you can use a started sticky Service. However, depending on what exactly you want to do, you might want to check if AlarmManager suits your requirements better (maybe in combination with an IntentService, cf. cwac-wakeful).
I am currently developing an Android telephony application that includes a service to handle all the SIP signaling for making and receiving calls.
I want this service to start exclusively when the user has correctly logged into the application. However, I am observing an undesired behavior: if the device is shut down while the app is running, the service is automatically started after the phone boots. This does not happen if the application is closed at the moment of shutting down the phone.
I have been reading about it but no answer comes up. Could anybody explain why this happens and how to prevent it?
Thank you in advance.
Thanks to CommonsWare comment I have quickly found the answer:
[...] The only way a service starts up is if somebody starts it, and the OS will not do that on its own.
I was so blinded thinking the OS was responsible for it that I didn't notice it was being done on purpose, as an undocumented feature inherited from a former version of the app.
There was a BroadcastReceiver listening to the android.intent.action.BOOT_COMPLETED action. This receiver was, among other things, restarting the service on start up when the app had not been properly shut down.
Thank you CommonsWare for your help.
Update
After preventing the BroadcastReceiver from listening to the BOOT_COMPLETE action, I still experience the same behavior.
The reason is that this BroadcastReceiver is also listening to connectivity changes to restart the SIP service when the WIFI or a data connection becomes active, only when the app is running. Wether the application was closed or not is stored in the app preferences, but this value was not properly set when the phone was shut down while the app was running.
That is why the service was still unwantedly starting on boot: because the BroadcastReceiver detected an android.net.conn.CONNECTIVITY_CHANGE at start up and the preference telling wether the app was still running or had been quit was not properly updated.