Background Location for android (Lollipop and above)

Chances are high you landed on the above page first before this article. COVID has brought out the developer in us and almost everyone wants to create an app that monitors user’s whereabouts in the background. If you are new to android development, like every optimistic programmer you start coding.

1 hour after your code sprint :)

There’s an easy workaround to the restriction shall you wish to implement it. Enter: Foreground Services. Let’s dive into the implementation.

Disclaimer: Traditionally getting the current location is implemented by Fused Location Client, but for this article let’s focus on the service. The API implements it for us in the backend along with other fallbacks.

Step 1: Install the Library

implementation 'io.nlopez.smartlocation:library:3.3.3'

Step 2: Adding permissions

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

Step 3: Implementing the service class

class LocationService : Service() {
private var builder : LocationParams.Builder?=null
private var
mNotificationManager: NotificationManager? = null

override fun
onBind(intent: Intent?): IBinder {
throw UnsupportedOperationException("Not yet implemented")
}

override fun onCreate() {
super.onCreate()
builder = LocationParams.Builder()
.setAccuracy(LocationAccuracy.HIGH)
.setInterval(Constants.LOCATION_UPDATE_INTERVAL_IN_MILLISECONDS.toLong())

mNotificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val mChannel = NotificationChannel(Constants.NOTIFICATION_CHANNEL_ID, Constants.NOTIFICATION_CHANNEL_NAME, NotificationManager.IMPORTANCE_DEFAULT)
mNotificationManager!!.createNotificationChannel(mChannel)
}
}

override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
startForeground(1, notification)
SmartLocation.with(this)
.location()
.continuous()
.config(builder!!.build())
.start { location ->
Toast.makeText(this, location.latitude.toString() + " " + location.longitude.toString(), Toast.LENGTH_SHORT).show()
Log.w(TAG,location.toString())
}
return START_STICKY
}


private val notification: Notification
get() {
val builder = NotificationCompat.Builder(this, Constants.NOTIFICATION_CHANNEL_ID)
.setContentText(getString(R.string.body_text))
.setContentTitle(getString(R.string.header_text))
.setOngoing(true)
.setSmallIcon(R.drawable.ic_notification)

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
builder.setChannelId(Constants.NOTIFICATION_CHANNEL_ID)

return builder.build()
}

companion object{
private val TAG = LocationService::class.java.simpleName
}
}
/**
Please define the following constants when you use the code
Constants.NOTIFICATION_CHANNEL_ID
Constants.NOTIFICATION_CHANNEL_NAME
Constants.LOCATION_UPDATE_INTERVAL_IN_MILLISECONDS
*/

In a gist, my onCreate does all the heavy lifting and creates a persistent notification while onStart handles getting the location and showing the toast.

Step 4: Registering the service in MainActivity

class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)

if (!Helper.isLocationPermissionGranted(this))
requestPermissions()
else
registerService()

}

private fun registerService(){
val serviceIntent = Intent(this, LocationService::class.java)
startService(serviceIntent)
}
private fun requestPermissions(){/**handle request permission and onRequest permission result accoringly*/}

Step 5: Registering the service in Manifest

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

There you have it. Persistent background location in the background. I’ll love to keep the article updated in case there is something that I missed.

Stay Safe❤

Sometimes it is the people no one can imagine anything of, do the things no one can imagine.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store