Android Question Startserviceat during sleep

fransvlaarhoven

Active Member
Licensed User
Longtime User
Hallo,

I have a foreground service that reschedules itself using StartServiceAt("", RestartAt, True)

This works fine with a lot of different devices.

However, it seems to be that some android implementations go into some kind of deep sleep mode that just ignores the scheduled restart of the service.

I also experimented with phonewakestate but nothing seems to avoid this problem.

Do you have a suggestion how to solve this problem?
 

fransvlaarhoven

Active Member
Licensed User
Longtime User
Why is the foreground service stopped? Are you stopping it?

nothing has changed in the code of the app. With a few exceptions, the app runs normally on devices with Android 5.1

I've tested the app on a blackberry priv running android 6.01.

I looks a bit as this behavior is caused by the new "doze" as introduced in Android 6

It is doing more or less as stated in the documentation:

- puts the device in a sleep mode when the device is not moving, toched etc. for a period longer then 1 hour
- suspends receiving GCM messages that are sended to the device with normal priority
- suspends access to the network
- wakes up the device when moving, shaking, etc the device
- wakes up the device once every few hours. During this period, normal access to the network is possible.

from the documentation of google, it should be possible to "whitelist" an app but up to now, I was not able to do that.

All suggestions are more then welcome.
 
Last edited:
Upvote 0

marcick

Well-Known Member
Licensed User
Longtime User
from the documentation of google, it should be possible to "whitelist" an app but up to now, I was not able to do that.

In setting-battery-other-optimize battery you choose your app and put it in the whitelist.
Don't forget to add this code in your service_create:

B4X:
Dim n As Notification
n.Initialize
Service.StartForeground(1,n)

with StartForeground my service seems to work correctly also withou the app in the whitelist, so it seems the StartForeground overwrite that parameter.
 
Upvote 0

fransvlaarhoven

Active Member
Licensed User
Longtime User
In setting-battery-other-optimize battery you choose your app and put it in the whitelist.
Don't forget to add this code in your service_create:

B4X:
Dim n As Notification
n.Initialize
Service.StartForeground(1,n)

with StartForeground my service seems to work correctly also withou the app in the whitelist, so it seems the StartForeground overwrite that parameter.

This is already in the code but seems to make no difference. Note however that testing this is a lengthy process: the first hour, all runs normal. It is only after 1 hour or more that "doze" shuts down the phone. (at least with the phone I use for testing, a BlackBerry priv)

Also "Whitelisting" seems to make no difference: I switched off battery optimization for ALL apps on the phone with no effect at all
 
Upvote 0

marcick

Well-Known Member
Licensed User
Longtime User
Without StartForeground my StartServiceAt stops immediatly to work when i switch off the screen.
With StartForeground it seems to work, but I didn't do a so longer test, just a few minutes.....
I'll try to leave the device with screen off for a longer time and see what's happen
 
Upvote 0

fransvlaarhoven

Active Member
Licensed User
Longtime User
Upvote 0

fransvlaarhoven

Active Member
Licensed User
Longtime User
Why ?
Shouldn't the release be done when app is terminated ?

As far as I understand it, the partial lock must avoid that the cpu enters a sleep mode while running the code in the service.
After that it is the responsibility of the OS to restart the service. (Please Erel, correct me if I'm wrong)
 
Upvote 0

marcick

Well-Known Member
Licensed User
Longtime User
Maybe our scenario are different.
I have a service that must start every 30 seconds so I have a StartServiceAt repeated at each service start.
I have acquired the partial lock at application.start and I release it only when the app is terminated by the user.
 
Upvote 0

wes58

Active Member
Licensed User
Longtime User
Maybe our scenario are different.
I have a service that must start every 30 seconds so I have a StartServiceAt repeated at each service start.
I have acquired the partial lock at application.start and I release it only when the app is terminated by the user.
As I wrote in your other post:
In Android 6 a new method has been introduced in Alarm Manager to allow for exact scheduling of alarms - setExactAndAllowWhileIdle. But if you read about it, you will find the following:
These alarms can significantly impact the power use of the device when idle (and thus cause significant battery blame to the app scheduling them), so they should be used with care. To reduce abuse, there are restrictions on how frequently these alarms will go off for a particular application. Under normal system operation, it will not dispatch these alarms more than about every minute (at which point every such pending alarm is dispatched); when in low-power idle modes this duration may be significantly longer, such as 15 minutes.

So it may not be possible now to start the service every 30 seconds.
 
Upvote 0

marcick

Well-Known Member
Licensed User
Longtime User
I have tested it yesterday and seemed to work. The service was running every 30 seconds at screen off.
But after one night, I see this morning the service has stopped to work.
Now I'm repeting the test adding my app to the whitelist.
Looks like it was very easy for Google to improve the power consumption in this new OS, just cutting some vital functionality .....
I think I'll definitely abandon this method and move to remote notification, as Erel said and as I had to do in IOS because there were no other chances.
 
Upvote 0

fransvlaarhoven

Active Member
Licensed User
Longtime User
I have done some more testing keeping the app running overnight.

- in the manifest: <uses-sdk android:minSdkVersion="10" android:targetSdkVersion="23"/>
- a service running as Service.StartForeground
- the first line in Service_Start is WakeState.PartialLock
- the last line in Service_Start is WakeState.ReleasePartialLock

- the service reschedules itself using Erel's code:

Dim p As Phone
If p.SdkVersion < 23 Then
StartServiceAtExact("", RestartAt, True)
Else
Dim in As Intent
in.Initialize("", "")
in.SetComponent(Application.PackageName & "/.monitor")
Dim ctxt As JavaObject
ctxt.InitializeContext
Dim am As JavaObject = ctxt.RunMethod("getSystemService", Array("alarm"))
Dim pi As JavaObject
pi = pi.InitializeStatic("android.app.PendingIntent").RunMethod("getService", _
Array(ctxt, 1, in, 134217728))
am.RunMethod("setExactAndAllowWhileIdle", Array(0, RestartAt, pi))
End If

the service is supposed to run once a second when the screen is on and once a minute when the screen is off
-when the screen is on, running the service is limited to once every 5 seconds
-when the screen is off, the first hour, all runs as normal
-when "doze" starts, the service is running once every 9 minutes

As far as I can see, this is the behavior as intended by google.

In order to test this, I made the service as such that, each time the service runs, a message is sended to a server because when connecting the phone to the computer and looking at the log switches off Doze....
 
Upvote 0

marcick

Well-Known Member
Licensed User
Longtime User
And you have used the whitelist I suppose.
So, what's its intended for if it doesn't work ? .....
 
Upvote 0

fransvlaarhoven

Active Member
Licensed User
Longtime User
And you have used the whitelist I suppose.
So, what's its intended for if it doesn't work ? .....

Indeed, I also whitelisted the app.

It seems that google wants to cut down on the battery consumption. And indeed, this is a simple way of doing it...

Unfortunately, part of my app keeps a connection with a mailserver open (IMAP). That functionality is completely broken with this behavior :oops::oops:

I will run some tests to see if one must whitelist the app or not, just look what happens.
I also will run some tests to see if high priority GCM-messages wake up the device.

But in the mean time, the whole thing is seriously interfering with the behavior of my app...
 
Upvote 0
Top