getLatitude and getLongitude throws NullPointerException [duplicate] - java

This question already has answers here:
What is a NullPointerException, and how do I fix it?
(12 answers)
Closed 3 years ago.
Would you please explain me why getLongitude and getLatitude returns a NullPointerException?
The truth is the problem already has been solved, but there's one thing that is bugging me for this might be asked by our thesis coordinator. The situation is that I have to get the user's current coordinates (latitude and longitude). I've decided to use FusedLocationClient.getLastLocation() in order to get the coordinates.
mFusedLocationClient = getFusedLocationProviderClient(this);
//app already crashes once the line below is executed
mFusedLocationClient.getLastLocation().addOnSuccessListener(this, new OnSuccessListener<Location>() {
#Override
public void onSuccess(Location location) {
if(location != null){
//myLocation is an instance variable of this class
myLocation = location;
}else{
Toast.makeText(PlaceCategoriesActivity.this, "Location fetch failed!", Toast.LENGTH_SHORT).show();
}
}
});
latitude = myLocation.getLatitude(); //this line throws NullPointerException
longitude = myLocation.getLongitude();
The app seems to compile fine but then it crashes, upon inspecting by adding a breakpoint for debugging on myLocation.getLatiude() and myLocation.getLongititude(), it turns out that this method invokes a null pointer exception, which for me is weird because myLocation already has referenced the location object brought by the onSuccess method of the addOnSuccessListener.
I've already solved the problem by moving the last two lines of code and putting in within the listener like this:
mFusedLocationClient = getFusedLocationProviderClient(this);
mFusedLocationClient.getLastLocation().addOnSuccessListener(this, new OnSuccessListener<Location>() {
#Override
public void onSuccess(Location location) {
if(location != null){
myLocation = location;
//moved the 2 lines of code and it now works
latitude = myLocation.getLatitude();
longitude = myLocation.getLongitude();
}else{
Toast.makeText(PlaceCategoriesActivity.this, "Location fetch failed!", Toast.LENGTH_SHORT).show();
}
}
});
//Toast returns a value of 0 on latitude and 0 on longitude
Toast.makeText(this, "Lat: " + latitude + "Long: + " + longitude, Toast.LENGTH_SHORT).show();
The funny thing is that the longitude and latitude is shown on the Toast and both has a value of 0.

which for me is weird because myLocation already has referenced the location object brought by the onSuccess method of the addOnSuccessListener
Let's simplify your first code listing:
mFusedLocationClient = getFusedLocationProviderClient(this);
latitude = myLocation.getLatitude(); //this line throws NullPointerException
longitude = myLocation.getLongitude();
Here, myLocation has not been assigned a value. If you have not assigned a value to myLocation in preceding lines, myLocation will be null, and you will get a NullPointerException.
Now, let's restore some lines to that code snippet:
mFusedLocationClient = getFusedLocationProviderClient(this);
//app already crashes once the line below is executed
mFusedLocationClient.getLastLocation().addOnSuccessListener(this, new OnSuccessListener<Location>() {
#Override
public void onSuccess(Location location) {
}
});
latitude = myLocation.getLatitude(); //this line throws NullPointerException
longitude = myLocation.getLongitude();
The last word in addOnSuccessListener() is "listener". This suggests that you are registering an event listener. Usually — though not always — such a listener is only invoked on future events. It is likely that onSuccess() will not be called until sometime later. However, your program keeps running, and you then try calling getLatitude() on myLocation. Since we still have not done anything to assign a value to myLocation, it will be null, and you will crash with a NullPointerException.
And so while your first code snippet does assign a value to myLocation, you as a programmer have to assume that it will not do so until some time in the future (e.g., when we get a new location fix). Do not attempt to use myLocation until onSuccess() has assigned it a value.

you should not add these lines after addOnSuccessListener:
latitude = myLocation.getLatitude(); //this line throws NullPointerException
longitude = myLocation.getLongitude();
because you have to wait until mFusedLocationClient successfully gets LastLocation
i.e. move these lines into onSuccess method!
As for the reason of the nullPointerException it's because myLocation has not yet been initialized !

