I am getting coordinates with FusedLocationProviderClient in my application on a button click to store into a database. The issue is that when I reboot the phone or the emulator the .getLastLocation() is null and I have to click another time the button i order for this to work. Is there a way to force to get a current position if the value of location from .lastKnownPosition() is null?
// Google fused location client for GPS position
private FusedLocationProviderClient flpc;
// Vars to store GPS info
public Double latitude, longitude;
public Float accuracy;
// Google Fused Client for location
public void getLocation() {
// FusedLocationProviderClient
flpc = LocationServices.getFusedLocationProviderClient(context);
if (ActivityCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(context, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
......
return;
}
// Get the latest position from device
Task<Location> task = flpc.getLastLocation();
task.addOnSuccessListener(new OnSuccessListener<Location>() {
#Override
public void onSuccess(Location location) {
if(location!=null) {
latitude = location.getLatitude();
longitude = location.getLongitude();
accuracy = location.getAccuracy();
}
}
});
}
In my button handler I call getLocation() and use latitude, longitude and accuracy to store to the database.
Any help appreciated!
When getLastLocation() is null, you need to make a LocationRequest
private LocationRequest locationRequest;
private LocationCallback locationCallback;
...
locationRequest = LocationRequest.create();
locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
locationRequest.setInterval(20 * 1000);
locationCallback = new LocationCallback() {
#Override
public void onLocationResult(LocationResult locationResult) {
if (locationResult == null) {
return;
}
for (Location location : locationResult.getLocations()) {
if (location != null) {
wayLatitude = location.getLatitude();
wayLongitude = location.getLongitude();
txtLocation.setText(String.format(Locale.US, "%s -- %s", wayLatitude, wayLongitude));
}
}
}
};
mFusedLocationClient.requestLocationUpdates(locationRequest, locationCallback, Looper.getMainLooper())
If you don't need continuous updates, you can remove the request once you've received it.
mFusedLocationClient.removeLocationUpdates(locationCallback);
More info here: https://medium.com/#droidbyme/get-current-location-using-fusedlocationproviderclient-in-android-cb7ebf5ab88e
When the phone is rebooted the cached last location is lost so if you didnt open up an app that uses GPS like google maps or something then there will be no last location.
There never has to be a location returned to you, you should always assume it could be null.
If you want to get location, you just need to use LocationCallback as #tenprint said in this thread.
Refer this links
Android get location is null after phone reboot
Related
I am trying to get an exact GPS location on the click of a button. I am using the fusesLocationProviderClient and have FINE_LOCATION permission.
private void getCurrentGPSLocation() {
// get the new location from the fused client
// update the UI - i.e. set all properties in their associated text view items
//Initialize new location request
LocationRequest locationRequest = new LocationRequest()
.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY)
.setInterval(10000)
.setFastestInterval(1000)
.setNumUpdates(1);
//Initialize location call back
LocationCallback locationCallback = new LocationCallback() {
#Override
public void onLocationResult(LocationResult locationResult) {
//Initialize location1
Location location1 = locationResult.getLastLocation();
//Set Accuracy
double accura1 = location1.getAccuracy();}
};
//Request location updates
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
return;
}
fusedLocationProviderClient.requestLocationUpdates(locationRequest
, locationCallback, Looper.myLooper());
}
Then I am getting the coordinates from the location1 variable as I am getting accuracy from it. The problem is that this is very unprecise as I am getting an accuracy of 800-1000m. After having opened GoogleMaps for a few seconds and then returning to my app calling getLastLocation(); with another button (not part of my code sample), I am getting an accuracy of 4-5m. When using my code again the accuracy again is 800-1000m.
So my question is, how I can change my code to get this kind of accuracy into my getCurrentGLSLpcation() method.
i am using this code to get location, using FusedLocationProviderClient and its giving almost accurate location upto 5..7 meters
try {
Task<Location> locationResult = mFusedLocationClient.getLastLocation();
locationResult.addOnCompleteListener(this, new OnCompleteListener<Location>() {
#Override
public void onComplete(#NonNull Task<Location> task) {
if (task.isSuccessful()) {
Location location = task.getResult();
if (location != null) {
//fo your job
} else {
Toast.makeText(context, "Please on GPS", Toast.LENGTH_SHORT).show();
}
}
else {
Toast.makeText(context, "error:"+task.getException().getMessage(), Toast.LENGTH_SHORT).show();
}
}
});
} catch (SecurityException e) {
Log.e("Exception: %s", e.getMessage(), e);
}
I have found a solution for it after having tried your ideas:
private void getCurrentGPSLocation() {
// get the new location from the fused client
// update the UI - i.e. set all properties in their associated text view items
//Initialize new location request
LocationRequest locationRequest = new LocationRequest()
.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY)
.setInterval(2500)
.setFastestInterval(2000)
.setNumUpdates(8);
//Initialize location call back
LocationCallback locationCallback = new LocationCallback() {
#Override
public void onLocationResult(LocationResult locationResult) {
//Initialize location1
Location location1 = locationResult.getLastLocation();
//Set latitude
tvLatitude.setText(String.valueOf(location1.getLatitude()));
//Set longitude
tvLongitude.setText(String.valueOf(location1.getLongitude()));
//Set Accuracy
double accura1 = location1.getAccuracy();
tvAccuracy.setText(new DecimalFormat("##.##").format(accura1) + " m");
//Set Altitude
double altit1 = location1.getAltitude();
tvAltitude.setText(new DecimalFormat("##.##").format(altit1) + " m");
//Get Adress
double longitude1 = location1.getLongitude();
double latitude1 = location1.getLatitude();
Geocoder geocoder = new Geocoder(getApplicationContext(), Locale.getDefault());
try {
List<Address> listAddresses = geocoder.getFromLocation(latitude1, longitude1, 1);
if (null != listAddresses && listAddresses.size() > 0) {
String _Location1 = listAddresses.get(0).getAddressLine(0);
//Set Location
tvLocation.setText(String.valueOf(_Location1));
}
} catch (IOException e) {
e.printStackTrace();
}
//Set Update Time
TextView textView = findViewById(R.id.tv_update);
SimpleDateFormat sdf = new SimpleDateFormat("dd.MM.yyyy 'um ' HH:mm:ss z");
String currentDateandTime = sdf.format(new Date());
textView.setText(currentDateandTime);
}
};
//Call method to insert data into database
(new Handler()).postDelayed(this::OnReg, 30000);
//OnReg();
//Call Method to save data in SharedPreferences
(new Handler()).postDelayed(this::saveData, 30000);
//saveData();
//call Method to save data in Internal File
(new Handler()).postDelayed(this::saveToFile, 30000);
//saveToFile();
//Request location updates
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
return;
}
fusedLocationProviderClient.requestLocationUpdates(locationRequest
, locationCallback, Looper.myLooper());
}
So this is the complete code with the textviews being updated from the location. Basically I have 8 location updates before taking the last and therefore most precise location to call my methods which save the location in a database (OnReg), an internal file (saveToFile) and the SharedPreferences(saveData). These methods are called with a delay of 30 seconds to make sure the location is accurate.
We are using FusedLocationProviderClient to fetch GPS location continuously in our app. We find that the location provided is slightly off (about 200mtrs) and delayed by about 15-20secs. This causes problems while driving.
The code snippet is below. Please let me know what we might be doing wrong, appreciate your help to fix this. If there is a better method to fetch location continuously, please suggest that as well.
mFusedLocationClient = LocationServices.getFusedLocationProviderClient(context);
locationRequest = LocationRequest.create();
locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
locationRequest.setInterval(500);
locationCallback = new LocationCallback() {
#Override
public void onLocationResult(LocationResult locationResult) {
if (locationResult == null) {
return;
}
Location location = locationResult.getLocations().get(locationResult.getLocations().size() - 1);
if (location != null) {
currLatFusedLoc = location.getLatitude();
currLngFusedLoc = location.getLongitude();
}
};
};
mFusedLocationClient.requestLocationUpdates(locationRequest, locationCallback, Looper.myLooper());
I started using FusedLocationClient and I'm not sure why would I need both an OnSuccessListener and a LocationCallback. Shouldn't just one of these suffice?
private void initLocationCallback(Context context) {
fusedLocationClient = LocationServices.getFusedLocationProviderClient(context);
fusedLocationClient.getLastLocation()
.addOnSuccessListener(new OnSuccessListener<Location>() {
#Override
public void onSuccess(Location location) {
onLocationChanged(location);
}
});
locationCallback = new LocationCallback() {
#Override
public void onLocationResult(LocationResult locationResult) {
if (locationResult != null) {
for (Location location : locationResult.getLocations()) {
if (location != null) {
onLocationChanged(location);
}
}
}
}
};
LocationRequest locationRequest = LocationRequest.create();
locationRequest.setInterval(INTERVAL);
locationRequest.setFastestInterval(FASTEST_INTERVAL);
fusedLocationClient.requestLocationUpdates(locationRequest, locationCallback, context.getMainLooper());
}
private void onLocationChanged(Location location) {
// use location...
}
According to documentation when getting lastKnownLocation(), OnSuccessListener should be enough also in rare cases Location might be null.
Personalty I am also using OnSuccessListener()
If you are not interested in the user's exact location at this precise moment, then lastKnownLocation() and OnSuccessListener would suffice and you don't need a LocationCallback.
But if you want precise location and want regular updates in case the user is on the move, then you need to implement the LocationCallback to keep getting location updates. In this case, you would typically want the last known location as getting a location update might take some time.
Hello everyone I am developing two apps one for Admin and second for its employees. Now i want to track the employee device using this app the location is send to server when location of employee device changed.Location is send only when location changed. how i can send location of device to server when location is changed??
second i want to show the location of employee on admin app map as it is changing its location.(May i send Location co ordinates from server to admin app through GCM or any other technique?)
Hey, down voters can you explain what is wrong in this question? If you have a Answer to the question the give otherwise try to understand the questions.
please help
Thanks in advance..
public LatLng getLocation()
{
// Get the location manager
MyLocationListener myLocListener = new MyLocationListener();
LocationManager locationManager = (LocationManager) getSystemService(LOCATION_SERVICE);
Criteria criteria = new Criteria();
String bestProvider = locationManager.getBestProvider(criteria, false);
Location location = locationManager.getLastKnownLocation(bestProvider);
locationManager.requestLocationUpdates(bestProvider,timeAfteryougetUpdate, minDistanceAfterYougetupdate, myLocListener);
Double lat,lon;
try {
lat = location.getLatitude ();
lon = location.getLongitude ();
return new LatLng(lat, lon);
}
catch (NullPointerException e){
e.printStackTrace();
return null;
}
}
**Use this to get location **
private class MyLocationListener implements LocationListener
{
#Override
public void onLocationChanged(Location loc)
{
if (loc != null)
{
// Do something knowing the location changed by the distance you requested
methodThatDoesSomethingWithNewLocation(loc);
}
}
#Override
public void onProviderDisabled(String arg0)
{
// Do something here if you would like to know when the provider is disabled by the user
}
#Override
public void onProviderEnabled(String arg0)
{
// Do something here if you would like to know when the provider is enabled by the user
}
#Override
public void onStatusChanged(String arg0, int arg1, Bundle arg2)
{
// Do something here if you would like to know when the provider status changes
}
}
you can implement locationListener with service, you can req api from server and send data in any of form, json, xml and once you got the co-ordinates you can show them to the map.
LocationListener
android-location-based-services-example
Hope these can help you.
I know my response is a little bit late.
I will explain my answer using google maps services and firebase real-time database and Geo-Fire for easy location uploading to the cloud database.
Get the real-time location -
#Override public void onMapReady(GoogleMap googleMap) {
mMap = googleMap;
locationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);
if (ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED &&
ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
// add the code to get the permission
return;
}
buildGoogleApiClient();
mMap.setMyLocationEnabled(true);
}
protected synchronized void buildGoogleApiClient(){
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
mGoogleApiClient.connect();
}
#Override public void onConnected(#Nullable Bundle bundle) {
mLocationRequest = new LocationRequest();
mLocationRequest.setPriority(LocationRequest.PRIORITY_LOW_POWER);
if (ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
return;
}
LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);
}
#Override public void onLocationChanged(Location location) {
if(getApplicationContext() != null) {
mlasLocation = location;
LatLng latLng = new LatLng(location.getLatitude(), location.getLongitude()); // plot the realtime location on the map
mMap.moveCamera(CameraUpdateFactory.newLatLng(latLng));
mMap.animateCamera(CameraUpdateFactory.zoomTo(11));
addToDataBase(latLng);
}
}
Adding the real-time location to the cloud database using Geo-Fire
public void addtoDataBase(LatLng location){
//unique name work like a promary key
String uid = "119-userID";
final DatabaseReference databaseReference = FirebaseDatabase.getInstance().getReference("SOSRequests");
GeoFire geoFire = new GeoFire(databaseReference);
geoFire.setLocation(uid, new GeoLocation(location.latitude, location.longitude));
}
I want to get the Location object on Button press.
I know the LocationListener callbacks, however they execute only after a particular time or distance. I want to get Location instantaneously. Are there any methods to do so.
public class GPSHelper {
private Context context;
// flag for GPS Status
private boolean isGPSEnabled = false;
// flag for network status
private boolean isNetworkEnabled = false;
private LocationManager locationManager;
private Location location;
private double latitude;
private double longitude;
public GPSHelper(Context context) {
this.context = context;
locationManager = (LocationManager) context
.getSystemService(Context.LOCATION_SERVICE);
} public void getMyLocation() {
List<String> providers = locationManager.getProviders(true);
Location l = null;
for (int i = 0; i < providers.size(); i++) {
l = locationManager.getLastKnownLocation(providers.get(i));
if (l != null)
break;
}
if (l != null) {
latitude = l.getLatitude();
longitude = l.getLongitude();
}
}
public boolean isGPSenabled() {
isGPSEnabled = locationManager
.isProviderEnabled(LocationManager.GPS_PROVIDER);
// getting network status
isNetworkEnabled = locationManager
.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
return (isGPSEnabled || isNetworkEnabled);
}
/**
* Function to get latitude
*/
public double getLatitude() {
return latitude;
}
/**
* Function to get longitude
*/
public double getLongitude() {
return longitude;
}
You are welcome to call getLastKnownLocation() on LocationManager to retrieve the last known location for your requested location provider. However:
that location may be old
that location may be null
Hence, your code will need to be able to cope with both of those scenarios.
Use LocationManager class:
locationManager = (LocationManager)this.getSystemService(LOCATION_SERVICE);
location = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
if (location != null) {
latitude=location.getLatitude();
longitude=location.getLongitude();
Log.d("old","lat : "+latitude);
Log.d("old","long : "+longitude);
this.onLocationChanged(location);
}
Try the following:
https://github.com/delight-im/Android-SimpleLocation
If your location is enabled, you need just 3 lines of code:
SimpleLocation location = new SimpleLocation(this); //or context instead of this
double latitude = location.getLatitude();
double longitude = location.getLongitude();
You can get the last known location using FusedLocationProviderClient
There are very simple steps to get current latitude, longitude, altitude & bearing
Update or install Google Play services to the current latest version in your SDK Manager.
Add Location permission into your project's manifest.
Add this line into your Activity/Fragment:
(i) Code For Kotlin
private lateinit var fusedLocationClient: FusedLocationProviderClient
fusedLocationClient = LocationServices.getFusedLocationProviderClient(this)
fusedLocationClient.lastLocation
.addOnSuccessListener { location: Location? ->
Log.d(TAG, "latitude:" + location?.latitude)
Log.d(TAG, "longitude:" + location?.longitude)
Log.d(TAG, "altitude:" + location?.altitude)
Log.d(TAG, "bearing:" + location?.bearing)
}
(ii) Code for JAVA
private FusedLocationProviderClient fusedLocationClient;
fusedLocationClient = LocationServices.getFusedLocationProviderClient(this);
fusedLocationClient.getLastLocation()
.addOnSuccessListener(this, new OnSuccessListener<Location>() {
#Override
public void onSuccess(Location location) {
if (location != null) {
Log.d(TAG,location.getLatitude)
Log.d(TAG,location.getLongitude)
}
}
});
That's it. Run your code and you can check your current location in Logcat. Don't forget to accept location permission from your emulator or Android phone.
You can not get proper altitude and bearing using FusedLocationProviderClient.
Happy Coding :)