Android Question Service Stops Posting GPS Data

spv4u

Member
Licensed User
Hi

I have used the GPS example and added some functionality as the plan here is to have a simple GPS logger that submits it location every 1 minutes to a API using HTTP POST.

The app and service work fine when launched, and once the device screen is off through timeout or turned off however after about 6 minutes the app stops posting the JSON data, when the device is woken back up the data is submitted again. I added a count to the JSON and can see records 0-6 arrive fine then it stops, after waiting a few minutes and waking the device the data is received again with counts higher e.g. 10 showing that the service seems to still be working and counting but the data is not being sent.

I thought that the service was beign killed on my phone so I added #StartCommandReturnValue: android.app.Service.START_STICKY under the service attributes but no joy. After reading the forum and other examples I added StartServiceAt("", DateTime.Now + 60 * 1000, True) to schedule the restart, I believe the blank string is fine as it is scheduling itself.

As a side note I could not get Service.StartForeground to work at all as it always threw a complie error.

Here is some code from the service to show how it is working, any help would be great

B4X:
#Region  Service Attributes
    #StartAtBoot: False
    #ExcludeFromLibrary: True
    #StartCommandReturnValue: android.app.Service.START_STICKY
#End Region

B4X:
Sub Service_Create
    GPS1.Initialize("GPS")
        StartServiceAt("", DateTime.Now + 60 * 1000, True)
End Sub

B4X:
Sub CreateJSON
    'Create JSON file for sending
    Dim gen As JSONGenerator
    Dim m As Map
    m.Initialize
    m.Put("ID", srvDeviceID)
    m.Put("Lat", srvLat)
    m.Put("Lon", srvLon)
    m.Put("Spd", srvSpeed)
    m.Put("Ver", Version)
    m.Put("Count", sendCount)
    gen.Initialize(m)
    genString = gen.ToString
    If debugStatus = True Then
         Log(genString)
    End If
End Sub

B4X:
Sub PostLocation
    'Set Data
    srvLat = srvLocation.Latitude
    srvLon = srvLocation.Longitude
    Dim mph As Int = (srvLocation.Speed / 0.44704)
    srvSpeed = mph
   
    'Create JSON file for sending
    CreateJSON
   
    'Submit data
    Dim NS As HttpJob
    NS.Initialize("PostData",Me)
    NS.PostString (sendURI, genString)
    If debugStatus = True Then
        Log("URL = " & sendURI & " String " & genString)
        Log("Service Send")
        Log("Send Number = " & sendCount)
    End If

    'Cleardown
    lastSend = DateTime.Now
    sendCount = sendCount + 1
End Sub

Sub JobDone (Job As HttpJob)
       If debugStatus = True Then
           Log("JobName = " & Job.JobName & ", Success = " & Job.Success)
    End If
End Sub
 

Jmu5667

Well-Known Member
Licensed User
Hello

You have a number of options available to you. You can 1.) schedule acallback to your service(GPS Logger) or 2.) you can keep the service running as a background task.

For option 2 try the following

B4X:
Sub Process_Globals
   'These global variables will be declared once when the application starts.
   'These variables can be accessed from all modules.   

   Dim n1 As Notification   
End Sub

Sub Service_Create
 
   n1.Initialize
   n1.SetInfo("Your App Name","",Main)
   n1.Number = 1
   n1.Icon = "icon"
   n1.Vibrate = False
   n1.Sound = False
   n1.OnGoingEvent = True
   ' // tell android to treat this service as foreground service
   Service.StartForeground(1,n1)
   
End Sub

for option 1 try the following:

Put this code at the end of your service.

B4X:
Sub schedulecallback(timeToAlarm As Long)
   
   Dim p As Phone
   
    
   ' // zero check
   If timeToAlarm = 0 Then
     Return
   End If  
   
   If p.SdkVersion >= 23 Then     
     Dim srvAt As JavaObject
     srvAt.InitializeContext
     srvAt.RunMethod("StartServiceAtExactWhileIdle", Array(timeToAlarm, True))
   Else
     mod_functions.writelog("svc_gps(), call back using StartServiceAtExact()")
     StartServiceAtExact(Me,timeToAlarm,True)
   End If

   
   
End Sub

