Other GPS and battery drain

udg

Expert
Licensed User
Hi all,

I'd like to hear from you about "in the field" use of GPS and what to expect as the resulting battery drain.

I wrote my device-tracking app. It is designed along the following assumptions:

1. use GPS only; no service from Google, no accurate location, no wi-fi etc.
2. GPS object defined and initialized in Starter service
3. GPS started in a second service which has : StartAtBoot=True, StickyService=True, StartAt 30minutes intervals
4. Main just set a "privacy" checkbox and has buttons to start/stop service and close app.

The general idea is that, once launched, the service keeps starting every half-hour, does a maximum of 3 readings (one every couple of minutes) and records the eventual locations to a remote server, only if the privacy checkbox allows it and the new location has a distance greater than 200meters from the previous one.

My doubts are:
1. do I really need to try 3 readings every 30minutes or should I simply start the service, wait for the first reading than stop the service and rely on next wake up? Will this significantly save my battery?
2. Do I need the Sticky flag?
3. What can I do to reduce battery drain to a minimum given that the service will operate for the great part of the day (probably the device will be turned off during night-time)?

TIA for all your hints and advice.

udg
 

udg

Expert
Licensed User
1. Because I originally planned a longer delay between wakeups. Something like "wake up once per hour, start gps with 10minutes and 500meters as parameters then stop gps to save on battery".
Now I could set it to "wake up every 30minutes, start gps, do a single reading then stop gps". In this case, should I consider a timer? I mean, there's no guarantee that a valid reading will happen, so I have to consider a way to stop the gps before "going to sleep". (this will avoid to repetively start gps without stopping it in between).
Or, instead of the timer, keep the counter and, although I record just the first valid reading, I stop the gps when counter reaches 3?

2. From the thread introducing the sticky service:
"A sticky service is somewhere between a regular service and a foreground service. Android will kill the process from time to time. However it will recreate it automatically (as soon as possible). For example if you want to track the device location you can use this option. The service (together with the process) will be killed however it will also be recreated again."

PhoneWakeState will be easy on battery drain?
You need to use PhoneWakeState to prevent it from sleeping until it is ready.
On a second reading of your hint, do you suggest PWS for the short time needed to acquire a valid gps reading as a way to assure the OS won't kill the service while it was waiting for a location (after gps.start and before a gps.stop)? If not, can you explain better. Thank you.

3. What if I don't use neither sticky nor PhonewakeState? will the service be awakened anyway due to its StartAt feature?

udg
 
Upvote 0

Erel

Administrator
Staff member
Licensed User
1) You should use a timer if you want to implement a timeout feature.

2) Without PhoneWakeState, the OS will kill the process before the GPS is ready.

3) The process will start, however there is a good chance that it will be killed.

It is not a bad idea to make it a sticky service. It means that the process will stay alive longer.
 
Upvote 0

udg

Expert
Licensed User
Do you mind to check the following simplified code? Thanks
B4X:
#Region  Service Attributes
   #StartAtBoot: True
   #StartCommandReturnValue: android.app.Service.START_STICKY
#End Region

Sub Process_Globals
   Dim timer1 As Timer                  'used to stop GPS readings
   Dim LastLoc As Location              'keeps track of last valid location
   Dim const mindist As Float = 200.0   'minimum distance in meters between valid GPS locations
End Sub

Sub Service_Create
   LastLoc.Initialize2("00:00:00","00:00:00")
End Sub

Sub Service_Start (StartingIntent As Intent)
   'next wake up time: 30minutes from now
   StartServiceAt("", DateTime.Now + (30 * DateTime.TicksPerMinute), True)
   Dim pws As PhoneWakeState
   pws.PartialLock                     'acquires partial lock to ensure OS won't kill service (for next 60s)
   timer1.Initialize("tm1", 60000)     '60s timeout to complete GPS reading and server recording
   timer1.Enabled = True               'starts timer; when it ticks: lock release, gps stop, timer stop
   If Starter.GPS1.GPSEnabled Then Starter.GPS1.Start(30000, mindist)     '30s and 200m
End Sub

