Move marker instead of adding it after requestLocationUpdates in kotlin - android

I'm using google map in kotlin with help of this tutorial Introduction to Google Maps API for Android with Kotlin. in this tutorial showed how can add a marker after location updated but when it updated,there is still a marker in previous location and added again and again. there is no object of Marker in this code and i want remain first added marker and then move it. how can i do this? Thanks
class MapsActivity : AppCompatActivity(), OnMapReadyCallback,
GoogleMap.OnMarkerClickListener {
private lateinit var map: GoogleMap
private lateinit var fusedLocationClient: FusedLocationProviderClient
private lateinit var lastLocation: Location
private lateinit var locationCallback: LocationCallback
private lateinit var locationRequest: LocationRequest
private var locationUpdateState = false
companion object {
private const val LOCATION_PERMISSION_REQUEST_CODE = 1
private const val REQUEST_CHECK_SETTINGS = 2
private const val PLACE_PICKER_REQUEST = 3
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_maps)
// Obtain the SupportMapFragment and get notified when the map is ready to be used.
val mapFragment = supportFragmentManager
.findFragmentById(R.id.map) as SupportMapFragment
mapFragment.getMapAsync(this)
fusedLocationClient = LocationServices.getFusedLocationProviderClient(this)
locationCallback = object : LocationCallback() {
override fun onLocationResult(p0: LocationResult) {
super.onLocationResult(p0)
lastLocation = p0.lastLocation
placeMarkerOnMap(LatLng(lastLocation.latitude, lastLocation.longitude))
}
}
createLocationRequest()
val fab = findViewById<FloatingActionButton>(R.id.fab)
fab.setOnClickListener {
loadPlacePicker()
}
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent) {
super.onActivityResult(requestCode, resultCode, data)
if (requestCode == REQUEST_CHECK_SETTINGS) {
if (resultCode == Activity.RESULT_OK) {
locationUpdateState = true
startLocationUpdates()
}
}
if (requestCode == PLACE_PICKER_REQUEST) {
if (resultCode == RESULT_OK) {
val place = PlacePicker.getPlace(this, data)
var addressText = place.name.toString()
addressText += "\n" + place.address.toString()
placeMarkerOnMap(place.latLng)
}
}
}
override fun onPause() {
super.onPause()
fusedLocationClient.removeLocationUpdates(locationCallback)
}
public override fun onResume() {
super.onResume()
if (!locationUpdateState) {
startLocationUpdates()
}
}
override fun onMapReady(googleMap: GoogleMap) {
map = googleMap
map.uiSettings.isZoomControlsEnabled = true
map.setOnMarkerClickListener(this)
setUpMap()
}
override fun onMarkerClick(p0: Marker?) = true
private fun setUpMap() {
if (ActivityCompat.checkSelfPermission(this,
android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this,
arrayOf(android.Manifest.permission.ACCESS_FINE_LOCATION), LOCATION_PERMISSION_REQUEST_CODE)
return
}
map.isMyLocationEnabled = true
map.mapType = GoogleMap.MAP_TYPE_NORMAL
fusedLocationClient.lastLocation.addOnSuccessListener(this) { location ->
// Got last known location. In some rare situations this can be null.
if (location != null) {
lastLocation = location
val currentLatLng = LatLng(location.latitude, location.longitude)
placeMarkerOnMap(currentLatLng)
map.animateCamera(CameraUpdateFactory.newLatLngZoom(currentLatLng, 12f))
}
}
}
private fun placeMarkerOnMap(location: LatLng) {
val markerOptions = MarkerOptions().position(location)
val titleStr = getAddress(location) // add these two lines
markerOptions.title(titleStr)
map.addMarker(markerOptions)
}
private fun startLocationUpdates() {
if (ActivityCompat.checkSelfPermission(this,
android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this,
arrayOf(android.Manifest.permission.ACCESS_FINE_LOCATION),
LOCATION_PERMISSION_REQUEST_CODE)
return
}
fusedLocationClient.requestLocationUpdates(locationRequest, locationCallback, null /* Looper */)
}
private fun createLocationRequest() {
locationRequest = LocationRequest()
locationRequest.interval = 10000
locationRequest.fastestInterval = 5000
locationRequest.priority = LocationRequest.PRIORITY_HIGH_ACCURACY
val builder = LocationSettingsRequest.Builder()
.addLocationRequest(locationRequest)
val client = LocationServices.getSettingsClient(this)
val task = client.checkLocationSettings(builder.build())
task.addOnSuccessListener {
locationUpdateState = true
startLocationUpdates()
}
task.addOnFailureListener { e ->
if (e is ResolvableApiException) {
// Location settings are not satisfied, but this can be fixed
// by showing the user a dialog.
try {
// Show the dialog by calling startResolutionForResult(),
// and check the result in onActivityResult().
e.startResolutionForResult(this#MapsActivity,
REQUEST_CHECK_SETTINGS)
} catch (sendEx: IntentSender.SendIntentException) {
// Ignore the error.
}
}
}
}
private fun loadPlacePicker() {
val builder = PlacePicker.IntentBuilder()
try {
startActivityForResult(builder.build(this#MapsActivity), PLACE_PICKER_REQUEST)
} catch (e: GooglePlayServicesRepairableException) {
e.printStackTrace()
} catch (e: GooglePlayServicesNotAvailableException) {
e.printStackTrace()
}
}
}

The addMarker() method of GoogleMap returns a Marker.
You need to keep a reference to the returned marker and later update it's position using the setPosition method.

#LordRaydenMK's answer is correct. I spent a week trying to work this out and found finally got it. That raywenderlich tutorial you referenced is good, except they incorrectly coded the placeMarkerOnMap() function.
First, set a variable for your location marker above onCreate:
private var userLocationMarker: Marker? = null
Then replace your placeMarkerOnMap() function with this code and it should work fine:
private fun placeMarkerOnMap(location: Location) {
val latLng = LatLng(location.latitude, location.longitude)
if (userLocationMarker == null) {
//Create a new marker
val markerOptions = MarkerOptions()
markerOptions.position(latLng)
markerOptions.icon(BitmapDescriptorFactory.fromResource(R.mipmap.ic_user_location))
markerOptions.rotation(location.bearing)
markerOptions.anchor(0.5.toFloat(), 0.5.toFloat())
userLocationMarker = map.addMarker(markerOptions)
map.animateCamera(CameraUpdateFactory.newLatLngZoom(latLng, 20f))
} else {
//use the previously created marker
userLocationMarker!!.position = latLng
userLocationMarker!!.rotation = location.bearing
map.animateCamera(CameraUpdateFactory.newLatLngZoom(latLng, 20f))
}
}
If you want to get rid of the blue dot make sure to set isMyLocationEnabled to false.

Related

FusedLocation not trigger locationcallback for android api <= 21

so I want to get the latitude and longitude from the device, but when I build my application on android Lollipop or API 22 I'm not getting the current latitude and longitude. is this because of android permission or what? here is my code
I'm using play service location version:
implementation 'com.google.android.gms:play-services-location:17.0.0'
LocationUser.kt
class LocationUser(context: Context) {
private var fusedLocation: FusedLocationProviderClient? = null
private val INTERVAL: Long = 300000
private val FASTEST_INTERVAL: Long = 300000
private val REQUEST_LOCATION_PERMISSION = 1
lateinit var locationRequest: LocationRequest
private lateinit var lastLocation: Location
fun startLocationUpdates(context: Context) {
Log.d("LOCATION UPDATE", "started location update")
locationRequest = LocationRequest()
locationRequest.priority = LocationRequest.PRIORITY_HIGH_ACCURACY
locationRequest.interval = INTERVAL
locationRequest.fastestInterval = FASTEST_INTERVAL
val builder = LocationSettingsRequest.Builder()
builder.addLocationRequest(locationRequest)
val locationSettingsRequest = builder.build()
val settingsClient = LocationServices.getSettingsClient(context)
settingsClient.checkLocationSettings(locationSettingsRequest)
fusedLocation = LocationServices.getFusedLocationProviderClient(context)
if (ActivityCompat.checkSelfPermission(
context,
android.Manifest.permission.ACCESS_FINE_LOCATION
) != PackageManager.PERMISSION_GRANTED &&
ActivityCompat.checkSelfPermission(
context,
android.Manifest.permission.ACCESS_COARSE_LOCATION
) != PackageManager.PERMISSION_GRANTED
) {
return
}
fusedLocation!!.requestLocationUpdates(locationRequest, locationCallback, Looper.myLooper())
Log.d("LOCATION UPDATE", "end location update")
}
fun isPermissionGranted(context: Context): Boolean {
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (context.checkSelfPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) ==
PackageManager.PERMISSION_GRANTED
) {
true
} else {
ActivityCompat.requestPermissions(
context as Activity, arrayOf(android.Manifest.permission.ACCESS_FINE_LOCATION),
REQUEST_LOCATION_PERMISSION
)
false
}
} else {
true
}
}
private val locationCallback = object : LocationCallback() {
override fun onLocationResult(locationResult: LocationResult) {
locationResult.lastLocation
onLocationChanged(context, locationResult.lastLocation)
super.onLocationResult(locationResult)
}
}
fun onLocationChanged(context: Context, location: Location) {
Log.d("UWUWU", "location changed")
lastLocation = location
val geocoder = Geocoder(context, Locale.getDefault())
val latitude = lastLocation.latitude
val longitude = lastLocation.longitude
val sharedPref = SharedPref(context)
Log.d("latitude", latitude.toString())
Log.d("longitude", longitude.toString())
sharedPref.saveStringPref("latitude_user", latitude.toString())
sharedPref.saveStringPref("longitude_user", longitude.toString())
try {
val addresses: List<Address> = geocoder.getFromLocation(latitude, longitude, 1)
val namaKota = addresses[0].subAdminArea
val namaKecamatan = addresses[0].locality
sharedPref.saveStringPref("alamat_user", "$namaKecamatan, $namaKota")
} catch (e: Exception) {
e.localizedMessage
}
Log.d("UWUWU", "location changed")
}
}
and in the activity I called the class like this
MainActivity.kt
class MainActivity : AppCompatActivity() {
private val REQUEST_LOCATION_PERMISSION = 1
private val REQUESTING_LOCATION_UPDATES_KEY = "requesting_location_update"
private val requestingLocationUpdates = true
val locationUser = LocationUser(this)
#SuppressLint("SimpleDateFormat", "SetTextI18n")
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
../
val locationManager = getSystemService(Context.LOCATION_SERVICE) as LocationManager
if (!locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)) {
checkUserGPS()
}
if(locationUser.isPermissionGranted(this)){
locationUser.startLocationUpdates(this)
}
Log.d("GRANTED ?", locationUser.isPermissionGranted(this).toString())
}
override fun onCreateOptionsMenu(menu: Menu?): Boolean {
menuInflater.inflate(R.menu.menu_setting, menu)
return true
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
if (item.itemId == R.id.menu_settings) {
val intent = Intent(this, SettingsActivity::class.java)
startActivity(intent)
return true
}
return super.onOptionsItemSelected(item)
}
override fun onRequestPermissionsResult(
requestCode: Int,
permissions: Array<out String>,
grantResults: IntArray
) {
if (requestCode == REQUEST_LOCATION_PERMISSION) {
if (grantResults.contains(PackageManager.PERMISSION_GRANTED)) {
Toast.makeText(this, "permission granted", Toast.LENGTH_SHORT).show()
}
}
}
private fun checkUserGPS() {
val dialog = AlertDialog.Builder(this)
dialog.setMessage("GPS tidak aktif, apakah kamu ingin megaktifkannya?")
.setCancelable(false)
.setPositiveButton("iya") { _, which ->
startActivityForResult(Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS), 11)
}
.setNegativeButton("tidak") { dialog, _ ->
dialog.cancel()
finish()
}
.create()
.show()
}
override fun onResume() {
locationUser.startLocationUpdates(this)
super.onResume()
}
}
when I see log I noticed that the function of onLocationChange not called when function startLocationUpdates function is called. is this because of permission or what, I'm suffering StackOverflow and get this question which is vice versa with my problem, and I noticed the same thing which is locationcallback is not triggered
FusedLocationProviderClient requestLocationUpdates doesn't trigger LocationCallBack for API 23 above
I'm confused right now
The fused Location Provider will only maintain background location if at least one client is connected to it. Now just turning on the location service will not guarantee to store the last known location.
Once the first client connects, it will immediately try to get a location. If your activity is the first client to connect and getLastLocation() is invoked right away in onConnected(), that might not be enough time for the first location to arrive..
I suggest you to launch the Maps app first, so that there is at least some confirmed location, and then test your app.

