Can’t navigate in google maps activity it always spawns back to my current location



I am new to android development and was working on an app which requires google map activity. Problem I am facing is that when I am trying to pan(or scroll) through the map I am immediately respawned to my current location which I set initially. A little help would be wonderful as I am stuck at this point and unable to find a solution. Here is the code:-

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    binding = ActivityMapsBinding.inflate(getLayoutInflater());
    setContentView(binding.getRoot());

    // Obtain the SupportMapFragment and get notified when the map is ready to be used.
    SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
            .findFragmentById(R.id.map);
    mapFragment.getMapAsync(this);
}



@Override
public void onMapReady(GoogleMap googleMap) {
    mMap = googleMap;
    mMap.getUiSettings().setScrollGesturesEnabled(true);
    locationManager=(LocationManager)this.getSystemService(Context.LOCATION_SERVICE);
    locationListener=new LocationListener() {
        @Override
        public void onLocationChanged(@NonNull Location location) {
            centerOnMap(location,"Your Location");
        }
    };

    if(ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)!= PackageManager.PERMISSION_GRANTED)
    {
        ActivityCompat.requestPermissions(this,new String[]{Manifest.permission.ACCESS_FINE_LOCATION},1);
    }
    else{
        locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER,0,0,locationListener);
        Location lastKnownLocation=locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
        centerOnMap(lastKnownLocation,"Your Location");
    }
}

public void centerOnMap(Location location,String address)
{
    LatLng userLocation = new LatLng(location.getLatitude(),location.getLongitude());
    mMap.addMarker(new MarkerOptions().position(userLocation).title(address));
    mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(userLocation, 15));
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull @org.jetbrains.annotations.NotNull String[] permissions, @NonNull @org.jetbrains.annotations.NotNull int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    if(grantResults.length>0 && grantResults[0]==PackageManager.PERMISSION_GRANTED)
    {
        if(ContextCompat.checkSelfPermission(this,Manifest.permission.ACCESS_FINE_LOCATION)==PackageManager.PERMISSION_GRANTED){
            locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER,0,0,locationListener);
        }

    }
}

}

Answer

The one requirement that you likely have but not stated is:

When the lastLocation becomes available and the user has not moved the map then center the map on the location. If the user has already moved the map then do not center the map. In either case, add a marker at the user’s location.

Before getting too far along it must be noted that Google Maps provides a feature similar to what you are trying to achieve, though you’d still have to “move camera”. The marker is a blue-ball and not the typical marker. See myMap.setMyLocationEnabled(true). That’s it! Do this when you have gotten map permissions.

But in the event you don’t want to use that then here are the simple changes you need.

Remember that the LocationManager getLastKnownLocation can return null if the device does not have one (yet). So I’d recommend one small change a bit unrelated – just let the location listener do all the work and get rid of this one special case:

// this is where you initially check permissions and have them.
else{
    locationManager.requestLocationUpdates (LocationManager.GPS_PROVIDER,0,0,locationListener);
    // Here I removed the last location centering and let the
    // location listener always handle it.
}

So this opens the possibility that the user could be interacting with map and finally the last location arrives. I understand this to be the issue you are trying to address.

(As an aside, it seems to me you are mixing the use of the android.location.LocationManager with the FusedLocationProviderApi (com.google.android.gms.location) so I couldn’t get your code to compile due to incompatible LocationListeners. Unfortunately, Google Maps has two LocationListener classes so to be certain you’d have to include your imports to understand further.)

Anyways…

When the map is first ready (onMapReady) the camera of the map is centered at (0,0). You can get the cameras target position (center) at any time using LatLng tgtCtr = mMap.getCameraPosition().target;.

Oddly enough it is not straightforward to know whether the user has interacted with the map in any way: scrolling events generate camera changes while touch events generate a separate event. Camera changes cannot be used exclusively because your code or the user could just zoom which is not moving the map. You could go this route but for the purposes of this answer, to keep things simple, the camera target is used.

Declare a class instance variable (same area where you define mMap):

LatLng tgtCtr;

So in your onMapReady after assigning mMap do:

tgtCtr = mMap.getCameraPosition().target;

So assume your code exists as you posted (it’s pretty close) then these changes may help:

// This change simply restricts centering of the map on location
// update to only when user has not moved the map (scrolled).

@Override
public void onLocationChanged(@NonNull Location location) {
    LatLng currentCtr = mMap.getCamaraPosition().target;
    
    // This is not the ideal check since `double` comparisons 
    // should account for epsilon but in this case of (0,0) it should work.
    
    // Alternatively you could compute the distance of current
    // center to (0,0) and then use an epsilon: 
    //    see `com.google.maps.android.SphericalUtil.computeDistanceBetween`.
    
    if (currentCtr.latitude == 0 && currentCtr.longitude == 0) {
        centerOnMap(location,"Your Location");
    }
}

It also seems like a good idea to save the marker which was added for user’s location – this is optional but may come in handy to prevent multiple markers from being added at that one location:

// Define a class instance variable
Marker myLocMarker = nulll;

// and then in centerOnMap
public void centerOnMap(Location location, String address)
{
    // ... other code

    if (myLocMarker == null) {
        myLocMarker = mMap.addMarker(new MarkerOptions().position(userLocation).title(address));
    }

    // ... more code
}

So really the only difficulty in this is figuring out “has the user moved the map.” In this case, based on the initial requirement you would not want to move the map.



Source: stackoverflow