javaandroid-studiogoogle-mapsandroid-maps

Cannot get value of getter in OnMapReady (Android Studio)


Im trying to get realtime location with pointing on the Google Map. Currently i successfully get the latitude and longitude in realtime and it will update everytime to a getter, setter class called sosrecord.getLatitude() and sosrecord.getLongitude(). I want to point the google map based on the updated latitude and longitude. But everytime when i put the getter on the LatLng latLng = new LatLng(sosrecord.getLatitude(), sosrecord.getLongitude()); it will return me Null and eventually crash the app due to java.lang.NullPointerException: Attempt to invoke virtual method 'double java.lang.Double.doubleValue()' on a null object reference It should point the current location when user click on a button. Sorry if the code sample below is messy, hope someone could help me with this issue. Thanks.

Main.java

public class MainActivity extends FragmentActivity{
    private Handler mHandler = new Handler();
    DatabaseReference reff;
    SosRecords sosrecords;
    boolean startclicked =true;
    String selectedOfficer = "Police";
    private static final String TAG = "MainActivity";
    int LOCATION_REQUEST_CODE = 1001;
    SupportMapFragment smf;



    FusedLocationProviderClient fusedLocationProviderClient;
    LocationRequest locationRequest; 
    LocationCallback locationCallback = new LocationCallback() {
        @Override
        public void onLocationResult(LocationResult   <------This function will get the lat and long and set the value to sosrecordlocationResult) {
            if (locationResult == null) {
                return;
            }
            for (Location location : locationResult.getLocations()) {
                double lat = location.getLatitude();
                double lon = location.getLongitude();
                sosrecords.setLatitude(lat);
                sosrecords.setLongitude(lon);

            }
        }
    };


    private void showOptionDialog() {
        String[] officers = {"Police", "Hospital", "Bomba"};
        AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
        builder.setTitle("Choose SOS types");
        builder.setSingleChoiceItems(officers, 0, new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                selectedOfficer = officers[which];
            }
        });
        builder.setPositiveButton("Proceed", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                sosrecords.setCallFor(selectedOfficer);{
                    onStart();
                    startclicked= false;
                    //GET ALL INFORMATION FROM FIRESTORE AND SEND TO REALTIME DATABASE
                    if(FirebaseAuth.getInstance().getCurrentUser()!= null){
                        DocumentReference df = FirebaseFirestore.getInstance().collection("Users").document(FirebaseAuth.getInstance().getCurrentUser().getUid());
                        df.get().addOnSuccessListener(new OnSuccessListener<DocumentSnapshot>() {
                            @Override
                            public void onSuccess(DocumentSnapshot documentSnapshot) {
                                if(documentSnapshot.getString("FullName")!= null){
                                    String id = reff.push().getKey();
                                    Log.d(TAG, "asdasd"+id);
                                    SosRecords sosRecords = new SosRecords(documentSnapshot.getString("FullName"), (documentSnapshot.getString("PhoneNumber")), (documentSnapshot.getString("UserEmail") ),sosrecords.getLatitude(),sosrecords.getLongitude(),sosrecords.getCallFor() );
                                    reff.child(id).setValue(sosRecords);
                                    sosrecords.setRecordID(id);
                                    btnStartSOS.setEnabled(false);
                                    btnStopSOS.setEnabled(true);
                                    Toast.makeText(MainActivity.this, "You're are now activating SOS request !", Toast.LENGTH_SHORT).show();
                                    LatLonLoop.run();
                                    smf.getMapAsync(new OnMapReadyCallback() {
                                        @Override
                                        public void onMapReady(GoogleMap googleMap) {
                                            LatLng latLng = new LatLng(sosrecords.getLatitude(),sosrecords.getLongitude());
                                            MarkerOptions markerOptions = new MarkerOptions().position(latLng).title("Here");

                                            googleMap.addMarker(markerOptions);
                                            googleMap.animateCamera(CameraUpdateFactory.newLatLngZoom(latLng,15));
                                        }
                                    });

                                }

                            }


                        }).addOnFailureListener(new OnFailureListener() {
                            @Override
                            public void onFailure(@NonNull Exception e) {
                                FirebaseAuth.getInstance().signOut();
                                startActivity(new Intent(getApplicationContext(),Login.class));
                                finish();
                            }
                        });
                    }
                    if(ContextCompat.checkSelfPermission(MainActivity.this,Manifest.permission.ACCESS_FINE_LOCATION)== PackageManager.PERMISSION_GRANTED){
                        checkSettingsAndStartLocationUpdates();
                    }else{
                        askLocationPermission();
                    }


                }
                dialog.dismiss();
            }
        });

