1

Once the customer name is clicked the place of his/her needs to be marked with a marker on google map. As I am displaying the customer details on a popup window, the customer's latitude and longitude are being passed from popup window class to the map activity class as an object through intents. While receiving it in map activity.java it becomes null and throwing a null pointer exception.

my code for popup window class (CustomerPupUp.java):

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_customer_pop_up);

    DisplayMetrics dm = new DisplayMetrics();
    getWindowManager().getDefaultDisplay().getMetrics(dm);

    int width = dm.widthPixels;
    int height = dm.heightPixels;

    getWindow().setLayout((int)(width),(int)(height*.7));

    listView = (ListView)findViewById(R.id.custListVw);
    database = FirebaseDatabase.getInstance();
    reference = database.getReference("Customers");

    list = new ArrayList<>();
    adapter = new ArrayAdapter<String>(this, R.layout.activity_cust_layout,R.id.cus, list);

    customer = new AddCustomer();
    reference.addValueEventListener(new ValueEventListener() {
        @Override
        public void onDataChange(DataSnapshot dataSnapshot) {
            for(DataSnapshot ds: dataSnapshot.getChildren() )
            {
                customer = ds.getValue(AddCustomer.class);
                Log.d("CustomerPopUp", "onDataChange: " + customer.getLat());
                list.add(customer.getFname().toString() + " " + customer.getLname().toString()  );
                customerList.add(customer);

            }
            listView.setAdapter(adapter);
            listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
                @Override
                public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                    Intent intent = new Intent(CustomerPopUp.this, MapsActivity.class);
                    intent.putExtra("CustomerData", customerList.get(position));
                    startActivity(intent);
                }
            });
        }

        @Override
        public void onCancelled(DatabaseError databaseError) {

        }
    });
}

following code segment shows how I am getting the object through intent in MapsActivity.java

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_maps);

    try {
        database = FirebaseDatabase.getInstance();
        reference = database.getReference("Customers");

        customer= (AddCustomer) getIntent().getSerializableExtra("CustomerData");

        mMap.addMarker(new MarkerOptions().position(new LatLng(customer.getLat(), customer.getLng())).title(customer.getFname() + customer.getLname()));

    }catch (NullPointerException ex)
    {
        Log.d(TAG, "onCreate: " + ex.getMessage());
    }

    search = (EditText)findViewById(R.id.SearchText);
    gps =(ImageView) findViewById(R.id.GpsBtn);
    cust = (ImageView)findViewById(R.id.CusBtn);

    isServiceFine();

    getLocationPermission();

    cust.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            Intent intent = new Intent(MapsActivity.this, CustomerPopUp.class);
            startActivity(intent);
        }
    });
}

following is the AddCustomer class

public class AddCustomer implements Serializable {

private String fname;
private String lname;
private String email;
private String pass;
private String confPass;
private int num;
Double lat;
Double lng;


AddCustomer()
{

}

public AddCustomer(String FName, String LName, String EMail, String PWD, String CONFPWD, int NUM, Double latitude, Double longtitude)
{
    this.fname = FName;
    this.lname = LName;
    this.email = EMail;
    this.pass = PWD;
    this.confPass = CONFPWD;
    this.num = NUM;
    this.lat = latitude;
    this.lng = longtitude;

}

public String getFname() {
    return fname;
}

public void setFname(String fname) {
    this.fname = fname;
}

public String getLname() {
    return lname;
}

public void setLname(String lname) {
    this.lname = lname;
}

public String getEmail() {
    return email;
}

public void setEmail(String email) {
    this.email = email;
}

public String getPass() {
    return pass;
}

public void setPass(String pass) {
    this.pass = pass;
}

public String getConfPass() {
    return confPass;
}

public void setConfPass(String confPass) {
    this.confPass = confPass;
}

public int getNum() {
    return num;
}

public void setNum(int num) {
    this.num = num;
}

public Double getLat() {
    return lat;
}

public void setLat(Double lat) {
    this.lat = lat;
}

public Double getLng() {
    return lng;
}

public void setLng(Double lng) {
    this.lng = lng;
}

}

Please help me solve this issue.

