-1

In the below code, I am able to create a marker on the map. Whenever I try to run it with the runnable, I get the error stating to googleMap with the error as:

java.lang.RuntimeException: Unable to start activity ComponentInfo{com.journaldev.MapsInAction/com.journaldev.MapsInAction.MainActivity}: java.lang.NullPointerException: Attempt to invoke virtual method 'com.google.android.gms.maps.model.Marker com.google.android.gms.maps.GoogleMap.addMarker(com.google.android.gms.maps.model.MarkerOptions)' on a null object reference

The code is as follows:

import android.graphics.Point;
import android.os.Bundle;
import android.os.Handler;
import android.os.SystemClock;
import android.support.design.widget.FloatingActionButton;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.View;
import android.view.Menu;
import android.view.MenuItem;
import android.view.animation.Interpolator;
import android.view.animation.LinearInterpolator;

import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.MapFragment;
import com.google.android.gms.maps.OnMapReadyCallback;
import com.google.android.gms.maps.Projection;
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 MainActivity extends AppCompatActivity implements OnMapReadyCallback {

    SupportMapFragment mapFragment;
    private GoogleMap googleMap;
    double latitude=12.9716;
    double longitude=77.5946;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);


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

        FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
        fab.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                mapFragment.getMapAsync(new OnMapReadyCallback() {
                    @Override
                    public void onMapReady(GoogleMap googleMap) {
                        googleMap.setMapType(GoogleMap.MAP_TYPE_NORMAL);

                        googleMap.addMarker(new MarkerOptions()
                                .position(new LatLng(latitude, longitude))
                                .title("Bus Location")
                                .icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_GREEN)));

                        googleMap.animateCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(latitude, longitude), 15));
                    }
                });
            }
        });
        periodicUpdate.run();
    }
    Handler handler = new Handler();
    private Runnable periodicUpdate = new Runnable() {
        @Override
        public void run() {
            handler.postDelayed(periodicUpdate, 10*1000 - SystemClock.elapsedRealtime()%1000);
            latitude+=0.01;
            longitude+=0.01;
            MarkerOptions a = new MarkerOptions()
                    .position(new LatLng(50,6));
            Marker m = googleMap.addMarker(a);
            m.setPosition(new LatLng(50,5));
        }
    };
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

        //noinspection SimplifiableIfStatement
        if (id == R.id.action_settings) {
            return true;
        }

        return super.onOptionsItemSelected(item);
    }

    @Override
    public void onMapReady(GoogleMap googleMap)
    {
      googleMap.addMarker(new MarkerOptions()
              .position(new LatLng(latitude, longitude))
              .title("Bus Location")
              .icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_GREEN)));


        googleMap.animateCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(latitude, longitude), 15));

    }
}

How do I make sure that the code also updates the marker every 10 seconds? If the Runnable code is removed, it works perfectly with the marker shown. With the Runnable code, it crashes with the error above.

Phantômaxx
  • 37,901
  • 21
  • 84
  • 115
Rathan
  • 29
  • 1
  • 8

4 Answers4

2

getMapAsync initialize Map asynchronously. So when you call googleMap.addMarker() at first time in your Runnable it crashes because Map is not initialized yet and googleMap is null. Easiest way to fix this is move periodicUpdate.run(); to onMapReady() callback Also you must not forget to clean Runnable in onPause()

Onix
  • 662
  • 3
  • 10
0

There are several issues with your code. At first, it crashes because in periodicUpdate.run(); you try to create marker (Marker m = googleMap.addMarker(a);) by calling addMarker() on global private GoogleMap googleMap; object which is not initialized. It will be better if you rename private GoogleMap googleMap; to private GoogleMap mGoogleMap; and init mGoogleMap in onMapReady(GoogleMap googleMap) by mGoogleMap = googleMap nd than call addMarker() on it: Marker mGoogleMap = googleMap.addMarker(a);. Also, you should get rid of two onMapReady() methods. And you should start call periodicUpdate.run(); inside onMapReady() because in other case its possible that the Marker m = mGoogleMap.addMarker(a); can be called before mGoogleMap was created. And you should declare Marker m as global (private Marker mMarker) for possibility to remove it before create updated marker. And seems you didn't update LatLng of marker... So, there are a lot of work...

Andrii Omelchenko
  • 13,183
  • 12
  • 43
  • 79
0

You are putting marker before map is initialized in runnable. That is why it is causing null pointer exception and crashing app. Putting a null pointer check will resolve this error. Try this:

    @Override
public void run() {
    handler.postDelayed(periodicUpdate, 10 * 1000 - SystemClock.elapsedRealtime() % 1000);
    latitude += 0.01;
    longitude += 0.01;
    MarkerOptions a = new MarkerOptions()
            .position(new LatLng(50, 6));
    if (googleMap != null) {
        Marker m = googleMap.addMarker(a);
    }
    m.setPosition(new LatLng(50, 5));
}
Arslan Shoukat
  • 432
  • 4
  • 10
0

You haven't initialed the variable googleMap yet. And before using googleMap, you have to make sure Google Map is ready. So follow this code:

    private Runnable periodicUpdate = new Runnable() {
    @Override
    public void run() {
        handler.postDelayed(periodicUpdate, 10*1000 - SystemClock.elapsedRealtime()%1000);
        if(googleMap){
        latitude+=0.01;
        longitude+=0.01;
        MarkerOptions a = new MarkerOptions()
                .position(new LatLng(50,6));
        Marker m = googleMap.addMarker(a);
        m.setPosition(new LatLng(50,5));
        }

    }
};

@Override
public void onMapReady(GoogleMap googleMap)
{
  this.googleMap = googleMap;
  googleMap.addMarker(new MarkerOptions()
          .position(new LatLng(latitude, longitude))
          .title("Bus Location")
          .icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_GREEN)));


    googleMap.animateCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(latitude, longitude), 15));

}
Louis Solo
  • 136
  • 2