0
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_map);
    SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
            .findFragmentById(R.id.google_map);


    restaurantNearbyRef = FirebaseDatabase.getInstance().getReference().child("Restaurant").child("Info");
    fusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(this);


    fetchLastLocation();
    getNearbyRestaurant();


}


private ArrayList<Marker> restaurantMarker = new ArrayList<>();

private void fetchLastLocation() {

    if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.ACCESS_FINE_LOCATION)) {
        ActivityCompat.requestPermissions(this, new String[]
                {Manifest.permission.ACCESS_FINE_LOCATION}, REQUEST_CODE);
        return;
    }
    Task<Location> task = fusedLocationProviderClient.getLastLocation();
    task.addOnSuccessListener(new OnSuccessListener<Location>() {
        @Override
        public void onSuccess(Location location) {
            if (location != null) {

                mCurrentLocation = location;
                Toast.makeText(getApplicationContext(), mCurrentLocation.getLatitude()
                        + "" + mCurrentLocation.getLongitude(), Toast.LENGTH_SHORT).show();
                SupportMapFragment supportMapFragment = (SupportMapFragment)
                        getSupportFragmentManager().findFragmentById(R.id.google_map);
                supportMapFragment.getMapAsync(MapActivity.this);

                latitude = mCurrentLocation.getLatitude();
                longitude = mCurrentLocation.getLongitude();

                Log.d(TAG, "The latitude is " + latitude + " and the longitude is " + longitude);
            }

        }

    });

}


public void getNearbyRestaurant(){
    if (restaurantMarker != null) {
        for (Marker marker : restaurantMarker) {
            marker.remove();
        }
    }

    GeoFire geoFire = new GeoFire(restaurantNearbyRef);

    GeoQuery geoQuery = geoFire.queryAtLocation(new GeoLocation(latitude,longitude),radius);
    geoQuery.addGeoQueryEventListener(new GeoQueryEventListener() {
        @Override
        public void onKeyEntered(String key, GeoLocation location) {
            restaurantMarker
                    .add(mMap.addMarker(new MarkerOptions().title("Restaurant").icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_BLUE))
                            .position(new LatLng(location.latitude, location.longitude))));

            Log.d(TAG,"The getNearbyRestaurant latitude is " + latitude + "and the longitude is " +longitude );
        }

        @Override
        public void onKeyExited(String key) {

        }

        @Override
        public void onKeyMoved(String key, GeoLocation location) {

        }

        @Override
        public void onGeoQueryReady() {

        }

        @Override
        public void onGeoQueryError(DatabaseError error) {

        }
    });
}

My function getNearbyRestaurant is not called. I am not sure why? I have tried to place in different locations but yet failed to call. Hope anyone can help. I am trying to show a list of nearby restaurant near my current location. I maybe missing something. Hope anyone can help as there are not much resource when it comes to getting nearby locations. I have seen more videos on e-hailing service

I.Z.
  • 23
  • 8

1 Answers1

0

Both fetchLastLocation and getNearbyRestaurant load data asynchronously. If you run the code in a debugger, or add some logging, you'll see that by the time your GeoQuery geoQuery = geoFire.queryAtLocation(new GeoLocation(latitude,longitude),radius) runs, the latitude = mCurrentLocation.getLatitude() lines haven't run yet.

Data is loaded from Firebase asynchronously and locations are retrieved from the Android OS asynchronously. The main thread of your Android app does not wait for that data or location to be available. For that reason, any code that needs the location or the data needs to be inside the relevant callback, or be called from there.

The simplest fix is to call getNearbyRestaurant from within onSuccess:

Task<Location> task = fusedLocationProviderClient.getLastLocation();
task.addOnSuccessListener(new OnSuccessListener<Location>() {
    @Override
    public void onSuccess(Location location) {
        if (location != null) {

            mCurrentLocation = location;
            Toast.makeText(getApplicationContext(), mCurrentLocation.getLatitude()
                    + "" + mCurrentLocation.getLongitude(), Toast.LENGTH_SHORT).show();
            SupportMapFragment supportMapFragment = (SupportMapFragment)
                    getSupportFragmentManager().findFragmentById(R.id.google_map);
            supportMapFragment.getMapAsync(MapActivity.this);

            latitude = mCurrentLocation.getLatitude();
            longitude = mCurrentLocation.getLongitude();

            Log.d(TAG, "The latitude is " + latitude + " and the longitude is " + longitude);

            getNearbyRestaurant();
        }

I highly recommend reading up on asynchronous APIs, as the way this works is the same for pretty much any modern cloud or I/O based API.

See:

Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807
  • Hi Frank, I have tried your method but it seems that getNearbyRestaurant() is not called – I.Z. Apr 15 '20 at 15:56
  • That means that you're entire `onSuccess` isn't called. Interactively debugger is really inefficient to do through Stack Overflow though. It's best if you debug the code yourself, set breakpoints at all lines, and then see what doesn't do what you expect it to do. – Frank van Puffelen Apr 15 '20 at 16:03