'Stops timer and GPS; release lock
Sub tm1_Tick
   timer1.Enabled = False
   If Starter.GPS1.GPSEnabled Then Starter.GPS1.Stop
   Dim pws As PhoneWakeState
   pws.ReleasePartialLock
End Sub

Sub Service_Destroy
   CancelScheduledService(Me)
End Sub

Sub GPS_LocationChanged (Location1 As Location)
   If (Location1.DistanceTo(LastLoc) > mindist) And Starter.RecGPS Then
      LastLoc = Location1
      SaveGPSReading(Location1)
   Else
      'too close to previous location so no need to record it
      'OR recording not allowed due to privacy setting
   End If
End Sub

Sub JobDone (Job As HttpJob)
    .....
   Job.Release
   tm1_Tick   'stops timer, gps and lock
End Sub

udg
 
Upvote 0

Erel

Administrator
Staff member
Licensed User
I think that it is safer to remove the call to CancelScheduledService from Service_Destroy and move the code from Service_Start to Service_Create.

You should assume that Service_Start can be called multiple times. Service_Create will run only once until the service is destroyed.

Call StopService(Me) when you are done reading the GPS.
 
Upvote 0

udg

Expert
Licensed User
Thank you.
I set up things that way because I intended the service to be active (i.e. wake up at boot and then every 30minutes) for several days. The CancelScheduleService should be triggered only by a command issued from Main where I have a button to initially start the service and one to shut it off (using StopService).
It would be something like a widget; I launch the app once, set the privacy flag and launch the servive above then terminate the app.
From that moment on (unitl I open up the app again and terminate the service), the service will be wake up every 30minutes and after a reboot by OS, start gps (if available), try a reading and stop gps. After 30minutes loop again.

Or at least that was my intention..eheh

udg
 
Upvote 0

udg

Expert
Licensed User
Reading again post #6, are you suggesting that the correct way to accomplish my goal is to:
start the service due to servicestartat in service_create each half hour
Start a timer set to a short interval
Check gps is on and start it
Eventually acquire a valid location and send it to the remote server
In timer_tick turn off gps and call stopservice

Obviously first servicevrun will be launched by main by means of its dedicated button. Did I understood well your suggestion? Thanks.

Udg
 
Upvote 0

udg

Expert
Licensed User
Ok, thanks. I retooled my service following your advice and (no doubts) it is working!
Just a note: in StartService At documentation (and almost in any thread citing it) it is pointed out to place it in Service_Start. Maybe a note explaining when it is safe and correct to place it in Service_Create will help.

Question: calling StopService, will the whole process (I mean the process hosting starter and tracker services) survive so to be awakend in 30 minutes or will the OS eventually destroy it and recreate it later? If the latter, I would need to save locally (local storage) last valid location in order to avoid DB recording of too close locations. Or even modify B4J module to decide whether to store or not a reading in the DB.
 
Last edited:
Upvote 0

RVP

Active Member
Licensed User
I wrote an app for a customer to use with a WOrk Order system. Their in field techs use it to receive and enter details of jobs they are working on. It also tracks their location as they move from job to job and anytime they make time entries. It runs the GPS service all the time, gets a reading as often as every few seconds if they are moving, and their phones easily run for the entire day even with phone calls added in. They are running on the Samsung Note 3 which has a decent battery live anyways, but I don't think that GPS use is as energy intensive as some people believe. However it is possible that this phone just has a better GPS chip than others.
 
Upvote 0

udg

Expert
Licensed User
Hi all,
I conducted an H24 experiment to test battery drain due to my GPS-based tracking app. Here are my figures.

Rules:
Wake-up each half hour
PhoneWakeState.PartialLock active up to 25 seconds
GPS1.Start(0, 100)
Service stopped after a fix or because of the 25 secs limit