You simply need to display the location when you get it, not before. That's said, just put the display code in the listener.
mFusedLocationClient = getFusedLocationProviderClient(this);
// Register a listener, that will be called when the location will be available
mFusedLocationClient.getLastLocation().addOnSuccessListener(this, new OnSuccessListener<Location>() {
#Override
public void onSuccess(Location location) {
if (location != null) {
// We have a location!
myLocation = location;
// So print it now
latitude = myLocation.getLatitude();
longitude = myLocation.getLongitude();
Toast.makeText(PlaceCategoriesActivity.this, "Lat: " + latitude + "Long: + " + longitude, Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(PlaceCategoriesActivity.this, "Location fetch failed!", Toast.LENGTH_SHORT).show();
}
}
});
// Loading, as we wait for listener to be called
Toast.makeText(this, "Loading...", Toast.LENGTH_SHORT).show();

Example:
class LocationApi : Service(), GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener, LocationListener {
private var myGoogleApiClient: GoogleApiClient? = null
private val myLocationRequest = LocationRequest.create()
override fun onBind(intent: Intent?): IBinder? {
return null
}
override fun onCreate() {
super.onCreate()
myGoogleApiClient = GoogleApiClient.Builder(this)
.addApi(LocationServices.API)
.addOnConnectionFailedListener(this)
.addConnectionCallbacks(this)
.build()
}
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
myGoogleApiClient?.connect()
return super.onStartCommand(intent, flags, startId)
}
override fun onDestroy() {
myGoogleApiClient?.disconnect()
if (myGoogleApiClient != null && myGoogleApiClient?.isConnected!!) {
LocationServices.getFusedLocationProviderClient(this).removeLocationUpdates(locationCallBack)
}
super.onDestroy()
}
override fun onConnected(bundle: Bundle?) {
//here u can define your interval and priority
// request locations, check permissions ok
if (ContextCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
LocationServices.getFusedLocationProviderClient(this).requestLocationUpdates(myLocationRequest, locationCallBack, Looper.myLooper())
}
}
override fun onConnectionSuspended(p0: Int) {
}
override fun onConnectionFailed(p0: ConnectionResult) {
}
override fun onLocationChanged(location: Location?) {
//saving location on DB
LocationInteractor(location)
}
private val locationCallBack = object : LocationCallback() {
override fun onLocationResult(location: LocationResult) {
super.onLocationResult(location)
onLocationChanged(location.lastLocation)
}
}
}

Related

Getting location when the app is closed using fusedLocationProviderClient

I am currently working on a location-based reminder app.
Obviously, the should send a notification when the user is close to a location he set.
For that, I am using a foreground service - which starts when the app starts. It also works when the app is closed, like swiped up from the apps list (not force stopped).
In the service, I am getting the current location and iterating over the location to see which ones I should send a notification for.
Every thing works fine, but for some reason, when the app is closed, the service doesn't enter the onLocationResult:
LocationServices.getFusedLocationProviderClient
(ServiceLocationNotification.this).requestLocationUpdates(locationRequest, new LocationCallback() {
#Override
public void onLocationResult(#NonNull LocationResult locationResult) {
GetCurrentLocationAsyncTaskServiceLocationNotification task =
new GetCurrentLocationAsyncTaskServiceLocationNotification
(ServiceLocationNotification.this,
locationResult,
this);
try
{
currentLatLng = task.execute().get();
}
catch (Exception e)
{
System.out.println("Exception");
e.printStackTrace();
}
}
},
Looper.getMainLooper()); // Use the main thread's looper to receive location updates
(I checked with prints).
GetCurrentLocationAsyncTaskServiceLocationNotification (sorry for the long name) is a class i created to retrieve the current location and get the latLng out of it:
// for the ServiceLocationNotification class.
public class GetCurrentLocationAsyncTaskServiceLocationNotification extends AsyncTask<Void, Void, LatLng>
{
private WeakReference<ServiceLocationNotification> ServiceLocationNotificationWeakReference;
private LocationCallback locationCallback;
private LocationResult locationResult;
GetCurrentLocationAsyncTaskServiceLocationNotification(ServiceLocationNotification activity,
#NonNull LocationResult locationResult,
LocationCallback locationCallback)
{
ServiceLocationNotificationWeakReference = new WeakReference<>(activity);
this.locationResult = locationResult;
this.locationCallback = locationCallback;
}
// .execute().get() gets the return value.
#Override
protected LatLng doInBackground(Void... voids)
{
double latitude;
double longitude;
// get location
LocationServices.getFusedLocationProviderClient(ServiceLocationNotificationWeakReference.get())
.removeLocationUpdates(locationCallback);
// Check if the location result is not null and has at least one location
if (locationResult != null && locationResult.getLocations().size() > 0)
{
// Get the most recent location from the location result
int index = locationResult.getLocations().size() - 1;
latitude = locationResult.getLocations().get(index).getLatitude();
longitude = locationResult.getLocations().get(index).getLongitude();
return new LatLng(latitude, longitude);
}
return null;
}
}
I would appreciate any help understanding why this happens (not entering the onLocationResult function).
Thanks!

