Background Service to Loop FusedLocation

533 views Asked by At

I cannot seem to create an infinite loop that runs periodically for a background service and is reliable.

The app uses a Service to post a GPS location every 5 seconds using a FusedLocationClient LocationCallback.

The functions loop as expected when running on the main thread, however the functions stop looping shortly after starting a different app. This is the case for a new thread, as well as a background service, and even a new thread created by a background service, it consistently stops looping shortly after starting a different app. Shortly thereafter onDestroy() is called.

The only way I have been able to successfully continue looping a function in a Service while the user is in a different app is by having a while(true) loop. However, when I implement this method, I never get a call back from the FusedLocationClient. I cannot figure out why or how to get around this problem.

I have already reviewed the Android Guides and API documentation for Background processing, Background Service, Handler, Looper, Thread.

As well as the StackExchange questions:how to run infinite loop in background thread and restart it, How to run an infinite loop in Android without freezing the UI.

My question is how do I maintain a continuous loop in a background service that does not interfere with the UI AND does not interfere with the FusedLocationCallback

Below is a snippet of my code. And yes, I declared everything correctly in the manifest.

class MyService: Service(){

private lateinit var locationRequest: LocationRequest
private lateinit var locationCallback: LocationCallback
private lateinit var looper: Looper
private lateinit var context: Context
data class postGPS(...)

val runnable: Runnable = object : Runnable {
    override fun run() {
        getLocation()
    }
}

override fun onStartCommand(...): Int {
    context = this
    val thread = BackgroundThread()
    thread.start()
    return START_STICKY
}

inner class BackgroundThread: Thread(){
override fun run() {
    Looper.prepare()
    looper = Looper.myLooper()!!
    handler = Handler(looper)
    getLocation()
    Looper.loop()
    }
}
@SuppressLint("MissingPermission")
fun getLocation()
{
    fusedLocationClient = LocationServices.getFusedLocationProviderClient(context!!)
    locationRequest = LocationRequest()
    locationRequest.interval = 1000
    locationRequest.fastestInterval = 1000
    locationRequest.smallestDisplacement = 10f
    locationRequest.priority = LocationRequest.PRIORITY_HIGH_ACCURACY
    locationCallback = object : LocationCallback() {
        override fun onLocationResult(locationResult: LocationResult?) {
            locationResult ?: return
            if (locationResult.locations.isNotEmpty()) {
                PostGPS(postGPS(locationResult.lastLocation)
            }
        }
    }
    fusedLocationClient.requestLocationUpdates(
        locationRequest,
        locationCallback,
        looper
    )
}

    private fun PostGPS(gps: postGPS){
    val queue = Volley.newRequestQueue(context)
    val url = "https://www.URL.com/api"
    val stringReq: StringRequest =
        object : StringRequest(
            Method.POST, url,
            Response.Listener { response ->
                Toast.makeText(context, response, Toast.LENGTH_SHORT).show()
                handler.postDelayed(runnable,5000) //Loop for posting GPS location
            },
            Response.ErrorListener { error ->
                Toast.makeText(context, error.message.toString(),Toast.LENGTH_SHORT).show()
            }
        ) {

            override fun getBody(): ByteArray {
                return gps.toByteArray(Charset.defaultCharset())
            }
        }
    queue.add(stringReq)
}
override fun onBind(intent: Intent): IBinder? {
    return null
}

override fun onDestroy() {
    Toast.makeText(this, "service done", Toast.LENGTH_SHORT).show()
}
}
0

There are 0 answers