requestLocationUpdates doesn't call the locationCallback

I started to make a Kotlin app and i'm trying to access the users location. It's all my app must do. However, the function "client.requestLocationUpdates(locationRequest, locationCallback, null)" never calls my locationCallback method and I don't know why. I already debug this code, it execute the "client.requestLocationUpdates(locationRequest, locationCallback, null)" line but it never execute my LocationCallbackFunction. Here's my code:
class MainActivity : AppCompatActivity() {
private lateinit var client : FusedLocationProviderClient
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
client = LocationServices.getFusedLocationProviderClient(this)
}
override fun onResume() {
super.onResume()
var codigo = GoogleApiAvailability.getInstance().isGooglePlayServicesAvailable(this);
codigo = 0
when (codigo) {
ConnectionResult.SERVICE_MISSING,
ConnectionResult.SERVICE_VERSION_UPDATE_REQUIRED,
ConnectionResult.SERVICE_DISABLED -> {
GoogleApiAvailability.getInstance().getErrorDialog(this, codigo, 0, DialogInterface.OnCancelListener {
fun onCancel(dialog: DialogInterface?) {
finish();
}
}).show()
}
ConnectionResult.SUCCESS -> {
println("Google Play Service is working!")
}
}
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
println("This app hasn't permission to access users location")
return;
}
val locationRequest = LocationRequest.create()
val fifteen = 15 * 1000.toLong()
val five = 5 * 1000.toLong()
locationRequest.interval = fifteen
locationRequest.fastestInterval = five
locationRequest.priority = LocationRequest.PRIORITY_HIGH_ACCURACY
var builder = LocationSettingsRequest.Builder().addLocationRequest(locationRequest)
var settingsClient = LocationServices.getSettingsClient(this)
settingsClient.checkLocationSettings(builder.build())
.addOnSuccessListener(
fun (locationSettingsResponse : LocationSettingsResponse) {
println("locationSettingsResponse.locationSettingsStates.isGpsPresent = ${locationSettingsResponse.locationSettingsStates.isGpsPresent}")
println("locationSettingsResponse.locationSettingsStates.isGpsUsable = ${locationSettingsResponse.locationSettingsStates.isGpsUsable}")
}
)
.addOnFailureListener(
fun (e: Exception) : Unit {
if (e is ResolvableApiException) {
try {
var resolvable : ResolvableApiException = e
resolvable.startResolutionForResult(this, 10);
} catch (e1 : IntentSender.SendIntentException ) {
}
}
}
)
val locationCallback : LocationCallback? = object : LocationCallback() {
override fun onLocationResult(locationResult : LocationResult?) {
if (locationResult == null) {
println("the value is null")
return;
}
for ( location : Location in locationResult.getLocations()) {
location.getLatitude()
println("latitude=" + location.getLatitude());
textoPrincipal.text = location.getLatitude().toString()
}
}
}
client.requestLocationUpdates(locationRequest, locationCallback, null)
}
}
That is the entire content of my activity
I solved this, and I don't know how, this exactly code is running perfectly right now. It was a error in my Android Studio configuration, I guess

