Update location in background using foreground service android.

Komal Thakkar
3 min readMay 8, 2020

After many struggles I’ve decided to write this article to get a location in the background. I tried many ways to do it but when i removed the app from the background(stack) then it was not working. From Android 8, there are some limits for background execution. I found an easy way to get a location in the background using foreground service. It’ll work if we remove the app from the stack as well.

Foreground Service

A foreground service performs the task which is noticeable to the user and the service continues running when the user is not interacting with the app. i.e Audio Player app, that uses a foreground service to play the audio track that must display the notification even if the app is in the background or removed from the stack.

You can use Workmanager / JobScheduler to schedule the task as well.

To see the detail of service, check Services overview

Now we move step by step.

Step 1: Setup project

First let’s create the project with Empty Activity Template and give the name of the project.

Step 2: Add location dependency in your gradle file

implementation ‘com.google.android.gms:play-services-location:17.0.0’

Step 3: Add permissions to manifest file

<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

Step 4: Create a service class.

I’ve created LocationService.

Step 5: Add requestLocationUpdates() in your service.

Request location updates is to get the location of the device at regular intervals. As well as the geographical location (latitude and longitude). It requests regular updates about a device’s location using the requestLocationUpdates() method in the fused location provider.

For more detail you can check requestLocationUpdates()

private fun requestLocationUpdates() {
val request = LocationRequest()
request.setInterval(10000)
request.setFastestInterval(5000)
request.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY)
val client: FusedLocationProviderClient =
LocationServices.getFusedLocationProviderClient(this)

val permission = ContextCompat.checkSelfPermission(
this,
Manifest.permission.ACCESS_FINE_LOCATION
)
if (permission == PackageManager.PERMISSION_GRANTED) { // Request location updates and when an update is
// received, store the location in Firebase
client.requestLocationUpdates(request, object : LocationCallback() {
override fun onLocationResult(locationResult: LocationResult) {
val location: Location = locationResult.getLastLocation()
if (location != null) {
latitude = location.latitude
longitude = location.longitude
Log.d("Location Service", "location update $location")
}
}
}, null)
}
}

Step 6: Create Notification Chanel(channels)

From Android 8.0 (API level 26), all notifications must be assigned to a channel. For each channel, you can set the visual behavior that is applied to all notifications in that channel.

@RequiresApi(Build.VERSION_CODES.O)
private fun createNotificationChanel() {
val NOTIFICATION_CHANNEL_ID = "com.getlocationbackground"
val
channelName = "Background Service"
val
chan = NotificationChannel(
NOTIFICATION_CHANNEL_ID,
channelName,
NotificationManager.IMPORTANCE_NONE
)
chan.lightColor = Color.BLUE
chan.lockscreenVisibility = Notification.VISIBILITY_PRIVATE
val manager =
(getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager)
manager.createNotificationChannel(chan)
val notificationBuilder =
NotificationCompat.Builder(this, NOTIFICATION_CHANNEL_ID)
val notification: Notification = notificationBuilder.setOngoing(true)
.setContentTitle("App is running count::" + counter)
.setPriority(NotificationManager.IMPORTANCE_MIN)
.setCategory(Notification.CATEGORY_SERVICE)
.build()
startForeground(2, notification)
}

Step 7: Register your service into manifest file

<service
android:name=".service.LocationService"
android:enabled="true"
android:exported="true"
/>

You can get location using the above steps in background but in some devices i.e oppo, vivo devices that won’t work when remove app from the background due to custom os, so we need to restart the service on destroy method for that send broadcast for restart the service.

Step 8: Register Broadcast receiver in manifest file

<receiver
android:name=".receiver.RestartBackgroundService"
android:enabled="true"
android:exported="true"
>
<intent-filter>
<action android:name="restartservice" />
</intent-filter>
</receiver>

Step 9: Restart the service in broadcast receiver

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
context!!.startForegroundService(Intent(context, LocationService::class.java))
} else {
context!!.startService(Intent(context, LocationService::class.java))
}

Step 10: For full source code kindly check the here

Hope It may Help You :)

--

--