Coder
  • 338
  • 2
  • 19
  • You're resetting the adapter and click listener every single time an object in Firebase changes... That's probably not what you want and explains very well why things are null - You're expecting data that is being overwritten – OneCricketeer May 01 '18 at 01:01
  • But I've used the same method to display customer details on labels and it worked. – Coder May 01 '18 at 01:16
  • Okay, well, still. You should move `listView.setOnItemClickListener` outside of `reference.addValueEventListener`. It's also recommended to use Parcelable objects, as mentioned in the answer rather than Serializable – OneCricketeer May 01 '18 at 02:24
  • does your AddCustomer implements Serializable? and have you checked if customerList != null or its size is more than 0? – Sakura Fukuyoshi May 01 '18 at 02:32
  • @cricket_007 Even after moving it outside I'm getting the same exception. – Coder May 02 '18 at 01:25
  • @SakuraFukuyoshi Yeah AddCustomer class implements Serializable. but I did't check customerlist != null until now. – Coder May 02 '18 at 01:28
  • can you check it first? Maybe you don't have any items in your customerList and that is the reason why you are getting null – Sakura Fukuyoshi May 02 '18 at 02:57
  • @SakuraFukuyoshi I tried it under onMapReady method and its working. – Coder May 02 '18 at 12:20

3 Answers3

1

You can only pass Parcelable or Serializable objects through Intent. In this case, with your custom object, you need to make it implement Parcelable or Serializable.

I recommend using http://www.parcelabler.com/ to generate your code easily.

See: How can I make my custom objects Parcelable?

Lucas Cabrales
  • 2,073
  • 1
  • 12
  • 21
0

mMap.addMarker(new MarkerOptions().position(new LatLng(customer.getLat(), customer.getLng())).title(customer.getFname() + customer.getLname()));

This is where your problem lies. Instead of using an anonymous object, declare Class variables of MarkerOptions and LatLng and use it like this:

public class Foo extends FragmentActivity implements OnMapReadyCallback {

    private MarkerOptions mrkOpt = new MarkerOptions();
    private LatLng lalg;

    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_maps);

        try {
            database = FirebaseDatabase.getInstance();
            reference = database.getReference("Customers");

            customer= (AddCustomer) getIntent().getSerializableExtra("CustomerData");

            lalg = new LatLng(customer.getLat(), customer.getLng());
            mrkOpt.position(lalg);
            mrkOpt.title(customer.getFname() + customer.getLname())

            mMap.addMarker(mrkOpt);

        }catch (NullPointerException ex)
        {
            Log.d(TAG, "onCreate: " + ex.getMessage());
        }

        search = (EditText)findViewById(R.id.SearchText);
        gps =(ImageView) findViewById(R.id.GpsBtn);
        cust = (ImageView)findViewById(R.id.CusBtn);

        isServiceFine();

        getLocationPermission();

        cust.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent(MapsActivity.this, CustomerPopUp.class);
                startActivity(intent);
            }
        });
    }
}
sam
  • 1,800
  • 1
  • 25
  • 47
  • thanks for your answer. But still i'm getting this null exception. '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' – Coder May 02 '18 at 01:17
  • your code worked for me when I place the try catch part under onMapReady method. Thank you! – Coder May 02 '18 at 12:23
0

Can you try this? Remove the setAdapter and the onItemClickListener inside onDataChange and put it on onCreate.. then on your onDataChange check if the adapter is null then if not try to do notifyDataSetChanged

I dont know if this will work but I hope you get the picture. I think the possible problem is that you are not passing any data and that's the cause of the Null exception.

     protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_customer_pop_up);

        DisplayMetrics dm = new DisplayMetrics();
        getWindowManager().getDefaultDisplay().getMetrics(dm);

        int width = dm.widthPixels;
        int height = dm.heightPixels;

        getWindow().setLayout((int)(width),(int)(height*.7));

        listView = (ListView)findViewById(R.id.custListVw);
        database = FirebaseDatabase.getInstance();
        reference = database.getReference("Customers");

        list = new ArrayList<>();
        adapter = new ArrayAdapter<String>(this, R.layout.activity_cust_layout,R.id.cus, list);

        listView.setAdapter(adapter);
        listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
                    @Override
                    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                        if(customerList.size() != 0) {
                           Intent intent = new Intent(CustomerPopUp.this, MapsActivity.class);
                           intent.putExtra("CustomerData", customerList.get(position));
                           startActivity(intent);
                        }
                    }
                });

        customer = new AddCustomer();
        reference.addValueEventListener(new ValueEventListener() {
            @Override
            public void onDataChange(DataSnapshot dataSnapshot) {
                for(DataSnapshot ds: dataSnapshot.getChildren() )
                {
                    customer = ds.getValue(AddCustomer.class);
                    Log.d("CustomerPopUp", "onDataChange: " + customer.getLat());
                    list.add(customer.getFname().toString() + " " + customer.getLname().toString()  );
                    customerList.add(customer);

                    if(adapter != null)
                        adapter.notifyDataSetChanged();

                }

            }

            @Override
            public void onCancelled(DatabaseError databaseError) {

            }
        });
    }
Sakura Fukuyoshi
  • 1,461
  • 1
  • 10
  • 14
  • thanks for your answer. But I tried printing the value on Log and am getting the correct values passed. – Coder May 02 '18 at 12:17