2

I've been looking online for the past couple of weeks about this and it seems I'm not asking the right questions so posting one here. Thanks in advance for any info.

Using Android v7.1 and Google Maps API v2 I want to show a user's location on a map fragment. My question is: why does the default current location marker (blue circle in example image below) often not align with the marker I manually draw to show the user's location (green circle)? The code redraws the green marker when location is changed, so I am trying to figure out why the green marker is not being redrawn as often as the default current location marker moves.

Do I simply need to update the frequency/displacement that my LocationCallback() is getting called? Currently it is set at 500ms, with displacement of 2 meters. If this is the case, will that have significant impact on battery?

I've experimented with using onLocationChanged() instead of the fused location api's LocationCallback(), but then my manual marker doesn't get updated if the user doesn't have an internet connection.

I realize I've got something off in my code, but I guess my understanding isn't good enough that I'm managing to figure it out by myself. Thanks again in advance for any insight.


Relevant code and example image:

From MainActivity:

    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mapFragment = (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.mapFragment);
        mapFragment.getMapAsync(this);

        mFusedLocationClient = LocationServices.getFusedLocationProviderClient(this);

        mLocationCallback = new LocationCallback() {
            @Override
            public void onLocationResult(LocationResult locationResult) {
                super.onLocationResult(locationResult);
                mLastLocation = locationResult.getLastLocation();
                mapManager.updateLocation(mLastLocation); //this is where the green marker is drawn
            }
        };
    }

    @Override
    public void onConnectionSuspended(int i) {}

    @Override
    public void onConnectionFailed(@NonNull ConnectionResult connectionResult) {}

    @Override
    protected void onResume() {

        super.onResume();

        mapState = new MapState(this);

        if (mapFragment == null) {
            mapFragment = (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.mapFragment);
            mapFragment.getMapAsync(this);
        }
    }

    @Override
    public void onMapReady(GoogleMap googleMap) {
        mapManager.mMap = googleMap;
        mapManager.mMap.setOnMapLongClickListener(this);
        mapState = new MapState(this);

        //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();
                mapManager.mMap.setMyLocationEnabled(true);
            }
        }
        else {
            buildGoogleApiClient();
            mapManager.mMap.setMyLocationEnabled(true);
        }

        CameraPosition position = mapState.getSavedCameraPosition();
        if (position != null) {
            CameraUpdate update = CameraUpdateFactory.newCameraPosition(position);
            mapManager.mMap.setMapType(mapState.getSavedMapType());
        }
    }

    protected synchronized void buildGoogleApiClient() {
        //https://stackoverflow.com/questions/37102240/cannot-resolve-symbol-mgoogleapiclient-android-studio
        mGoogleApiClient = new GoogleApiClient.Builder(this)
                .addConnectionCallbacks(this)
                .addOnConnectionFailedListener(this)
                .addApi(LocationServices.API)
                .build();
        mGoogleApiClient.connect();
    }

    private void setupAndRequestLocationPermissions() {
        mLocationRequest = new LocationRequest();
        mLocationRequest.setInterval(500); 
        mLocationRequest.setFastestInterval(500);
mLocationRequest.setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY);
        mLocationRequest.setSmallestDisplacement(2); //10 meters
        if (ContextCompat.checkSelfPermission(this,
                Manifest.permission.ACCESS_FINE_LOCATION)
                == PackageManager.PERMISSION_GRANTED) {
            mFusedLocationClient.requestLocationUpdates(mLocationRequest,
                    mLocationCallback,
                    null);
        }
    }

    @Override
    public void onConnected(@Nullable Bundle bundle) {
        setupAndRequestLocationPermissions();
    }

    @Override
    public void onLocationChanged(Location location) {

    }

    @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.
                    if (ContextCompat.checkSelfPermission(this,
                            Manifest.permission.ACCESS_FINE_LOCATION)
                            == PackageManager.PERMISSION_GRANTED) {
                        if (mGoogleApiClient == null) {
                            buildGoogleApiClient();
                        }
                        mapManager.mMap.setMyLocationEnabled(true);

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

From manifest:

<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="com.google.android.providers.gsf.permission.READ_GSERVICES" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

Example image:

example google map image

sadie parker
  • 349
  • 5
  • 13
  • 3
    Currently you are asking for possibly inaccurate location updates and you don't want to get them any more often than every half a second. There's [some discussion about PRIORITY_BALANCED_POWER_ACCURACY](https://stackoverflow.com/questions/24090584/does-priority-balanced-power-accuracy-exclude-the-gps-provider). You can try PRIORITY_HIGH_ACCURACY instead. – Markus Kauppinen Jul 04 '18 at 10:44
  • Thanks so much, I'll check this out @MarkusKauppinen – sadie parker Jul 04 '18 at 11:18

0 Answers0