#If JAVA
   //import android.app.Service;
   import android.app.AlarmManager;
   import android.app.PendingIntent;
   import android.content.Context;
   import android.content.Intent;
   import android.os.PowerManager;

   public void StartServiceAtExactWhileIdle(Long time, Boolean wakeUp){
    AlarmManager alMan = (AlarmManager)getSystemService(Context.ALARM_SERVICE);
    Intent intent = new Intent(this.getApplicationContext(), this.getClass());
    PendingIntent penInt = PendingIntent.getService(this.getApplicationContext(), 1, intent, 134217728);
    alMan.setExactAndAllowWhileIdle(wakeUp?AlarmManager.RTC_WAKEUP:AlarmManager.RTC, time, penInt);
   }
#End If

When you have done your work in the service, end the service like this:

B4X:
Sub Service_Destroy
       
   
       ' // schedukle the service callback
       schedulecallback(theTimeToCallBackAt)   

End Sub


Give both method a go and see what works for you, I would go with option 1 myself.

REgards

John.
 
Upvote 0

spv4u

Member
Licensed User
Thanks

Getting undeclared varible mod_fuctions do I need to add additional libaries other than javaobject?
 
Upvote 0

Jmu5667

Well-Known Member
Licensed User
Thanks

Getting undeclared varible mod_fuctions do I need to add additional libaries other than javaobject?

mod_functions line can be removed.

mod_functions is a code module and the writelog is a function.

B4X:
Sub writelog(m As String)
 
   Dim s As OutputStream, b() As Byte
   Dim TimeFormat, myTimeFormat As String
   Dim rt As RuntimePermissions
 
   Try
     ' // save existing time format
     TimeFormat = DateTime.TimeFormat
       
     myTimeFormat = "HH:mm:ss.SSS"
     ' // set date time format
     DateTime.TimeFormat = myTimeFormat
     ' // debugger logging
     Log(DateTime.Date(DateTime.Now) & " " & DateTime.time(DateTime.Now) & " - " & m)
     ' // create log data for file
     m = DateTime.Date(DateTime.Now) & " " & DateTime.time(DateTime.Now) & " - " & m & Chr(10) & Chr(13)
     ' // restore date time format
     DateTime.TimeFormat = TimeFormat
   
     b = m.GetBytes("UTF8")
   
     If File.ExternalWritable = False Then
       If File.Size(File.DirInternal, "your_app_name.log") >= 8388608 Then
         File.Delete(File.DirInternal, "your_app_name.log")
       End If
       s = File.OpenOutput(File.DirInternal, "your_app_name.log", True)
     
     Else
       If File.Size(rt.GetSafeDirDefaultExternal(""), "your_app_name.log") >= 8388608 Then
         File.Delete(rt.GetSafeDirDefaultExternal(""), "your_app_name.log")
       End If
       s = File.OpenOutput(rt.GetSafeDirDefaultExternal(""),"your_app_name.log", True)
     End If
   
     s.WriteBytes(b,0,b.Length -1)
     s.Flush
     s.close

   
   Catch
     ToastMessageShow("writelog, error - " & LastException.Message,True)
   End Try
   
 
End Sub

regards

John.
 
Last edited:
Upvote 0

An Schi

Well-Known Member
Licensed User
In addition to the other comments:
Is it possible that you lost Internet connection and the data wasn't sent cause of this?
 
Upvote 0

spv4u

Member
Licensed User
Thanks John

I went with option 2 which works well for our implementation as it needs to be transparant to the user that we are monitoring them.

One last question is that when looking at the notification the Title is correct but the sub test is not show, the phone states

GPS Logger is running
Tap for more information or to stop the app

Is there a way to get the sub information on the alerts list and when clicked open the app rather than the App Info where they can unistall or force stop

Regards

Mark
 
Upvote 0

Jmu5667

Well-Known Member
Licensed User
Thanks John

I went with option 2 which works well for our implementation as it needs to be transparant to the user that we are monitoring them.

One last question is that when looking at the notification the Title is correct but the sub test is not show, the phone states

GPS Logger is running
Tap for more information or to stop the app

Is there a way to get the sub information on the alerts list and when clicked open the app rather than the App Info where they can unistall or force stop

Regards

Mark

Hi Mark

You need to call

B4X:
Sub show_notify(pMessage As String)
   
   n1.SetInfo("Your App Name",pMessage,Main)
   n1.Notify(1)
   
End Sub

from within your service and the parameter you pass is the sub text.

Regards

John.
 
Upvote 0

spv4u

Member
Licensed User
John

Thanks for all of your help on this, it is now running solid and has the correct text on the notification.

My problem is now resolved :)
 
Upvote 0
Top