Android Location Service

Get Location on background

In Android, we can get location data on background.
Background means that the user make the app background.(If app is clear, we cannot get)

Service + Google SDK

In this time, we use Google
(Google Play SDK wraps Android location and we don’t care the Internet connection and GPS at the same time)

To use Google Play SDK, you need to add following to build.gradle

compile 'com.google.android.gms:play-services-location:11.4.2'

LocationBackgroundService

class LocationBackgroundService : Service() {

    private val TAG : String = "LocationService"

    private lateinit var fusedLocationClient: FusedLocationProviderClient

    private lateinit var localCallback: LocationCallback

    override fun onBind(intent: Intent?): IBinder? {
        return null
    }

    override fun onCreate() {
        super.onCreate()
        Log.d(TAG, "Start Service")

        if (Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
            // Check Permission  work for background?
            checkPermission()
        } else {
            // Go
            startLocationUpdates()
        }
    }

    override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
        return super.onStartCommand(intent, flags, startId)
    }

    override fun onDestroy() {
        super.onDestroy()
        // Remove all location listeners
        stopLocationUpdates()
    }

    /**
     *  Helpers
     */
    private fun startLocationUpdates() {
        fusedLocationClient = LocationServices.getFusedLocationProviderClient(this)

        if (fusedLocationClient != null) {
            try {
                fusedLocationClient.requestLocationUpdates(createLocationRequest(), object : LocationCallback() {

                    override fun onLocationAvailability(locationAvailability: LocationAvailability) {
                        Log.d(TAG, "Location Available")
                    }

                    override fun onLocationResult(result: LocationResult) {
                        for (location: Location in result.locations) {
                            Log.d(TAG, "Latitude : " + location.latitude)
                            Log.d(TAG, "Longitude : " + location.longitude)

                            val message: String = String.format("Latitude %f, Longitude %f", location.latitude, location.longitude)
                            Toast.makeText(applicationContext, message, Toast.LENGTH_SHORT).show()
                        }
                    }

                }, null)
            } catch (e: SecurityException) {
                // Suppress
            }
        }
    }

    private fun checkPermission() {
        if (locationpermission()) {
            startLocationUpdates()
        }
    }

    private fun locationpermission(): Boolean {
        // For Emulator
        return ContextCompat.checkSelfPermission(applicationContext, android.Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED
                || ContextCompat.checkSelfPermission(applicationContext, android.Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED
    }

    private fun createLocationRequest(): LocationRequest {
        val locationRequest: LocationRequest = LocationRequest()
        locationRequest.interval = 10000            // Interval
        locationRequest.fastestInterval = 5000
        locationRequest.priority = LocationRequest.PRIORITY_HIGH_ACCURACY
        return locationRequest
    }

    private fun stopLocationUpdates() {
        if (fusedLocationClient != null) {
            fusedLocationClient.removeLocationUpdates(localCallback)
        }
    }
}

Unfortunately, we cannot show Permission UI from Service. If we need to show before starting service, we have call Permission dialog API on Activity.

Start Service

To use this service, we need 2

  • Register service in AndroidManifest.xml
  • Call startServcice from any Activity

Call Start Service

startService(Intent(this, LocationBackgroundService::class.java))

Result

This works even if the app becomes background.
Toast is shown every 10 seconds or so.