'How to get location in Android 12 and above when app is closed?

I am trying to get location in android 12 when app is closed using WorkManager. But the issue is, it work for few minutes and get killed by the OS. I am unable to find out why this is happening.

What could be the solution for this?

Question updated with code

WorkManager

class LocationWorker(
    private val context: Context,
    private val workerParameters: WorkerParameters
) : CoroutineWorker(context, workerParameters) {

    private val NOTIFICATION_ID = 10

    private var mRandomNumber = 0
    private var mIsRandomGeneratorOn = false

    private val MIN = 0
    private val MAX = 100

    private lateinit var fusedLocationClient: FusedLocationProviderClient

    override suspend fun doWork(): Result {
        fusedLocationClient = LocationServices.getFusedLocationProviderClient(context)
        setForeground(createForeGroundInfo())
        getLocation()
        return Result.success()
    }

    private fun createForeGroundInfo(): ForegroundInfo {

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            createChannel()
        }

        val notification =
            NotificationCompat.Builder(applicationContext, NOTIFICATION_ID.toString())
                .setContentTitle("Location Sharing")
                .setPriority(NotificationCompat.PRIORITY_HIGH)
                .setSmallIcon(R.drawable.ic_location)
                .setOngoing(true)
                .build()

        return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
            ForegroundInfo(NOTIFICATION_ID, notification, FOREGROUND_SERVICE_TYPE_LOCATION)
        } else {
            ForegroundInfo(NOTIFICATION_ID, notification)
        }
    }

    @RequiresApi(Build.VERSION_CODES.O)
    private fun createChannel() {
        val channelName = "location_sharing"
        val channel = NotificationChannel(
            NOTIFICATION_ID.toString(),
            channelName,
            NotificationManager.IMPORTANCE_DEFAULT
        )
        val manager =
            (context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager)
        manager.createNotificationChannel(channel)
    }

    private fun getLocation() {
        val locationRequest: LocationRequest = LocationRequest.create().apply {
            interval = 3000
            fastestInterval = 1500
            priority = LocationRequest.PRIORITY_HIGH_ACCURACY
            maxWaitTime = 2000
        }

        val locationCallback: LocationCallback = object : LocationCallback() {
            override fun onLocationResult(locationResult: LocationResult) {
                val locationList = locationResult.locations
                if (locationList.isNotEmpty()) {
                    val location = locationList.last()
                    Log.d("ServiceDemo", location.latitude.toString()+ " " + System.currentTimeMillis())
                }
            }
        }

        if (ActivityCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION)
            != PackageManager.PERMISSION_GRANTED
            && ActivityCompat.checkSelfPermission(context, Manifest.permission.ACCESS_COARSE_LOCATION)
            != PackageManager.PERMISSION_GRANTED) {

            Toast.makeText(applicationContext, "Permission required", Toast.LENGTH_LONG).show()
            return
        }else{
            fusedLocationClient.requestLocationUpdates(locationRequest, locationCallback, Looper.getMainLooper())
        }
    }
}

MainActivity

onCreate method

val constraints = Constraints.Builder()
       .setRequiredNetworkType(NetworkType.CONNECTED)
       .build()

workManager = WorkManager.getInstance(applicationContext)

workRequest = PeriodicWorkRequestBuilder<LocationWorker>(15, TimeUnit.MINUTES)
       .setConstraints(constraints)
       .build()
workManager!!.enqueueUniquePeriodicWork("Testing WorkManager", ExistingPeriodicWorkPolicy.REPLACE, workRequest as PeriodicWorkRequest)

I wonder how WhatsApp share location because it doesn't ask user to change the battery mode to unrestricted.



Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source