User location not showing on Button Click

I want to get the user location on button click. But it does not provide me location. I want to get user location by using android gps not with google play services
class NewPostActivity : AppCompatActivity(), LocationListener {
private val locationMangaer: LocationManager?
get() {
return getSystemService(Context.LOCATION_SERVICE) as LocationManager
}
override fun onCreate(savedInstanceState: Bundle?) {
getLocationbtn.setOnClickListener {
locationMangaer!!.requestLocationUpdates(LocationManager.GPS_PROVIDER, 5000, 10.toFloat(), this)
}
}
override fun onLocationChanged(location: Location?) {
Log.e("data", "called")
Log.e("data", "Location is ${location!!.latitude} and ${location.latitude}")
}
}
it is all of get current location code
class MainActivity : AppCompatActivity() {
val PERMISSION_ID = 42
lateinit var mFusedLocationClient: FusedLocationProviderClient
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
mFusedLocationClient = LocationServices.getFusedLocationProviderClient(this)
getLastLocation()
}
#SuppressLint("MissingPermission")
private fun getLastLocation() {
if (checkPermissions()) {
if (isLocationEnabled()) {
mFusedLocationClient.lastLocation.addOnCompleteListener(this) { task ->
var location: Location? = task.result
if (location == null) {
requestNewLocationData()
} else {
findViewById<TextView>(R.id.latTextView).text = location.latitude.toString()
findViewById<TextView>(R.id.lonTextView).text = location.longitude.toString()
}
}
} else {
Toast.makeText(this, "Turn on location", Toast.LENGTH_LONG).show()
val intent = Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS)
startActivity(intent)
}
} else {
requestPermissions()
}
}
#SuppressLint("MissingPermission")
private fun requestNewLocationData() {
var mLocationRequest = LocationRequest()
mLocationRequest.priority = LocationRequest.PRIORITY_HIGH_ACCURACY
mLocationRequest.interval = 0
mLocationRequest.fastestInterval = 0
mLocationRequest.numUpdates = 1
mFusedLocationClient = LocationServices.getFusedLocationProviderClient(this)
mFusedLocationClient!!.requestLocationUpdates(
mLocationRequest, mLocationCallback,
Looper.myLooper()
)
}
private val mLocationCallback = object : LocationCallback() {
override fun onLocationResult(locationResult: LocationResult) {
var mLastLocation: Location = locationResult.lastLocation
findViewById<TextView>(R.id.latTextView).text = mLastLocation.latitude.toString()
findViewById<TextView>(R.id.lonTextView).text = mLastLocation.longitude.toString()
}
}
private fun isLocationEnabled(): Boolean {
var locationManager: LocationManager = getSystemService(Context.LOCATION_SERVICE) as LocationManager
return locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER) || locationManager.isProviderEnabled(
LocationManager.NETWORK_PROVIDER
)
}
private fun checkPermissions(): Boolean {
if (ActivityCompat.checkSelfPermission(
this,
Manifest.permission.ACCESS_COARSE_LOCATION
) == PackageManager.PERMISSION_GRANTED &&
ActivityCompat.checkSelfPermission(
this,
Manifest.permission.ACCESS_FINE_LOCATION
) == PackageManager.PERMISSION_GRANTED
) {
return true
}
return false
}
private fun requestPermissions() {
ActivityCompat.requestPermissions(
this,
arrayOf(Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION),
PERMISSION_ID
)
}
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<String>, grantResults: IntArray) {
if (requestCode == PERMISSION_ID) {
if ((grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED)) {
getLastLocation()
}
}
}
}
you have to add this to your ``` manifest.xml``
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
and this to your gradle
implementation 'com.google.android.gms:play-services-location:17.0.0'
I hope it will help you . happy code

How to get coordinate from fixed marker at center of google maps in android

In my application I'm trying to get coordinate from fixed marker at center of google maps. When i scroll map, i want to get coordinate and set it on the text view.
Here is my Kotlin code:
class ActivityMapsDSPBng : AppCompatActivity(), OnMapReadyCallback, GoogleMap.OnMarkerClickListener, GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener,
com.google.android.gms.location.LocationListener {
...
private val TAG = "ActivityMapsDSPBng"
private lateinit var mGoogleApiClient: GoogleApiClient
private var mLocationManager: LocationManager? = null
lateinit var mLocation: Location
private var mLocationRequest: LocationRequest? = null
private val listener: com.google.android.gms.location.LocationListener? = null
private val UPDATE_INTERVAL = (2 * 1000).toLong()
private val FASTEST_INTERVAL: Long = 2000
lateinit var locationManager: LocationManager
override fun onStart() {
...
}
override fun onStop() {
...
}
override fun onConnectionSuspended(p0: Int) {
...
}
override fun onConnectionFailed(connectionResult: ConnectionResult) {
Log.i(TAG, "Connection failed. Error: " + connectionResult.errorCode)
}
override fun onLocationChanged(location: Location) {
var msg = "Update Location: Latitude " + location.latitude.toString() + " Longitude " + location.longitude.toString()
tv_dspbg_lat.setText("" + location.latitude)
tv_dspbg_long.setText("" + location.longitude)
Toast.makeText(this, msg, Toast.LENGTH_SHORT).show()
}
override fun onConnected(p0: Bundle?) {
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
return
}
startLocationUpdates()
var fusedLocationProviderClient: FusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(this)
fusedLocationProviderClient.lastLocation
.addOnSuccessListener(this, OnSuccessListener<Location> { location ->
if (location != null){
mLocation = location
tv_dspbg_lat.setText("" + mLocation.latitude)
tv_dspbg_long.setText("" + mLocation.longitude)
}
})
}
protected fun startLocationUpdates(){
// Create location request
mLocationRequest = LocationRequest.create()
.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY)
.setInterval(UPDATE_INTERVAL)
.setFastestInterval(FASTEST_INTERVAL)
// Request location updates
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED){
return
}
LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this)
}
override fun onCreate(savedInstanceState: Bundle?) {
...
val mapsDSPBNGfragment = supportFragmentManager
.findFragmentById(R.id.maps_dspbg) as SupportMapFragment
mapsDSPBNGfragment.getMapAsync(this)
fusedLPCBg = LocationServices.getFusedLocationProviderClient(this)
mGoogleApiClient = GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build()
mLocationManager = this.getSystemService(Context.LOCATION_SERVICE) as LocationManager
checkLocation()
}
private fun checkLocation(): Boolean{
...
}
private fun isLocationEnabled(): Boolean{
...
}
private fun showAlert(){
val dialog = AlertDialog.Builder(this)
dialog.setTitle("Enable Location")
.setMessage("Your location setting is set to 'Off'. \nPlease enable location to " + "use this app")
.setPositiveButton("Location Settings", DialogInterface.OnClickListener { paramDialogInterface, paramInt ->
val myIntent = Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS)
startActivity(myIntent)
})
.setNegativeButton("Cancel", DialogInterface.OnClickListener { paramDialogInterface, paramInt -> })
dialog.show()
}
}
I build code from https://androidteachers.com/kotlin-for-android/get-location-in-android-with-kotlin/
When I scrool maps, coordinates do not change according to the fixed maker.
Check my Java code. The fixed marker you are talking about is like an overlay View from your layout code. But if it's right at the center of the map, you can use the center of the camera:
mGoogleMap.setOnCameraIdleListener(new OnCameraIdleListener() {
#Override
public void onCameraIdle() {
// Get the center coordinate of the map, if the overlay view is center too
CameraPosition cameraPosition = mGoogleMap.getCameraPosition();
LatLng currentCenter = cameraPosition.target;
// Or get any coordinate if overlay view is not at the centered
// int[] location = new int[2];
// mOverlayView.getLocationInWindow(location);
// Point viewPosition = new Point(location[0], location[1]);
// LatLng currentCenter = mGoogleMap.getProjection().fromScreenLocation(viewPosition);
}
}
To get the center location of google map
LatLng centerLatLang = mMap.getProjection().getVisibleRegion().latLngBounds.getCenter();

Location is null unless GoogleMap is initialized again

What I'm trying to achieve is to display the user's last know location. If the GPS is disabled, request the location setting. When user presses OK, then enables the GPS and moves the map camera to the location found.
It works as expected when the GPS is already enabled; however, when it isn't, the map camera just doesn't make a move because the location is null.
I can make this work if I add initMap() after the else statement (when location == null) inside the displayLocation() function, but something doesn't feel right about this solution.
Could someone please explain what's going on in here? I greatly appreciate it!
By the way, I'm using MVP architecture, so when the Activity starts, the first function that is called is requestPermission()
class MainActivity : AppCompatActivity(), MainView, OnMapReadyCallback {
private val ZOOM_LEVEL = 12
private val ZOOM_DURATION = 2000
private val PERMISSION_REQUEST_CODE = 101
private val SETTINGS_REQUEST_CODE = 102
private val RC_SIGN_IN = 123
private lateinit var mMainPresent: MainPresenterImpl
private lateinit var mGoogleMap: GoogleMap
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
mMainPresent = MainPresenterImpl(this)
mMainPresent.onCreate()
}
override fun onResume() {
super.onResume()
mMainPresent.onResume()
}
override fun onPause() {
super.onPause()
mMainPresent.onPause()
}
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
when (requestCode) {
PERMISSION_REQUEST_CODE -> {
if (grantResults.isEmpty() || grantResults[0] == PackageManager.PERMISSION_DENIED) {
finish()
} else {
initMap()
}
}
}
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
when (requestCode) {
SETTINGS_REQUEST_CODE -> {
if (resultCode == Activity.RESULT_OK) {
initMap()
}
}
}
}
override fun onMapReady(googleMap: GoogleMap) {
mGoogleMap = googleMap
displayLocation()
}
override fun displayLoginMethods() {
startActivityForResult(
AuthUI.getInstance()
.createSignInIntentBuilder()
.setIsSmartLockEnabled(!BuildConfig.DEBUG) // disables it for debug
.setAvailableProviders(
Arrays.asList<AuthUI.IdpConfig>(AuthUI.IdpConfig.Builder(AuthUI.FACEBOOK_PROVIDER).build(),
AuthUI.IdpConfig.Builder(AuthUI.PHONE_VERIFICATION_PROVIDER).build()))
.build(),
RC_SIGN_IN)
}
override fun requestPermission() {
if (ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
requestPermissions(arrayOf(Manifest.permission.ACCESS_FINE_LOCATION), PERMISSION_REQUEST_CODE)
}
} else {
requestLocationSettings()
}
}
override fun displayLocation() {
val mFusedLocationClient: FusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(this)
try {
mGoogleMap.isMyLocationEnabled = true
mGoogleMap.uiSettings.isMyLocationButtonEnabled = true
mFusedLocationClient.lastLocation
.addOnSuccessListener(this) { location ->
// Got last known location. In some rare situations this can be null.
if (location != null) {
// Logic to handle location object
val latitude = location.latitude
val longitude = location.longitude
val coordinate = LatLng(latitude, longitude)
mGoogleMap.addMarker(MarkerOptions().position(coordinate))
mGoogleMap.moveCamera(CameraUpdateFactory.newLatLng(coordinate))
mGoogleMap.animateCamera(CameraUpdateFactory.zoomTo(ZOOM_LEVEL.toFloat()), ZOOM_DURATION, null)
} else {
Log.d("displayLocation", "location = null")
}
}
} catch (e: SecurityException) {
Log.e("Exception: %s", e.message)
}
}
/**
* Initiates Google Map. Once it's ready it calls the onMapReady method
*/
override fun initMap() {
val mapFragment = supportFragmentManager.findFragmentById(R.id.map) as SupportMapFragment
mapFragment.getMapAsync(this)
}
private fun createLocationRequest(): LocationRequest {
val locationRequest = LocationRequest()
locationRequest.interval = 10000
locationRequest.fastestInterval = 5000
locationRequest.priority = LocationRequest.PRIORITY_HIGH_ACCURACY
return locationRequest
}
private fun requestLocationSettings() {
val builder = LocationSettingsRequest.Builder().addLocationRequest(createLocationRequest())
val client = LocationServices.getSettingsClient(this)
val task = client.checkLocationSettings(builder.build())
task.addOnSuccessListener(this) {
// All location settings are satisfied. The client can initialize
// location requests here.
// ...
initMap()
}
task.addOnFailureListener(this) { e ->
if (e is ResolvableApiException) {
// Location settings are not satisfied, but this can be fixed
// by showing the user a dialog.
try {
// Show the dialog by calling startResolutionForResult(),
// and check the result in onActivityResult().
e.startResolutionForResult(this#MainActivity, SETTINGS_REQUEST_CODE)
} catch (sendEx: IntentSender.SendIntentException) {
// Ignore the error.
}
}
}
}
}
You can make use of the following callbacks when status changed,
private final LocationListener locationListener = new LocationListener() {
#Override
public void onStatusChanged(String provider, int status, Bundle extras) {
// TODO Auto-generated method stub
}
#Override
public void onProviderEnabled(String provider) {
// TODO Auto-generated method stub
}
#Override
public void onProviderDisabled(String provider) {
updateWithNewLocation(null);
}
#Override
public void onLocationChanged(Location location) {
updateWithNewLocation(location);
}
};

Categories

Resources