How to continuously move marker same as google default current location marker on google map android

20,198

Solution 1

You just need to remove the call to removeLocationUpdates() in onLocationChanged():

@Override
public void onLocationChanged(Location location)
{
    mLastLocation = location;
    if (mCurrLocationMarker != null)
    {
        mCurrLocationMarker.remove();
    }

    //Place current location marker
    LatLng latLng = new LatLng(location.getLatitude(), location.getLongitude());
    MarkerOptions markerOptions = new MarkerOptions();
    markerOptions.position(latLng);
    markerOptions.title("Current Position");
    markerOptions.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_ORANGE));
    mCurrLocationMarker = mGoogleMap.addMarker(markerOptions);

    //move map camera
    mGoogleMap.moveCamera(CameraUpdateFactory.newLatLng(latLng));
    mGoogleMap.animateCamera(CameraUpdateFactory.zoomTo(11));

    //Remove this code:
    //if (mGoogleApiClient != null)
    //{
      //LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, this);
    //}
}

Also add an onResume() Override and re-register for location updates if the Google API Client is not null:

@Override
public void onResume() {
    super.onResume();
    if (mGoogleApiClient != null &&
            ContextCompat.checkSelfPermission(this,
            Manifest.permission.ACCESS_FINE_LOCATION)
            == PackageManager.PERMISSION_GRANTED) {
        LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);
    }
}

The original code was designed to only get one location, and then remove location updates after the first location comes in.

Bear in mind that keeping a location listener active for long periods will cause more battery drain.

Also note that for testing purposes, you can set more aggressive values in the location request:

@Override
public void onConnected(Bundle bundle)
{
    mLocationRequest = new LocationRequest();
    mLocationRequest.setInterval(1000);
    mLocationRequest.setFastestInterval(1000);
    mLocationRequest.setSmallestDisplacement(0.1F); //added
    mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY); //changed
    if (ContextCompat.checkSelfPermission(this,
            Manifest.permission.ACCESS_FINE_LOCATION)
            == PackageManager.PERMISSION_GRANTED)
    {

        LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);

    }
}

Making the above changes, this code works for me:

