Search code examples
androidgpsskmaps

Display current location after GPS is enabled in android


I am new in Skobbler map. I using the Skobbler map to display my current location. Initially the marker is at somewhere in the map. enter image description here

I have set the default location at United States of America. So that, when i open the application it displays this. But, the marker is still somewhere in the map, above the sea. To display default location, I used this:

SKCoordinateRegion region = new SKCoordinateRegion();
region.setCenter(new SKCoordinate(-97.1867366, 38.4488163));
region.setZoomLevel(5);
mapView.changeMapVisibleRegion(region, true);

enter image description here

After that, when I enabled the GPS, the marker must move and shows my current location within time. What can be done to refresh the map to show my current location. What can be done to solve this problem?


Solution

  • TL;DR :

    SKCoordinate coordinates = new SKCoordinate (-97.1867366, 38.4488163)
    SKPosition lastSKPosition  = new SKPosition (coordinates);
    SKPositionerManager.getInstance ().reportNewGPSPosition (lastSKPosition);
    mapView.centerOnCurrentPosition (ZoomLevel, true, AnimationDuration);
    mapView.setPositionAsCurrent (lastSKPosition.getCoordinate (), Accuracy, center);
    

    Not being an expert on Skobbler, I don't like very much the Skobbler SDK as it looks too complex to me and the doc very poor, too much methods and classes, so I try to leverage the Android SDK and Google APIs as much as I can.

    This is not a production ready code but just so you can get the picture.

    This is how I like to organize my code when it comes to location :

    Abstract Location activity from which you'll extend all the activities that use location :

    public abstract class LocationActivity extends AppCompatActivity {
    
        private GeoLocService locationService;
    
        @Override
        protected void onCreate (Bundle savedInstanceState) {
            super.onCreate (savedInstanceState);
    
            if (GeoLocService.checkLocationPerms (this)) {
                initLocService ();
            }
        }
    
        @Override
        protected void onStart () {
            super.onStart ();
            if (locationService != null) {
                locationService.onStart ();
            }
        }
    
        @Override
        public void onRequestPermissionsResult (int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
            super.onRequestPermissionsResult (requestCode, permissions, grantResults);
            if (requestCode == 1000) {
                if (GeoLocService.checkLocationPerms (this)) {
                    initLocService ();
                    locationService.onStart ();
                }
            }
        }
    
        @Override
        protected void onResume () {
            super.onResume ();
            if (locationService != null) {
                locationService.onResume ();
            }
        }
    
        @Override
        protected void onPause () {
            super.onPause ();
            if (locationService != null) {
                locationService.onPause ();
            }
        }
    
        @Override
        protected void onStop () {
            if (locationService != null) {
                locationService.disconnect ();
            }
            super.onStop ();
        }
    
        private void initLocService () {
            GeoLocService.LocationResponse response = new GeoLocService.LocationResponse () {
    
                @Override
                public void onLocation (Location location) {
                    onLocationSuccess (location);
                }
    
                @Override
                public void onFailure (int errorCode) {
                    onLocationFailure (errorCode);
                }
            };
            locationService = new GeoLocService (this, response);
        }
    
        protected void stopFetchingLocations () {
            if (locationService != null) {
                locationService.stopLocationUpdates ();
                locationService.disconnect ();
            }
        }
    
        protected GeoLocService getLocationService () {
            return locationService;
        }
    
        protected abstract void onLocationSuccess (Location location);
        protected abstract void onLocationFailure (int errorCode);
    }
    

    GeoLoc Service that provides geoloc handling methods :

    public class GeoLocService implements ConnectionCallbacks, OnConnectionFailedListener, LocationListener {
    
        public final static long    UPDATE_INTERVAL_IN_MILLISECONDS = 10000;
    
        public final static long    FASTEST_UPDATE_INTERVAL_IN_MILLISECONDS = UPDATE_INTERVAL_IN_MILLISECONDS / 2;
    
        private GoogleApiClient     googleApiClient;
        private LocationRequest     locationRequest;
        private LocationResponse    locationResponse;
        private Location            currentLocation;
    
        private Date                lastUpdateTime;
    
        public GeoLocService (Activity context, LocationResponse locationResponse) {
            this.locationResponse   = locationResponse;
    
            googleApiClient         = new GoogleApiClient.Builder (context)
                .addConnectionCallbacks (this)
                .addOnConnectionFailedListener (this)
                .addApi (LocationServices.API)
                .build ();
    
            createLocationRequest ();
        }
    
        public void onStart () {
            if (googleApiClient != null) {
                googleApiClient.connect ();
            }
        }
    
        public void onResume () {
            if (googleApiClient != null && googleApiClient.isConnected ()) {
                startLocationUpdates ();
            }
        }
    
        public void onPause () {
            if (googleApiClient != null && googleApiClient.isConnected ()) {
                stopLocationUpdates ();
            }
        }
    
        public void disconnect () {
            if (googleApiClient != null) {
                googleApiClient.disconnect ();
            }
        }
    
        protected void createLocationRequest () {
            locationRequest = new LocationRequest ();
            locationRequest.setInterval (UPDATE_INTERVAL_IN_MILLISECONDS);
            locationRequest.setFastestInterval (FASTEST_UPDATE_INTERVAL_IN_MILLISECONDS);
            locationRequest.setPriority (LocationRequest.PRIORITY_HIGH_ACCURACY);
        }
    
        public void startLocationUpdates () {
            LocationServices.FusedLocationApi.requestLocationUpdates (googleApiClient, locationRequest, this);
        }
    
        public void stopLocationUpdates() { 
            LocationServices.FusedLocationApi.removeLocationUpdates(googleApiClient, this);
        }
    
        @Override
        public void onConnected(Bundle connectionHint) {
            if (currentLocation == null) {
                currentLocation = LocationServices.FusedLocationApi.getLastLocation (googleApiClient);
                lastUpdateTime  = Calendar.getInstance ().getTime ();
                sendUpdates ();
            }
    
            startLocationUpdates ();
        }
    
        private void sendUpdates () {
            if (locationResponse != null && currentLocation != null) {
                locationResponse.onLocation (currentLocation);
            }
        }
    
        @Override
        public void onLocationChanged (Location location) {
            currentLocation = location;
            lastUpdateTime  = Calendar.getInstance ().getTime ();
            sendUpdates ();
        }
    
        @Override
        public void onConnectionSuspended (int cause) {
            googleApiClient.connect ();
        }
    
        @Override
        public void onConnectionFailed (ConnectionResult result) {
            if (locationResponse != null) {
                locationResponse.onFailure (result.getErrorCode ());
            }
        }
    
        public static boolean checkLocationPerms (Activity context) {
            if (ActivityCompat.checkSelfPermission (context, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED
                    && ActivityCompat.checkSelfPermission (context, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
    
                ActivityCompat.requestPermissions (
                        context,
                        new String [] {
                                Manifest.permission.ACCESS_FINE_LOCATION,
                                Manifest.permission.ACCESS_COARSE_LOCATION,
                                Manifest.permission.ACCESS_NETWORK_STATE
                        },
                        1000
                );
                return false;
            }
            return true;
        }
    
        public GoogleApiClient getGoogleApiClient () {
            return googleApiClient;
        }
    
        public Date getLastUpdatedTime () {
            return lastUpdateTime;
        }
    
        public interface LocationResponse {
            void onLocation (Location location);
            void onFailure (int errorCode);
        }
    }
    

    And finally your Skobbler Activity :

    public class SkobblerActivity extends LocationActivity implements SKMapSurfaceListener {
    
        private final static float  ZoomLevel           = 15;
        private final static int    AnimationDuration   = 750;
        private final static float  Accuracy            = 1;
    
        private int                 placedOnCurrentPosCount;
    
        private SKMapViewHolder     mapHolder;
        private SKMapSurfaceView    mapView;
    
        private SKPosition lastSKPosition  = new SKPosition (new SKCoordinate ());
    
        @Override
        protected void onCreate (Bundle savedInstanceState) {
            super.onCreate (savedInstanceState);
            .....
        }
    
        @Override
        protected void onLocationSuccess (Location location) {
            convertLocToSKLoc (location);
            SKPositionerManager.getInstance ().reportNewGPSPosition (lastSKPosition);
            if (mapView != null) {
                boolean center = false;
                if (placedOnCurrentPosCount < 2 && (location.getLatitude () != 0 || location.getLongitude () != 0)) {
                    center = true;
                    mapView.centerOnCurrentPosition (ZoomLevel, true, AnimationDuration);
                }
    
                mapView.setPositionAsCurrent (lastSKPosition.getCoordinate (), Accuracy, center);
    
                placedOnCurrentPosCount ++;
            }
        }
    
        @Override
        protected void onLocationFailure (int errorCode) {
        }
    
        private void convertLocToSKLoc (Location location) {
            lastSKPosition.getCoordinate ().setLatitude (location.getLatitude ());
            lastSKPosition.getCoordinate ().setLongitude (location.getLongitude ());
        }
    
        .......................
    }
    

    Any critics from the skobbler developers to improve this are welcome :)