My get/set class

package com.example.sossystem;

public class SosRecords {

    String RecordID;
    String FullName;
    String PhoneNumber;
    String EmailAddress;
    Double Latitude;
    Double Longitude;
    String CallFor;


    public SosRecords(){

    }



    public SosRecords(String fullName, String phoneNumber, String userEmail, Double latitude, Double longitude, String callFor) {

        FullName = fullName;
        PhoneNumber = phoneNumber;
        EmailAddress = userEmail;
        Latitude = latitude;
        Longitude = longitude;
        CallFor = callFor;
    }

    public String getRecordID() {
        return RecordID;
    }

    public void setRecordID(String recordID) {
        RecordID = recordID;
    }

    public String getFullName() {
        return FullName;
    }

    public void setFullName(String fullName) {
        FullName = fullName;
    }

    public String getPhoneNumber() {
        return PhoneNumber;
    }

    public void setPhoneNumber(String phoneNumber) {
        PhoneNumber = phoneNumber;
    }

    public String getEmailAddress() {
        return EmailAddress;
    }

    public void setEmailAddress(String emailAddress) {
        EmailAddress = emailAddress;
    }

    public Double getLatitude() {
        return Latitude;
    }

    public void setLatitude(Double latitude) {
        Latitude = latitude;
    }

    public Double getLongitude() {
        return Longitude;
    }

    public void setLongitude(Double longitude) {
        Longitude = longitude;
    }

    public String getCallFor() {
        return CallFor;
    }

    public boolean setCallFor(String callFor) {
        CallFor = callFor;
        return false;
    }
}




Solution

  • The thing is that when you open MainActiity that time onMapReady() called first automatically before LocationCallback. Eventually, it will return null latitude and Longitude.

    However, your problem is that you haven't assigned your map fragment.

    first of all, you need to assign in onLocationResult() below the for loop.

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

    Secondly, remove smf.getMapAsync() from onMapReady().

    Instead of,

    smf.getMapAsync(new OnMapReadyCallback() {
    @Override
    public void onMapReady(GoogleMap googleMap) {
    LatLng latLng = new LatLng(sosrecords.getLatitude() 
                              ,sosrecords.getLongitude());
    MarkerOptions markerOptions = new MarkerOptions(). 
                                  position(latLng).title("Here");
    
    googleMap.addMarker(markerOptions);
                                            
    googleMap.animateCamera(CameraUpdateFactory.newLatLngZoom(latLng,15));
    }
    });
    

    Replace,

    // declare googlemap as a globally
    private GoogleMap mMap;
    mMap.setOnMapClickListener(new GoogleMap.OnMapClickListener() {
    @Override
    public void onMapReady(GoogleMap googleMap) {
    mMap = googleMap;
    LatLng latLng = new LatLng(sosrecords.getLatitude() 
                              ,sosrecords.getLongitude());
    MarkerOptions markerOptions = new MarkerOptions(). 
                                  position(latLng).title("Here");
    
    googleMap.addMarker(markerOptions);
                                            
    googleMap.animateCamera(CameraUpdateFactory.newLatLngZoom(latLng,15));
    }
    });