public class MapLocationActivity extends AppCompatActivity
        implements OnMapReadyCallback,
        GoogleApiClient.ConnectionCallbacks,
        GoogleApiClient.OnConnectionFailedListener,
        LocationListener {

    GoogleMap mGoogleMap;
    SupportMapFragment mapFrag;
    LocationRequest mLocationRequest;
    GoogleApiClient mGoogleApiClient;
    Location mLastLocation;
    Marker mCurrLocationMarker;

    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            checkLocationPermission();
        }

        mapFrag = (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map);
        mapFrag.getMapAsync(this);
    }

    @Override
    public void onPause() {
        super.onPause();

        //stop location updates when Activity is no longer active
        if (mGoogleApiClient != null) {
            LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, this);
        }
    }

    @Override
    public void onResume() {
        super.onResume();
        if (mGoogleApiClient != null &&
                ContextCompat.checkSelfPermission(this,
                Manifest.permission.ACCESS_FINE_LOCATION)
                == PackageManager.PERMISSION_GRANTED) {
            LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);
        }
    }

    @Override
    public void onMapReady(GoogleMap googleMap)
    {
        mGoogleMap=googleMap;
        mGoogleMap.setMapType(GoogleMap.MAP_TYPE_HYBRID);

        //Initialize Google Play Services
        if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            if (ContextCompat.checkSelfPermission(this,
                    Manifest.permission.ACCESS_FINE_LOCATION)
                    == PackageManager.PERMISSION_GRANTED) {
                buildGoogleApiClient();
                mGoogleMap.setMyLocationEnabled(true);
            }
        }
        else {
            buildGoogleApiClient();
            mGoogleMap.setMyLocationEnabled(true);
        }
    }

    protected synchronized void buildGoogleApiClient() {
        mGoogleApiClient = new GoogleApiClient.Builder(this)
                .addConnectionCallbacks(this)
                .addOnConnectionFailedListener(this)
                .addApi(LocationServices.API)
                .build();
        mGoogleApiClient.connect();
    }

    @Override
    public void onConnected(Bundle bundle) {
        mLocationRequest = new LocationRequest();
        mLocationRequest.setInterval(1000);
        mLocationRequest.setFastestInterval(1000);
        mLocationRequest.setSmallestDisplacement(0.1f);
        mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
        if (ContextCompat.checkSelfPermission(this,
                Manifest.permission.ACCESS_FINE_LOCATION)
                == PackageManager.PERMISSION_GRANTED) {
            LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);
        }
    }

    @Override
    public void onConnectionSuspended(int i) {}

    @Override
    public void onConnectionFailed(ConnectionResult connectionResult) {}

    @Override
    public void onLocationChanged(Location location)
    {
        Toast.makeText(this, "Location Changed " + location.getLatitude()
                + location.getLongitude(), Toast.LENGTH_LONG).show();

        mLastLocation = location;
        if (mCurrLocationMarker != null) {
            mCurrLocationMarker.remove();
        }

        //Place current location marker
        LatLng latLng = new LatLng(location.getLatitude(), location.getLongitude());
        MarkerOptions markerOptions = new MarkerOptions();
        markerOptions.position(latLng);
        markerOptions.title("Current Position");
        markerOptions.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_MAGENTA));
        mCurrLocationMarker = mGoogleMap.addMarker(markerOptions);

        //move map camera
        mGoogleMap.moveCamera(CameraUpdateFactory.newLatLng(latLng));
        mGoogleMap.animateCamera(CameraUpdateFactory.zoomTo(11));


    }

    public static final int MY_PERMISSIONS_REQUEST_LOCATION = 99;
    public boolean checkLocationPermission(){
        if (ContextCompat.checkSelfPermission(this,
                Manifest.permission.ACCESS_FINE_LOCATION)
                != PackageManager.PERMISSION_GRANTED) {

            // Should we show an explanation?
            if (ActivityCompat.shouldShowRequestPermissionRationale(this,
                    Manifest.permission.ACCESS_FINE_LOCATION)) {

                // Show an expanation to the user *asynchronously* -- don't block
                // this thread waiting for the user's response! After the user
                // sees the explanation, try again to request the permission.

                //Prompt the user once explanation has been shown
                ActivityCompat.requestPermissions(this,
                        new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
                        MY_PERMISSIONS_REQUEST_LOCATION);


            } else {
                // No explanation needed, we can request the permission.
                ActivityCompat.requestPermissions(this,
                        new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
                        MY_PERMISSIONS_REQUEST_LOCATION);
            }
            return false;
        } else {
            return true;
        }
    }

    @Override
    public void onRequestPermissionsResult(int requestCode,
                                           String permissions[], int[] grantResults) {
        switch (requestCode) {
            case MY_PERMISSIONS_REQUEST_LOCATION: {
                // If request is cancelled, the result arrays are empty.
                if (grantResults.length > 0
                        && grantResults[0] == PackageManager.PERMISSION_GRANTED) {

                    // permission was granted, yay! Do the
                    // contacts-related task you need to do.
                    if (ContextCompat.checkSelfPermission(this,
                            Manifest.permission.ACCESS_FINE_LOCATION)
                            == PackageManager.PERMISSION_GRANTED) {

                        if (mGoogleApiClient == null) {
                            buildGoogleApiClient();
                        }
                        mGoogleMap.setMyLocationEnabled(true);
                    }

                } else {

                    // permission denied, boo! Disable the
                    // functionality that depends on this permission.
                    Toast.makeText(this, "permission denied", Toast.LENGTH_LONG).show();
                }
                return;
            }

            // other 'case' lines to check for other
            // permissions this app might request
        }
    }

}

Solution 2

Here is a Simple method of updating marker as soon as the location changes! As we know the onLocationChanged() methode is called when ever there is a change in location. And here we basically set the marker to the current position. Follow the process given bellow. That works for me and I hope it will do for you as well :)

@RequiresApi(api = Build.VERSION_CODES.N)//This line requires if you are using 25/26 API
@Override
public void onLocationChanged(Location location) {
    //Removing previously added markers here!
    mMap.clear();
    Log.d(TAG, "Firing onLocationChanged..............................................");
    mCurrentLocation = location;
    mLastUpdateTime = DateFormat.getTimeInstance().format(new Date());

    updateUI();
}