So, the worst case is when the app is awakened 48 times (in a whole day) not finding any fix, causing a 25 x 48 = 1200 seconds of PartialLock/live activity. For any valid fix we should exeperience reduced battery drain from that worst case.
B4X:
Day Time                          07:59        09:30          11:05          12:13            12:56        14:14         16:14        18:14          20:16
Battery %                         92           88             84             84               83           82            77%          73%            71
Phone activity time               00:03:00     01:36:00       03:10:00       04:18:00         05:00:00     06:18:40      08:18:00     10:18:00       12:19:00
app battery drain                  < 1mAh      1 mAh          2 mAh          3mAh             3 mAh        4mAh          6 mAh        7 mAh          9mAh
app CPU time                      5"           7"             10"            12"              13"          16"           23"          26"            33"
app CPU time (background)         5"           7"             10"            12"              13"          16"           23"          26"            33"
app keep system on                5"           45"            114"           142"             153"         222"          290"         387"           481"
data (download/upload)         ---             480B/560B     960B/1.09KB  1,41KB/1.64KB    1.88/2.19    1.88/2.19     2.25/2.74      2.25/2.74    2.25/2.74


Time                             22:14          00:14         07:59
Battery %                        69             67            60
Phone activity time              14:18:00       16:18:00      24:00:00
app battery drain                10 mAh         12 mAh        > 40 mAh
app CPU time                     39"            43"           72"
app CPU time (background)        39"            43"           72"
app keep system on               553"           649"          965"
data (download/upload)       2.25/2.74        2.25/2.74     3.24/3.90

I found surprising the final reading, where it shows a 40+ mAh consumption. After 12 hours we had 9mAh so we could expect something between 18 and 20 mAh but here we have more than double of it!

Edit: another consideration; excluding night-time I registered a costant 3mAh every 4 hours of battery drain (look at data for 4/8/16) so I'm inclined to believe that something happend during those night hours.. a ghost, electro-magnetic thunderstrom, who knows!

I'd like to hear from you, commenting my data or publishing your own. Indeed GPS looks a terrible option when it comes to battery consumption.

udg

ps: sorry, it seems I'm not able to put my data in a decent columnar style.
pps: ok, much better now after some manual editing
 
Last edited:
Upvote 0

udg

Expert
Licensed User
My apologies to all. Due to the unsatisfactory findings reported in post #13 above, I revised (again) my code and started a new h24 test.
First, there was an error in code that kept the 25 sec countdown to its end even if a valid (but too close to previous one) fix was taken; due to this oversight a lot of readings eat up 25 seconds instead of just a couple.
Then there was the night-ghost mystery that made things worse; but that is another story (I guess that something broke the process and the Lock remained active).

Anyway, please find below my new figures (to be updated in the course of the day):
B4X:
Time                      15:05    18:05    19:05    20:06    21:05    22:07    23:08    07:05    08:05    10:05    12:05    13:05    15:05
Battery                   97%      90%      89%      88%      86%      85%      84%      82%      80%      77%      72%      67%      66%
Phone activity time       00:00:00 03:00:00 04:00:00 05:00:00 06:00:00 07:00:00 08:00:00 16:00:00 17:00:00 19:00:00 21:00:00 22:00:00 24:00:00
app battery drain         <1 mAh   <1 mAh   1 mAh    1 mAh    2 mAh    2 mAh    2 mAh    3 mAh    3 mAh    4 mAh    5 mAh    5 mAh    6 mAh
app CPU time              1"       3"       6"       6"       8"       8"       8"       12"      14"      14"      22"      25"      26"
app CPU time (background) 0"       3"       5"       6"       8"       8"       8"       12"      13"      14"      22"      24"      25"
app keep system on        3"       29"      47"      63"      86"      96"      109"     157"     168"     190"     231"     244"     265"

Keep in mind that I purposedly kept the device away from GPS detection for most of the time in order to test my revised code.

@Erel: I commented out the Sticky option on the assumption that since the service acquires a Lock it could be considered "safe" from OS claims on memory for those 25s max it needs.
 
Last edited:
Upvote 0

Erel

Administrator
Staff member
Licensed User
I commented out the Sticky option on the assumption that since the service acquires a Lock it could be considered "safe" from OS claims on memory for those 25s max it needs.
The sticky option is not required in this case. However you should make it a foreground service until you finish the reading.
 
  • Like
Reactions: udg
Upvote 0
Top