Update location in background using foreground service android.
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 :)