We can simply clear previously added markers using the mMap.clear() where mMap is the GoogleMap object and is also called and assigned in onMapReady() methode. Then we can get current location and set marker in an external method which is here: updateUI();

private void updateUI() {
    Log.d(TAG, "UI update initiated .............");
    if (null != mCurrentLocation) {

        LatLng allLatLang = new LatLng(mCurrentLocation.getLatitude(),mCurrentLocation.getLongitude());

        MarkerOptions markerOptions = new MarkerOptions();
        markerOptions.position(allLatLang);
        markerOptions.title("USER NAME");
        markerOptions.snippet("Users Basic Information");
        markerOptions.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_ORANGE));
        locationMarker = mMap.addMarker(markerOptions);

        //You can add this lines if you want to show the realtime data change on any TextView
        String lat = String.valueOf(mCurrentLocation.getLatitude());
        String lng = String.valueOf(mCurrentLocation.getLongitude());
        locationUpdate.setText("At Time: " + mLastUpdateTime + "\n" +
                "Latitude: " + lat + "\n" +
                "Longitude: " + lng + "\n" +
                "Accuracy: " + mCurrentLocation.getAccuracy() + "\n" +
                "Provider: " + mCurrentLocation.getProvider());
    } else {
        Log.d(TAG, "location is null ...............");
    }
}

So, when ever the location is changing, the onLocationChanged() method is called and then we are removing the existing markers and setting it again to the new position. Hope this will work out. Let me know if it helps. Thank you.!

Share:
20,198
jay gandhi
Author by

jay gandhi

Updated on July 09, 2022

