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"
}
}