Reputation: 151
I have a service worker that runs every 10 minutes and needs to get the current latitude and longitude every time it runs and I've been using the following code:
private var fusedLocationClient: FusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(applicationContext)
override fun doWork(): Result {
val priority = Priority.PRIORITY_HIGH_ACCURACY
val cancellationTokenSource = CancellationTokenSource()
fusedLocationClient.getCurrentLocation(priority, cancellationTokenSource.token)
.addOnSuccessListener { location ->
Log.e("Location", "location is found: $location")
curLat = location.latitude
curLong = location.longitude
}
.addOnFailureListener { exception ->
Log.e("Location", "Oops location failed with exception: $exception")
}
}
Unfortunately, location is always null.
Per https://stackoverflow.com/a/72038138/4696054 and several other answers: "If the location subsystem wasn't already on, it doesn't know what the location was, so it returns null. If you want to ensure that you don't get null, request updates."
This "request updates" part is confusing to me. I just need to get the location once when the service starts.
How am I able to do that and where do I initialize the location service for the update (other answers I found have been deprecated)? Service worker does not have "OnCreate" method where I can initialize the location service for https://developer.android.com/develop/sensors-and-location/location/request-updates and LocationRequest has been deprecated (at least Create () is deprecated).
Granted Permissions are:
android.permission.ACCESS_COARSE_LOCATION and android.permission.ACCESS_FINE_LOCATION and ACCESS_BACKGROUND_LOCATION
EDIT: Per @CommonWare I tried:
val currentBuilder = CurrentLocationRequest.Builder().setDurationMillis(30000)
currentLocationRequest = currentBuilder.build()
fusedLocationClient.getCurrentLocation(currentLocationRequest, null)
.addOnSuccessListener { location ->
Log.e("Location", "location is found: $location")
curLat = location.latitude
curLong = location.longitude
}
.addOnFailureListener { exception ->
Log.e("Location", "Oops location failed with exception: $exception")
}
Unfortunately, location is still null
Upvotes: 0
Views: 1870
Reputation: 72
This worked for me
Mark user
private fun markUser(googleMap: GoogleMap) {
if(!checkLocationPermission()){
requestLocationPermission()
}
if (ActivityCompat.checkSelfPermission(
requireContext(),
Manifest.permission.ACCESS_FINE_LOCATION
) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(
requireContext(),
Manifest.permission.ACCESS_COARSE_LOCATION
) != PackageManager.PERMISSION_GRANTED
) {
fusedLocationClient.lastLocation
.addOnSuccessListener { location: Location? ->
if (location != null) {
val latitude = location.latitude
val longitude = location.longitude
val userIcon =
BitmapDescriptorFactory.fromResource(android.R.drawable.btn_star_big_on)
val userLocation = LatLng(latitude, longitude)
googleMap.addMarker(
MarkerOptions()
.position(userLocation)
.title("You")
.icon(userIcon)
)
}
}
}
}
Permission
private fun checkLocationPermission(): Boolean {
val permission = Manifest.permission.ACCESS_FINE_LOCATION
return ContextCompat.checkSelfPermission(
requireContext(),
permission
) == PackageManager.PERMISSION_GRANTED
}
private fun requestLocationPermission() {
val permission = Manifest.permission.ACCESS_FINE_LOCATION
ActivityCompat.requestPermissions(requireActivity(), arrayOf(permission), REQUEST_LOCATION_PERMISSION)
}
@Deprecated("Deprecated in Java")
override fun onRequestPermissionsResult(
requestCode: Int,
permissions: Array<out String>,
grantResults: IntArray
) {
when (requestCode) {
REQUEST_LOCATION_PERMISSION -> {
if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
shareCurrentLocation()
}
}
}
}
When testing in Android Studio, default locations may be marked on your machine. Therefore, ensure to conduct tests on a mobile device.
Upvotes: 0
Reputation: 1554
you need to request location updates try the following for instance
val fusedLocationProviderClient =
LocationServices.getFusedLocationProviderClient(activity)
val locationCallback = object : LocationCallback() {
override fun onLocationResult(locationResult: LocationResult) {
val location = locationResult.lastLocation
if (location != null) {
val latitude = location.latitude
val longitude = location.longitude
// Use latitude and longitude for your purposes
Log.d("Location", "Latitude: $latitude, Longitude: $longitude")
// Remove location updates after receiving one
fusedLocationProviderClient.removeLocationUpdates(this)
} else {
Log.w("Location", "Failed to get location update")
}
}
}
if (ContextCompat.checkSelfPermission(
activity,
Manifest.permission.ACCESS_FINE_LOCATION
) != PackageManager.PERMISSION_GRANTED
) {
// Request permissions if not granted
val permissions = arrayOf(Manifest.permission.ACCESS_FINE_LOCATION)
activity.requestPermissions(permissions, LOCATION_PERMISSION_CODE)
return
}
val locationRequest =
LocationRequest.Builder(0L).setPriority(Priority.PRIORITY_HIGH_ACCURACY).build()
fusedLocationProviderClient.requestLocationUpdates(locationRequest, locationCallback, null)
Upvotes: 0
Reputation: 644
So here's how you can get your current location. I am skipping the permission part as you can do that yourself.
private fun isLocationEnabled(): Boolean {
val locationManager: LocationManager =
getSystemService(Context.LOCATION_SERVICE) as LocationManager
return locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER) || locationManager.isProviderEnabled(
LocationManager.NETWORK_PROVIDER
)
}
private fun getLastLocation() {
if (isLocationEnabled()) {
fusedLocationClient.lastLocation.addOnCompleteListener(this) { task ->
val location: Location? = task.result
if (location != null) {
//use the location latitude and logitude as per your use.
val latitude = location.latitude
val longitude = location.longitude
}
}
}
Upvotes: 1