Need to fetch background location even when the app is killed

31 Views Asked by At

Im using workmanger to fetch background location and stored in local storage using Realm.I schedule the work interval of 15 minutes its works first time correctly but when I killed the app it does work.How do I acheive this background location fetching job and is there any way to do this job?

This is my Work constrain

 private fun initializeWorker() {
        val constraints = Constraints.Builder()
            .setRequiresDeviceIdle(false)
            .build()

        // Create the work request
        val periodicWorkRequest =
            PeriodicWorkRequestBuilder<LocationWorker>(15, TimeUnit.MINUTES,5,TimeUnit.MINUTES)
                .setConstraints(constraints)
                .addTag(userId)
                .build()

        // Enqueue the work request

        WorkManager.getInstance(this).enqueueUniquePeriodicWork(
            userId,
            ExistingPeriodicWorkPolicy.KEEP, periodicWorkRequest
        )
        val workInfoLiveData: LiveData<List<WorkInfo>> =
            WorkManager.getInstance(this)
                .getWorkInfosForUniqueWorkLiveData(Constants.LOCATION_WORK_MANGER)

        workInfoLiveData.observe(this) { workInfoList ->
            if (workInfoList.isNotEmpty()) {
                val workInfo = workInfoList[0]
                when (workInfo.state) {
                    WorkInfo.State.SUCCEEDED -> {
                        println("WorkInfo State SUCCEEDED")
                        // getLocationDataFromRealm(userId)
                    }
                    WorkInfo.State.BLOCKED -> {
                        println("WorkInfo State BLOCKED")
                    }
                    WorkInfo.State.ENQUEUED -> {
                        println("WorkInfo State ENQUEUED")
                    }
                    WorkInfo.State.FAILED -> {
                        println("WorkInfo State FAILED")
                    }
                    WorkInfo.State.RUNNING -> {
                        println("WorkInfo State RUNNING")
                    }
                    WorkInfo.State.CANCELLED -> {
                        println("WorkInfo State CANCELLED")
                    }
                }
            }
        }
    }


import android.annotation.SuppressLint
import android.content.Context
import android.content.Intent
import android.location.Geocoder
import android.location.Location
import android.util.Log
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.ProcessLifecycleOwner
import androidx.localbroadcastmanager.content.LocalBroadcastManager
import androidx.work.Worker
import androidx.work.WorkerParameters
import com.google.android.gms.location.FusedLocationProviderClient
import com.google.android.gms.location.LocationServices
import com.google.android.gms.location.Priority
import com.google.android.gms.tasks.CancellationTokenSource
import com.mytask.realm.Database
import com.mytask.realm.LocationModel
import com.mytask.realm.UserModel
import com.mytask.utils.Constants
import com.mytask.utils.PreferenceManager
import io.realm.kotlin.ext.query
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.withContext
import java.text.SimpleDateFormat
import java.util.*


class LocationWorker(context: Context, workerParams: WorkerParameters) :
    Worker(context, workerParams) {

    private val fusedLocationClient: FusedLocationProviderClient =
        LocationServices.getFusedLocationProviderClient(context)
    private val geocoder = Geocoder(context)
    private val _context = context
    private val preferenceManager = PreferenceManager(context)
    override fun doWork(): Result = runBlocking {
        try {
           getLocation(context = _context)
            Result.success()
        } catch (e: Exception) {
            Log.e("", "Error getting location", e)
            Result.failure()
        }
    }

    @SuppressLint("MissingPermission")
    private suspend fun getLocation(context: Context) {
        val time: String =
            SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault()).format(Date())
        withContext(Dispatchers.IO) {
            fusedLocationClient.getCurrentLocation(
                Priority.PRIORITY_BALANCED_POWER_ACCURACY,
                CancellationTokenSource().token
            )
                .addOnSuccessListener { location ->
                      if (location != null ) {
                        Database.usersRealmOpen.writeBlocking {
                            val currentLocation = LocationModel().apply {
                                latitude = location.latitude
                                longitude = location.longitude
                                timeStamp = time
                                address = updateAddressText(location)
                            }
                            val userId =   preferenceManager.getString(Constants.KEY_USER_ID).toString()
                            val user: UserModel? = query<UserModel>("userId == $0", userId).first().find()
                            if (user == null) {
                                println("New user")
                                val userModel = UserModel().apply {
                                    this.userId = userId
                                    locations.add(currentLocation)
                                }
                                copyToRealm(userModel)
                            } else {
                                println("Old user")
                                findLatest(user)?.locations?.add(currentLocation)
                            }
                        }
                    }
                }.addOnFailureListener {
                        Result.retry()
                }
        }

    }

    private fun updateAddressText(currentLocation: Location): String {

        val latitude = currentLocation.latitude
        val longitude = currentLocation.longitude
        val addressText = StringBuilder()
        return geocoder.getFromLocation(latitude, longitude, 1)?.let { addresses ->
            val address = addresses[0]
            addressText.append(address.locality).append(", ")
            addressText.append(address.adminArea).append(", ")
            addressText.append(address.countryName).append(", ")
            addressText.toString()
        } ?: ""
    }
    companion object {
        private const val TAG = "LocationWorker"
    
    }
}

0

There are 0 best solutions below