How can I cat latitude and longitude of Android device?

So I'm making this app which finds restaurants near you, fetching information from a food-delivery app, using JSoup library.
The only problem with it is that sometimes the latitude and the longitude are getting null value.
Situations in which my application is working:
-turning on GPS and the waiting at least 1-2 minutes;
-opening google maps, closing it, and then returning to the application;
So the main problem: I can't fetch the location right after I enable it and hit the 'Find restaurants' button, I need to wait 1-2 minutes after enabling location, then it's working.
private TextView result;
private FusedLocationProviderClient client;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
requestPermission();
client = LocationServices.getFusedLocationProviderClient(this);
getBtn = findViewById(R.id.getRestaurants);
result = findViewById(R.id.restaurantsList);
getBtn.setOnClickListener(this);
}
private void requestPermission(){
ActivityCompat.requestPermissions(this, new String[]{ACCESS_FINE_LOCATION}, 1 );
}
public void onClick(View v) {
if (ActivityCompat.checkSelfPermission(MainActivity.this, ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED){
return;
}
client.getLastLocation().addOnSuccessListener(MainActivity.this, new OnSuccessListener<Location>() {
#Override
public void onSuccess(Location location) {
result.setText("Getting location...");
if(location != null){
double latitude = getLat(location);
double longitude = getLng(location);
result.setText("Finding restaurants near you...");
getWebsite(latitude, longitude);
}else{
result.setText("Couldn't fetch location!");
}
}
});
Here is a good way to implement the FusedLocationProvider in Kotlin (you might adapt to Java or use Java and Kotlin side by side) :
private fun startLoc() {
fusedLocationClient = LocationServices.getFusedLocationProviderClient(this)
try {
fusedLocationClient.lastLocation
.addOnSuccessListener { location: Location? ->
//showDialog(this#MapsActivity, TAG, "last know loc = ${location?.latitude} + ${location?.longitude}")
if (location != null){
lastKnowLoc = LatLng(location.latitude, location.longitude)
addMarkerToLocation(lastKnowLoc)
}
}
val locationRequest = LocationRequest()
locationRequest.interval = 10000
locationRequest.fastestInterval = 10000
locationRequest.priority = LocationRequest.PRIORITY_HIGH_ACCURACY
locationCallback = object : LocationCallback() {
override fun onLocationResult(locationResult: LocationResult?) {
locationResult ?: return
for (location in locationResult.locations){
//showDialog(this#MapsActivity, "locationResult", "location=${location.latitude};${location.longitude}")
addMarkerToLocation(LatLng(location.latitude, location.longitude))
val speed = location.speed
updateCamera(location.bearing)
}
}
}
fusedLocationClient.requestLocationUpdates(locationRequest, locationCallback, null)
btnStartLoc.isEnabled = false
btnStopLoc.isEnabled = true
}catch (e:SecurityException){}
}
you must use requestLocationUpdates()
you are using getLastLocation() and when the GPS is off and turned on after the last known location becomes null so you must call requestLocationUpdates()
you can find more information in the below link
https://developer.android.com/training/location/receive-location-updates

Why my app doesn't show location button when I accept the permission request dialog the second time is runned?

I am programming an Android App in Java. The activity holds a Google map and what I want is to have a button location at the top, like is shown in the picture:
I want that when I click the location to point to my current Location and for that I am using the class FusedLocationProviderClient.
When I run the program everything goes fine until i follow these steps sequencially:
1- Run app first time and I deny permissions
2- Run app second time. It request again permissions so I answer ok, but the button doesn't appear.
3- I close the app, and because I said yes last time, to the location permission, the button is on the map and is working.
Here is my code:
private void checkPermissions(int fineLocationPermission) {
if (fineLocationPermission != PackageManager.PERMISSION_GRANTED) { //If we don't have any permissions yet
// TODO: Consider calling
//We have to request permissions and in case the user refuse the permission we show an explanation of why he needs the permission
//The following method returns true in case the user reject the permission
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
PERMISSION_REQUEST_CODE);
} else
mLocationPermissionGranted=true;
}
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
switch (requestCode) {
case PERMISSION_REQUEST_CODE:
// If request is cancelled, the result arrays are empty.
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
//If the user accepts the dialog box then we get the last location and show button
mLocationPermissionGranted=true;
} else {
mLocationPermissionGranted=false;
// permission denied, boo! Disable the
// functionality that depends on this permission.
Toast.makeText(this, "permission denied", Toast.LENGTH_LONG).show();
}
}
}
public void onLocationChanged(final Location location) {
String msg = "Updated location: " +
Double.toString(location.getLatitude()) + ", " +
Double.toString(location.getLongitude());
Toast.makeText(this, msg, Toast.LENGTH_SHORT).show();
final LatLng latLng = new LatLng(location.getLatitude(), location.getLongitude());
//Show button to locate current position
mMap.setOnMyLocationButtonClickListener(new GoogleMap.OnMyLocationButtonClickListener() {
#Override
public boolean onMyLocationButtonClick() {
mMap.moveCamera(CameraUpdateFactory.newLatLng(latLng));
CameraUpdateFactory.newLatLngZoom(latLng,12);
//mMap.setMaxZoomPreference(12);
return false;
}
});
// Add a marker our current position
LatLng CurrentPosition = new LatLng(location.getLatitude(), location.getLongitude());
mMap.addMarker(new MarkerOptions().position(CurrentPosition).title("Here you are!"));
mMap.moveCamera(CameraUpdateFactory.newLatLng(CurrentPosition));
}
#Override
public void onMapReady(GoogleMap googleMap) {
//Create the map
mMap = googleMap;
//Set the type of the map: HYBRID, NORMAL, SATELLITE or TERRAIN. In our case TERRAIN type
mMap.setMapType(GoogleMap.MAP_TYPE_TERRAIN);
//Set the zoom
mMap.setMaxZoomPreference(12);
//Set the markers
MarkerOptions markerOptions= new MarkerOptions();
//Checking permissions with the permissions we have included in the manifiest
checkPermissions(permissionCheckFineLocation);
if (mLocationPermissionGranted) {
try {
mMap.setMyLocationEnabled(true);
//Last location task
Task<Location> locationResult = mFusedLocationClient.getLastLocation();
locationResult.addOnSuccessListener(this, new OnSuccessListener<Location>() {
#Override
public void onSuccess(Location location) {
//Got last known location. In some rare situations this can be null
if (location != null) {
//Logic to handle location object
onLocationChanged(location);
}
}
});
} catch (SecurityException e) {
Log.e("error", e.getMessage());
}
}
}
I know is a weird question, but I don't know how to express myself.
Any help would be great!
Thank you in advance!
onMapReady isn't called (again) after permission is granted (this happens after onMapReady).
Move the code in onMapReady in the if (mLocationPermissionGranted) clause to a separate method and call it from inside the if as well as from onRequestPermissionsResult if permission was granted.

