How to get the most accurate geo-location on an android device, I tried following code snippet But on Nexus 4 and 10, it doesn't work even after the gps is turned on :
LocationManager locationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
String locationProvider = locationManager.getBestProvider(new Criteria(), true);
if (locationProvider != null) {
//Log.d(TAG, "locationProvider is not null");
Location lastKnownLocation = locationManager.getLastKnownLocation(locationProvider);
if (lastKnownLocation != null) {
AppConstants.lat = latLon[0] = lastKnownLocation.getLatitude();
AppConstants.lon = latLon[1] = lastKnownLocation.getLongitude();
retryGenerating = false;
//Log.d(TAG, "lastKnownLocation, lat = " + AppConstants.lat + ", lon = " + AppConstants.lon);
}
}
The most accurate location you get by explicitly setting the LocationProvider to GPS Provider. Expect usually 3-6m accuracy, up to 30m in urban canyons.
You need to to be outside and have free view to sky.
Expect a delay of 20-40 s for the first valid location after going outside.
Related
in out app we have a module where you can send time records with GPS location.
In 40% of cases we have location problem because the module provides a location which is not real (sometime about 1 km away).
When we have this cases we open Google Maps app and it give us perfect location, then again out app and not-real location.
For getting the location we use this:
Slider s1 = new Slider();
Dialog dlg = makeDialog("HIGH PRECISION LOCATION...", s1, null, 'a');
dlg.addShowListener((ActionListener) e -> {
LocationManager locationManager = LocationManager.getLocationManager();
locationManager.setLocationListener(this, new LocationRequest(LocationRequest.PRIORITY_HIGH_ACCUARCY, 500));
loc = locationManager.getCurrentLocationSync(20000);
dlg.dispose();
if(loc == null) {
Slider s2 = new Slider();
Dialog dlg2 = makeDialog("GETTING LAST KNOWN LOCATION...", s2, "OK", 'a');
dlg2.addShowListener((ActionListener) e2 -> {
loc = locationManager.getLastKnownLocation();
if(loc == null) {
// location not found
Dialog.show("Attenzione!", "Posizione non trovata. E' consigliato di spostarsi all'aperto. "
+ "Tuttavia รจ possibile inviare la timbratura anche senza coordinate.", "Ok", null);
} else {
paintLocation(loc, GPSStateOn);
}
});
dlg2.show();
} else {
paintLocation(loc, GPSStateOn);
}
});
dlg.show();
-
#Override
public void locationUpdated(final Location location) {
switch (LocationManager.getLocationManager().getStatus()) {
case LocationManager.AVAILABLE:
GPSStateOn = true;
break;
case LocationManager.OUT_OF_SERVICE:
GPSStateOn = false;
break;
case LocationManager.TEMPORARILY_UNAVAILABLE:
GPSStateOn = false;
break;
}
if(loc != null) {
paintLocation(loc,GPSStateOn);
System.out.println("-----LATITUDINE: " + loc.getLatitude());
System.out.println("-----LONGITUDINE: " + loc.getLongitude());
}
}
We also have added the buil hint android.playService.location = true
ADDED 25/04/2020 11:58
I forgot to say that about 40% of cases it arrives at "GETTING LAST KNOWN LOCATION..." and then give perfect real location.
Android build hints:
last one is cutted... value is:
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/> <uses-permission android:name="com.google.android.providers.gsf.permission.READ_GSERVICES"/><uses-feature android:glEsVersion="0x00020000" android:required="true"/><uses-permission android:name="android.permission.CAMERA"/><uses-feature android:name="android.hardware.camera" android:required="false"/>
ADDED 06/05/2020 10:48
Maybe this can be useful:
I noticed when the location takes a lot the GPS icon isn't displayed in the topbar
And when it takes less time the GPS icon is visible
Looking again at the code I noticed you used set location listener and getCurrentLocationSync which are mutually exclusive in this case. You need to pick one. If you give the former (which is the preferred way) enough time to work it should give you an accurate location. Notice the GPS position sometimes needs a couple of seconds for the initial reading.
I am currently looking into (existing) solution for iOS under Xamarin. I have a map with following code:
public override async Task<string> ResolveLatLngToAddress(double lat, double lng, MapAddressFormat addressFormat)
{
var geocoder = new CLGeocoder();
try
{
var placemarks = await geocoder.ReverseGeocodeLocationAsync(new CLLocation(lat, lng));
if (placemarks.Length > 0)
{
var placemark = placemarks[0];
switch (addressFormat)
{
case MapAddressFormat.AddressFormatFull:
{
return FormatUtils.Join(true, placemark.Name, placemark.Locality, placemark.SubLocality);
}
case MapAddressFormat.AddressFormatNoNumber:
{
return FormatUtils.Join(true, placemark.Thoroughfare, placemark.Locality, placemark.SubLocality);
}
}
}
}
catch (Foundation.NSErrorException e)
{
// Unable to find a location with the supplied latitude and longitude
}
return null;
}
}
The code works really well when user moves the pin around, there is a textbox control that displays currently selected address. Once the user starts zooming in and out however, the application breaks and the function stops working.
I have done some research and I understand that CLGeocoder class works in a way that if the users starts too many requests, the response slows down and then stops completely (https://developer.apple.com/documentation/corelocation/clgeocoder).
I can see that the problem is that the event is triggered multiple times during the zoom, e.g. zooming in triggers for example 20 requests for location resolution.
I would to trigger the location resolution only after the user finished zooming, is it possible to achieve somehow, for example with delayed binding?
Please note that I am new to both iOS development and Xamarin.
Thank you very much for any help.
thank you for your comments. I have eventually solved it by caching previously queried location and re-querying only if the lat/lng coordinates changed by certain margin which I estimated to be 1 meter (perfectly fine for my purposes).
private double _cached_lat = 999;
private double _cached_lng = 9999;
private string _cached_location = "";
public override async Task<string> ResolveLatLngToAddress(double lat, double lng, MapAddressFormat addressFormat)
{
double latDif = System.Math.Abs(_cached_lat - lat);
double lngDif = System.Math.Abs(_cached_lng - lng);
//precission - around 1m
double geo_precission = 0.000005;
if (((System.Math.Abs (_cached_lat - lat) < geo_precission) && (System.Math.Abs (_cached_lng - lng) < geo_precission)) && (!string.IsNullOrEmpty(_cached_location)))
{
return _cached_location;
}
var geocoder = new CLGeocoder();
Simple question need simple answer.
How can I track the residence time in a specific geofence.
When I add geofence with Trigger on Enter, will I automatic receive a trigger when I leave that geofence. Basically I need to remember the time when I enter a geofence and when I leave that geofence so I can subtract leave-enter time and have my duration time. But I believe its not that easy to do that. So any other idea or advise how to solve that problem efficient ?
Thanks
I found one solution for this problem. In order to determine the dwell time in a geofence i have to get the time when user trigger a geofence and then i use to calculate if user leave the geofence with this mathematical method
Handler handler = new Handler();
getCurrentLatLng();
final Runnable myRunnable = new Runnable() {
public void run() {
GeofenceFinished myFinishedGeofence = db.getGeofenceFinishedByID("Finished" + id);
if (!isUserInRegion(latitude, longitude, myLatLng.latitude, myLatLng.longitude, rd)
|| myFinishedGeofence == null) {
String time = convertTime(endTime - startTime);
// get the finishedGeofence and set the duration of stay time
if (myFinishedGeofence != null)
setDurationOfStay("Finished" + id, time, getCurrentTime(System.currentTimeMillis()));
Toast.makeText(mContext, "Finish to determine duration of stay of " + myFinishedGeofence.getAddress(), Toast.LENGTH_SHORT).show();
handler.removeCallbacks(this);
} else {
getCurrentLatLng();
endTime += Constants.DELAY;
handler.postDelayed(this, Constants.DELAY);
}
}
private void setDurationOfStay(String geofenceid, String time, String endTime) {
if (db == null) db = GeofenceDatabaseHelper.getInstance(mContext);
if (!db.setDurationOfFinishedGeofence(geofenceid, time, endTime)) {
Log.i("setDurationOfStay", "fail");
}
}
};
handler.postDelayed(myRunnable, Constants.DELAY);
private boolean isUserInRegion(double firstLat, double firstLog, double curLat, double curLog, float radius) {
double distance = calculateDistance(firstLat, firstLog, curLat, curLog);
return distance <= radius;
}
To calculate the distance of user and center of geofence, i need to convert the current latitude and longitude in meter, so i can calculate that with the parametic equation for circle
So I use this approach from github
// https://github.com/mgavaghan/geodesy
private double calculateDistance(double firstLat, double firstLog, double curLat, double curLog) {
GeodeticCalculator geoCalc = new GeodeticCalculator();
Ellipsoid reference = Ellipsoid.WGS84;
GlobalPosition pointA = new GlobalPosition(firstLat, firstLog, 0.0); // Point A
GlobalPosition userPos = new GlobalPosition(curLat, curLog, 0.0); // Point B
// Distance between Point A and Point B
double distance = geoCalc.calculateGeodeticCurve(reference, userPos, pointA).getEllipsoidalDistance();
return distance;
}
hope it helps someone :D
Can anyone please inform me how to work with blackberry location-based services?
i am working on a project for a blackberry mobile application. i never had a blackberry before and i dont have a contract with any provider (just have a sim card from 3 and mobile device 9000 OS 4.6).
In the project i am currently trying to use the following code in order to retrieve the coordinates of current location (startpoint) and destination location (endpoint). It works just fine on the simulator but on the device nothing. Should i have a contract with a provider or something? and does this need just GPS or internet, or both to work?
Code:
String destination = "London";
final Landmark[] landmarks = Locator.geocode(destination.replace('\n', ' '), null);
Coordinates endPoint = landmarks[0].getQualifiedCoordinates();
// Get a location provider.
LocationProvider provider = LocationProvider.getInstance(null);
if (provider == null)
{
throw new IllegalStateException("No LocationProvider Available!!");
}
// Try to fetch the current location and get the coordinates of the current location.
Coordinates startPoint = provider.getLocation(-1).getQualifiedCoordinates();
double destiinationlatitude = endPoint.getLatitude();
double currentlatitude = startPoint.getLatitude();
thank you in advance
To get the GPS location on any version prior to 5.0 you have to instantiate this things
Criteria
Location Provider
Location Object (done with the location provider)
Here's the things you instantiate:
Criteria criteria = null;
LocationProvider provider = null;
javax.microedition.location.Location location = null;
After that you must assign values to the Criteria, get the instance of the LocationProvider using the criteria and get the Location using the LocationProvider.
criteria = new Criteria();
criteria.setPreferredPowerConsumption(Criteria.POWER_USAGE_HIGH);
criteria.setHorizontalAccuracy(50);
criteria.setVerticalAccuracy(50);
criteria.setCostAllowed(true);
provider = LocationProvider.getInstance(criteria);
location = provider.getLocation(5);
Note that the Criteria will determine if you use GPS, Wifi assisted location or Cellsite location, more info on the criteria setting here: http://www.blackberry.com/developers/docs/4.5.0api/javax/microedition/location/Criteria.html
After that, to get the coordinates you call the method: location.getQualifiedCoordinates()
And that's that... you should call this from a separate thread. And also the actual location management code should be on a try-catch block but the IDE will help you with that.
in this code we are seeing which modes are available to get co-ordinates(I.E if phone does not have a GPS then it should use satalite info.)
The Lat and Long is being retreived by the available mode.
A mapview is created (MapView which is the map, You set the required specifications such as the zooming, lat, lon, etc )then you invoke the map and the set zoom, lat, lon , etc will be applied to the map that reflects onto the screen.
CustomMapField mMapField;
Coordinates mCoordinates;
BlackBerryCriteria blackBerryCriteria = null;
BlackBerryLocation blackBerryLocation = null;
BlackBerryLocationProvider blackBerryLocationProvider = null;
double Doublelat = 0.0;
double Doublelng = 0.0;
blackBerryCriteria = new BlackBerryCriteria();
if(GPSInfo.isGPSModeAvailable(GPSInfo.GPS_MODE_CELLSITE)){
blackBerryCriteria.setMode(GPSInfo.GPS_MODE_CELLSITE);
}else if(GPSInfo.isGPSModeAvailable(GPSInfo.GPS_MODE_ASSIST)){
blackBerryCriteria.setMode(GPSInfo.GPS_MODE_ASSIST);
}else if(GPSInfo.isGPSModeAvailable(GPSInfo.GPS_MODE_AUTONOMOUS)){
blackBerryCriteria.setMode(GPSInfo.GPS_MODE_AUTONOMOUS);
}else{
blackBerryCriteria.setCostAllowed(true);
blackBerryCriteria.setPreferredPowerConsumption(Criteria.POWER_USAGE_LOW);
} try {
blackBerryLocationProvider = (BlackBerryLocationProvider) BlackBerryLocationProvider.getInstance(blackBerryCriteria);
blackBerryLocation = (BlackBerryLocation) blackBerryLocationProvider.getLocation(60);
QualifiedCoordinates qualifiedCoordinates = blackBerryLocation.getQualifiedCoordinates();
Doublelat = qualifiedCoordinates.getLatitude();
Doublelng = qualifiedCoordinates.getLongitude();
mCoordinates = new Coordinates(Doublelat, Doublelng, 0);
MapView mapView = new MapView();
mapView.setLatitude(finalintlat);
mapView.setLongitude(finalintlng);
mapView.setZoom(10);
MapsArguments mapsArgs = new MapsArguments(mapView);
Invoke.invokeApplication(Invoke.APP_TYPE_MAPS, mapsArgs);
}catch(Exception e){
System.out.println("Error in location :"+e.toString());
System.out.println("Error in location :"+e.getMessage());
}
I am working on gps based application. I am using LocationProvider and calling setlocationListener through it code is like
LocationProvider lp = LocationProvider.getInstance(null);
if (lp != null) {
lp.setLocationListener(new LocationListenerImpl(), 2, 1, 1);
} else {
Dialog.alert("GPS NOT SUPPORTED!");
retval = false;
}
} catch (LocationException e) {
System.out.println("GPS Error: " + e.toString());
}
return retval;
}
private class LocationListenerImpl implements LocationListener {
public void locationUpdated(LocationProvider provider, Location location) {
if (location.isValid()) {
heading = location.getCourse();
longitude = location.getQualifiedCoordinates().getLongitude();
latitude = location.getQualifiedCoordinates().getLatitude();
altitude = location.getQualifiedCoordinates().getAltitude();
speed = location.getSpeed();
System.out.println("Current latitude:"+latitude);
System.out.println("Current longitude:"+longitude);
System.out.println("Current speed:"+speed);
// This is to get the Number of Satellites
String NMEA_MIME = "application/X-jsr179-location-nmea";
satCountStr = location.getExtraInfo("satellites");
if (satCountStr == null) {
satCountStr = location.getExtraInfo(NMEA_MIME);
}
// this is to get the accuracy of the GPS Cords
QualifiedCoordinates qc = location.getQualifiedCoordinates();
accuracy = qc.getHorizontalAccuracy();
}
}
it doesnt give an error but dont even work out so help with the same.the control dont get transferred to LocationListenerImpl()...
I am using BlackBerry_JDE_PluginFull_1.0.0.67 with eclipse-java-galileo-SR1-win32 on Blackberry 8800 simulator..
Any assistence is grately appreciated....
Thanking you in advance.
try this:
lp.setLocationListener(new LocationListenerImpl(), 2, -1, -1);
Acc to me
u set 2,1,1 which means that time interval is 2 sec after which location updation will be automatically called
1 sec indicates time out
1 sec indicates max age
ur gps times out before going ahead for gps location update method.so try it with setting it to default value = -1
You have to enable the GPS in the simulator, is it enabled when you try?
If you're getting a NullPointerException then you should check in the OS Options that the GPS has Location activated.