Comments

  • jay gandhi
    jay gandhi almost 2 years
      package com.jaygandhi.map3;
    
     import android.Manifest;
     import android.content.pm.PackageManager;
     import android.location.Location;
     import android.os.Build;
     import android.support.v4.app.ActivityCompat;
     import android.support.v4.app.FragmentActivity;
     import android.os.Bundle;
     import android.support.v4.content.ContextCompat;
     import android.support.v7.app.AppCompatActivity;
     import android.widget.Toast;
    
     import com.google.android.gms.common.ConnectionResult;
     import com.google.android.gms.common.api.GoogleApiClient;
     import com.google.android.gms.location.LocationListener;
     import com.google.android.gms.location.LocationRequest;
     import com.google.android.gms.location.LocationServices;
     import com.google.android.gms.maps.CameraUpdateFactory;
     import com.google.android.gms.maps.GoogleMap;
     import com.google.android.gms.maps.OnMapReadyCallback;
     import com.google.android.gms.maps.SupportMapFragment;
     import com.google.android.gms.maps.model.BitmapDescriptorFactory;
     import com.google.android.gms.maps.model.LatLng;
     import com.google.android.gms.maps.model.Marker;
     import com.google.android.gms.maps.model.MarkerOptions;
    
    
    
    public class MapsActivity extends AppCompatActivity
            implements OnMapReadyCallback,
            GoogleApiClient.ConnectionCallbacks,
            GoogleApiClient.OnConnectionFailedListener,
            LocationListener
    {
    
        GoogleMap mGoogleMap;
        SupportMapFragment mapFrag;
        LocationRequest mLocationRequest;
        GoogleApiClient mGoogleApiClient;
        Location mLastLocation;
        Marker mCurrLocationMarker;
    
        @Override
        protected void onCreate(Bundle savedInstanceState)
        {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_maps);
    
            if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                checkLocationPermission();
            }
    
            mapFrag = (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map);
            mapFrag.getMapAsync(this);
        }
    
        @Override
        public void onPause() {
            super.onPause();
    
            //stop location updates when Activity is no longer active
            if (mGoogleApiClient != null) {
                LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, this);
            }
        }
    
        @Override
        public void onMapReady(GoogleMap googleMap)
        {
            mGoogleMap=googleMap;
            mGoogleMap.setMapType(GoogleMap.MAP_TYPE_HYBRID);
    
            //Initialize Google Play Services
            if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                if (ContextCompat.checkSelfPermission(this,
                        Manifest.permission.ACCESS_FINE_LOCATION)
                        == PackageManager.PERMISSION_GRANTED) {
                    buildGoogleApiClient();
                    mGoogleMap.setMyLocationEnabled(true);
                }
            }
            else {
                buildGoogleApiClient();
                mGoogleMap.setMyLocationEnabled(true);
            }
        }
    
        protected synchronized void buildGoogleApiClient() {
            mGoogleApiClient = new GoogleApiClient.Builder(this)
                    .addConnectionCallbacks(this)
                    .addOnConnectionFailedListener(this)
                    .addApi(LocationServices.API)
                    .build();
            mGoogleApiClient.connect();
        }
    
        @Override
        public void onConnected(Bundle bundle)
        {
            mLocationRequest = new LocationRequest();
            mLocationRequest.setInterval(1000);
            mLocationRequest.setFastestInterval(1000);
            mLocationRequest.setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY);
            if (ContextCompat.checkSelfPermission(this,
                    Manifest.permission.ACCESS_FINE_LOCATION)
                    == PackageManager.PERMISSION_GRANTED)
            {
    
                LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);
    
            }
        }
    
        @Override
        public void onConnectionSuspended(int i) {}
    
        @Override
        public void onConnectionFailed(ConnectionResult connectionResult) {}
    
        @Override
        public void onLocationChanged(Location location)
        {
            mLastLocation = location;
            if (mCurrLocationMarker != null)
            {
                mCurrLocationMarker.remove();
            }
    
            //Place current location marker
            LatLng latLng = new LatLng(location.getLatitude(), location.getLongitude());
            MarkerOptions markerOptions = new MarkerOptions();
            markerOptions.position(latLng);
            markerOptions.title("Current Position");
            markerOptions.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_ORANGE));
            mCurrLocationMarker = mGoogleMap.addMarker(markerOptions);
    
            //move map camera
            mGoogleMap.moveCamera(CameraUpdateFactory.newLatLng(latLng));
            mGoogleMap.animateCamera(CameraUpdateFactory.zoomTo(11));
    
            if (mGoogleApiClient != null)
            {
                LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, this);
            }
        }
    
        public static final int MY_PERMISSIONS_REQUEST_LOCATION = 99;
        public boolean checkLocationPermission(){
            if (ContextCompat.checkSelfPermission(this,
                    Manifest.permission.ACCESS_FINE_LOCATION)
                    != PackageManager.PERMISSION_GRANTED) {
    
                // Should we show an explanation?
                if (ActivityCompat.shouldShowRequestPermissionRationale(this,
                        Manifest.permission.ACCESS_FINE_LOCATION)) {
    
                    // Show an expanation to the user *asynchronously* -- don't block
                    // this thread waiting for the user's response! After the user
                    // sees the explanation, try again to request the permission.
    
                    //Prompt the user once explanation has been shown
                    ActivityCompat.requestPermissions(this,
                            new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
                            MY_PERMISSIONS_REQUEST_LOCATION);
    
    
                } else {
                    // No explanation needed, we can request the permission.
                    ActivityCompat.requestPermissions(this,
                            new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
                            MY_PERMISSIONS_REQUEST_LOCATION);
                }
                return false;
            } else {
                return true;
            }
        }
    
        @Override
        public void onRequestPermissionsResult(int requestCode,
                                               String permissions[], int[] grantResults) {
            switch (requestCode) {
                case MY_PERMISSIONS_REQUEST_LOCATION: {
                    // If request is cancelled, the result arrays are empty.
                    if (grantResults.length > 0
                            && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
    
                        // permission was granted, yay! Do the
                        // contacts-related task you need to do.
                        if (ContextCompat.checkSelfPermission(this,
                                Manifest.permission.ACCESS_FINE_LOCATION)
                                == PackageManager.PERMISSION_GRANTED) {
    
                            if (mGoogleApiClient == null) {
                                buildGoogleApiClient();
                            }
                            mGoogleMap.setMyLocationEnabled(true);
                        }
    
                    } else {
    
                        // permission denied, boo! Disable the
                        // functionality that depends on this permission.
                        Toast.makeText(this, "permission denied", Toast.LENGTH_LONG).show();
                    }
                    return;
                }
    
                // other 'case' lines to check for other
                // permissions this app might request
            }
        }
    
    }
    

    This code I get from different answer but it did not update in real time.

    I tried this code but when maps loads first time marker show current location but when my location is changed marker do not move to new location.

  • jay gandhi
    jay gandhi about 8 years
    sir, i removed this lines you told me and i went outside and check it again... but still marker is not moving to new location
  • jay gandhi
    jay gandhi about 8 years
    google's default current location marker(blue dot) is moving to new location , but costume marker markerOptions.icon(BitmapDescriptorFactory.defaultMarker(Bit‌​mapDescriptorFactory‌​.HUE_ORANGE)); is not moving to new location
  • jay gandhi
    jay gandhi about 8 years
    yes, i can send you screenshot, i am trying this from 2 days
  • jay gandhi
    jay gandhi about 8 years
    it works only first time , when we load the map , after that when we change location costume marker is not moving as default google marker moves.
  • Daniel Nugent
    Daniel Nugent about 8 years
    @jaygandhi I just updated the answer again, I realized that it needs to re-register for location updates in onResume() in order for it to work correctly when opening the app when it was already running in the background.
  • jay gandhi
    jay gandhi about 8 years
    thank you very much sir , it is working now, but can help me in fixing zoom level and camera potion for current location? i am using fake gps app to test the code, when i make change latitude and longitude in fake gps and again open the above code , it reloads the map and zoom to default level... how to maintain zoom level and camera position for current location
  • Daniel Nugent
    Daniel Nugent about 8 years
    @jay glad it's working! As for your next question, that is a bit broad, but basically you need to figure out all of the cases that you do want to set the zoom level, and when you want to leave it alone, and then write support for all of those cases in the code.
  • jay gandhi
    jay gandhi about 8 years
    in this code onStart() method is needed or not ? because when i open application it takes 5-10 to detect the location. any solution for that ? I am making live gps tracking application for my final year project.
  • Daniel Nugent
    Daniel Nugent about 8 years
    No, onStart() is not needed. I tested this code on a real device, and it got a location immediately every time, but it may have to do with my location (lots of wifi hotspots around)
  • jay gandhi
    jay gandhi about 8 years
    Or i put make changes in onMapReady() ready method ? can you help me also in geofancing ?
  • jay gandhi
    jay gandhi about 8 years
    How to send notification to one user when another user is in the first's user's Geofencing region
  • jay gandhi
    jay gandhi about 8 years
    Sir How do i zoom in automatically to the current location in this code
  • Hammad Nasir
    Hammad Nasir about 7 years
    @DanielNugent what if there are more than one marker?
  • Daniel Nugent
    Daniel Nugent about 7 years
    @HammadNasir This example only uses one Marker to show your current location. Of course, you can add as many Markers as you like in addition to the current location Marker.
  • Hammad Nasir
    Hammad Nasir about 7 years
    @DanielNugent thanks for replying. In my case, several players opens this activity which has a map from their devices and their location is shown on the map. Now what I want is to update the respective marker whenever any user's location changes to the respective location. How can I achieve this? Please guide me through this.
  • Daniel Nugent
    Daniel Nugent about 7 years
    @HammadNasir Are you trying to show all online user's location to each user of the app?
  • Hammad Nasir
    Hammad Nasir about 7 years
    @DanielNugent yeah sort of... Not to each user of the app but to a particular group of users. Each others location to each other users (online users) in that group.
  • Daniel Nugent
    Daniel Nugent about 7 years
    @HammadNasir Well, you'll need to develop server functionality such that each user can tell the server their location, and also query the server to get the location of other users in their group. Then, for each location the server gives you for other users, place a Marker on the map.
  • Hammad Nasir
    Hammad Nasir about 7 years
    @DanielNugent Yeah... I've tried it but still having issues. It'd be really helpful if you can help with this: stackoverflow.com/q/42252017/6144372
  • Hammad Nasir
    Hammad Nasir about 7 years
    @DanielNugent hey... Please help with it. Thanks.