Using mFusedLocationClient to get current location within a firebase service

I'm new to java/android dev so my code may be dumb.
I have a website which uses google maps, I have a button on the website which sends a push cURL message to a specific device using firebase. I want the device to then get the current location and update my database.
I'm using MyFirebaseMessagingService and onMessageReceived to grab the cURL message and that all works fine, it breaks when I start going into the location code. I had various errors so I tried creating a class for getting the location then calling a method of that class within my service.
The class:
public class LocationMedium {
private FusedLocationProviderClient mFusedLocationClient;
private Context mContext;
public LocationMedium(Context context) {
mContext=context;
}
public void getLocation()
{
mFusedLocationClient = LocationServices.getFusedLocationProviderClient(mContext);
if (ActivityCompat.checkSelfPermission(mContext, android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(mContext, android.Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
//currently pointless
//return;
}
mFusedLocationClient.getLastLocation()
.addOnSuccessListener((Activity)mContext, new OnSuccessListener<Location>() {
#Override
public void onSuccess(Location location) {
Log.d("mytag", "2222");
// Got last known location. In some rare situations this can be null.
if (location != null) {
// Logic to handle location object
double x = location.getLatitude();
double y = location.getLongitude();
Log.d("mytag1", String.valueOf(x));
Log.d("mytag2", String.valueOf(y));
String user = PreferenceManager.getDefaultSharedPreferences(mContext).getString("USERNAME", "none");
MyFirebaseInstanceIDService firebase = new MyFirebaseInstanceIDService();
firebase.onDeadline(user, x, y);
} else //no location found
{
String user = PreferenceManager.getDefaultSharedPreferences(mContext).getString("USERNAME", "none");
MyFirebaseInstanceIDService firebase = new MyFirebaseInstanceIDService();
firebase.onDeadline(user, 0, 0);
Log.d("mytag", "hmm");
}
}
});
//END OF LOCATION
Log.d("mytag", "theend");
}//end of run
}
And I call it with this from the MyFirebaseMessagingService
if (Objects.equals(user, " location ")) {
Handler handler = new Handler(Looper.getMainLooper());
handler.post(new Runnable() {
public void run() {
LocationMedium task = new LocationMedium(context);
task.getLocation();
}
});
}
The error with this I get is:
MyFirebaseMessagingService cannot be cast to android.app.Activity
And it appears to be on this line:
mFusedLocationClient.getLastLocation()
I tried removing the (Activity) bit from:
.addOnSuccessListener((Activity) mContext, new OnSuccessListener<Location>()
and changing it to:
.addOnSuccessListener(mContext, new OnSuccessListener<Location>()
but then I get the error:
Cannot resolve method 'addOnSuccessListener...'
Perhaps I'm going about this completely the wrong way. Any help/suggestions would be appreciated. Thanks.
.addOnSuccessListener(mContext, new OnSuccessListener<Location>()
Replace the above code with this,
.addOnSuccessListener(new OnSuccessListener<Location>()
Worked for me.

Location returns NULL

I am writing an Android app that returns longitude and latitude, however location holds a Null value.
Please see if you can see why, Its been bugging me all day. Code below:
public class example extends Activity {
public static double latitude;
public static double longitude;
LocationManager lm;
LocationListener ll;
Location location;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.questions);
lm = (LocationManager)getSystemService(Context.LOCATION_SERVICE);
ll = new MyLocationListener();
lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, ll);
//location = lm.getLastKnownLocation(lm.getBestProvider(criteria, true));
Button b = (Button) findViewById(R.id.button2);
b.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View arg0) {
String provider = Settings.Secure.getString(getContentResolver(), Settings.Secure.LOCATION_PROVIDERS_ALLOWED);
int index1 = provider.indexOf("gps");
if(index1 < 0)
// gps not enabled, call msgbox
showMsgBox("GPS is off", "GPS is off. Turn it on?", "Turn on");
else
areWeThereYet(); }});
}
private void areWeThereYet()
{
if(weAreThere())
{
toastMsg("in correct place");
}
else if(location!=null)
toastMsg("not there yet");
}
private boolean weAreThere() {
location = lm.getLastKnownLocation(LocationManager.GPS_PROVIDER);
if (location!=null)
{
longitude = location.getLongitude();
latitude = location.getLatitude();
toastMsg(latitude + " " + longitude);
return inCorrectPlace(question);
}
else
{
toastMsg("Location not ready yet");
return false;
}
}
private void toastMsg(String msg) {
Toast toast = Toast.makeText(this, msg, 2000);
toast.setGravity(Gravity.BOTTOM, 0, 0);
toast.show();
}
}
If the GPS has not ever gotten a location since the device was booted, the location object will be null. One thing you can do is attempt to get a GPS location and a network location, and check to two to see if either of them are good (or which one is better) and use that location.
If you're using the emulator, then see here for advice on setting up the emulator to provide a location. If you're testing it on your device, it may be because you've never had a gps location on it. Try using the Google maps application before testing your app.

Categories

Resources