Expo - increase location accuracy with Geofence - android

I could really use some help improving the accuracy of the Geofencing feature. If you look at the following screenshots you can see my location and the location of circle and marker which share the same latLng coordiantes and radius as my geofence.
Link to the image
If I run the following lines within the app.js file:
const taskName = "front_door";
const latLng = { latitude: -37.820711, longitude: 144.994264 };
const radius = 5;
Permissions.askAsync(Permissions.LOCATION);
Location.startGeofencingAsync(taskName, [
{
...latLng,
radius
}
]);
TaskManager.defineTask(taskName, task => {
if (task.data.eventType === Location.GeofencingEventType.Enter) {
console.log("entered");
}
console.log(task.data.region.state);
return;
});
Which is returning entered and 1 (explanation).
Given my current location being outside of the geofence I would expect entered to fire only once I had inside of the geofence and task.data.region.state to equal 2 (explanation).
If I change:
const latLng = { latitude: -37.820711, longitude: 144.994264 };
To:
const latLng = { latitude: -37, longitude: 144 };
The geofence is far enough away that entered is never output and the task.data.region.state equals 2.
This leads me to believe that the issue is related to the accuracy set of Location however, I cannot find a way to increase the accuracy when using the startGeofencingAsync method.
If I was not using geofencing I would do something like this:
Location.startLocationUpdatesAsync(taskName, {
accuracy: Location.Accuracy.Highest
});
But I can't see how to access the options object when using Location.startGeofencingAsync(taskName, regions)
If you know how to achieve this please do let me know as I am pulling my hair out over it! Thanks in advance :)

Related

agm/core polyline from firebase

How to store values in firebase from android like this:
polyline : [
{
latitude: 39.8282,
longitude: -98.5795
},
{
latitude: 37.772,
longitude: -122.214
},
{
latitude: 21.291,
longitude: -157.821
}}
so it can be used by agm/core's polyline. Firebase doesn't accept arrays and it seems like the only way to pass the polyline directive a set of coordinates and then iterate through it to draw out the polyline path would be as an array. Otherwise, I guess, I would have to pass individual latlong points to angular and create an array this way but I would prefer not doing it this way.

Get precise position of user device with GPS

In my Android application i need to get the traveled road with car and i check it with google android directions API and GPS.
But the problem is that some times the GPS location is not precise and i can get an error of 10Km for some lecture and that means that in a total travel of 150km my "distance traveled" can be 250km and it's wrong!
Yesterday i test it in highway and the problem is that when the marker is located out from highway, the calculation of distance traveled from my current position and the last marker located by road is very wrong (in this case out of the highway).
There is some best way for getting traveled distance with car using the phone?
Maybe some better code for getting more precise GPS position?
Here is my code:
private void getUserLocation() {
Log.d(TAG, "getUserLocation()");
checkLocationPermission();
mFusedLocationClient.getLastLocation()
.addOnSuccessListener(getActivity(), 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
String stringStartLat, stringStartLng;
double lat = location.getLatitude();
double lng = location.getLongitude();
//Start position of device
if (travelInfo.getStartLat() == 0 && travelInfo.getStartLng() == 0) {
travelInfo.setStartLat(lat);
travelInfo.setStartLng(lng);
//Set lastcoordinates equals to start
travelInfo.setLastLat(lat);
travelInfo.setLastLng(lng);
}
//Current position of device
travelInfo.setCurrentLat(lat);
travelInfo.setCurrentLng(lng);
stringStartLat = Double.toString(travelInfo.getStartLat());
stringStartLng = Double.toString(travelInfo.getStartLng());
//Set the TextView in the fragment with start coordinates
Log.d(TAG,"LatitudeStart: " + stringStartLat);
Log.d(TAG,"LongitudeStart: " + stringStartLng);
if (startMarker == null) {
//Add the user location to the map with a marker
LatLng userLoction = new LatLng(travelInfo.getStartLat(), travelInfo.getStartLng());
startMarker = googleMap.addMarker(new MarkerOptions()
.position(userLoction)
.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_ORANGE))
.title("Start Position")
.snippet("Show the start position of user"));
// For zooming automatically to the location of the marker
CameraPosition cameraPosition = new CameraPosition.Builder().target(userLoction).zoom(9).build();
googleMap.animateCamera(CameraUpdateFactory.newCameraPosition(cameraPosition));
} else {
LatLng currentLocation = new LatLng(travelInfo.getCurrentLat(), travelInfo.getCurrentLng());
currentPositionMarker = googleMap.addMarker(new MarkerOptions()
.position(currentLocation)
.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_YELLOW))
.title("Current Position")
.snippet("Show the current position of user during travel"));
// For zooming automatically to the location of the marker
CameraPosition cameraPosition = new CameraPosition.Builder().target(currentLocation).zoom(11).build();
googleMap.animateCamera(CameraUpdateFactory.newCameraPosition(cameraPosition));
}
if (travelInfo.getEndLat() != 0 && travelInfo.getEndLng() != 0) {
Log.i(TAG, "Dentro if userlocation");
//Get total distance of travel
getTotalDistanceTime(travelInfo);
//Get the percurred distance from last known coordinates
getPercurredDistance(travelInfo);
}
}
}
});
}
And getpercurredDistance use google direction API with this url
String url = "https://maps.googleapis.com/maps/api/directions/json?origin=" + obj.getLastLat() + "," + obj.getLastLng() + "&destination=" + obj.getCurrentLat() + "," + obj.getCurrentLng() + "&mode=driving&key=AI*******************I";
For getting distance traveled from last marker and current position marker.
But some times it put the localized position too far from real position... how avoid this?
EDIT
The method that i use is good for my work? mFusedLocationClient.getLastLocation()
There is no possibilities to get more precise GPS position from GPS sensor of android device, but you can filter "wrong" points this ways:
1) for each travel point get several values of Lat and Lng, discard the minimum and maximum and average the remaining ones;
2) log timestamps of each travel point and compare it for two neighboring points: speed (distance between that two points divided by time interval of that points) grater than max. car speed (e.g. 250 km/h) that means the second point is wrong (if first point is good of course).
3) use Google Maps Roads API to find best-fit road geometry for a given set of GPS coordinates.
Also take a look at this question.
For real-time location purposes, location updates allow you to request location updates at different intervals. See the android developer location documentation. The function you want is FusedLocationProviderClient.requestLocationUpdates.
There is no reason GPS (or any other widely used location technology) should ever give you 10km error for a single location estimate. If you are getting this, there is a large mismatch between when you the location estimate was made and when you are requesting it.

OSMdroid how to get screen coordinates?

I am doing app on android using osmdroid. How I can get coordinates(top, bottom, left,right) of map which is shown on screen?
Thanx.
It is not completely clear what you're asking, but I think you're asking for the lat/lon bounding box.
BoundingBoxE6 boundingBox = mMapView.getProjection().getBoundingBox();
"I do it in onCreate if it important" => Yes, it is.
In fact, you cannot access to a correct mapview bounding box in onCreate.
This is "because the MapView's width and height is zero because it hasn't had onLayout called yet"
This is a (quite annoying) osmdroid issue, not fixed in v4.2.
In addition, when called in onCreate, setCenter is also not working properly in v4.2.
See more explanation and workarounds here: https://github.com/osmdroid/osmdroid/issues/22
In react-native I use the onRegionChangeComplete event (onRegionChangeComplete={e => properties.regionChange(e)}). This event returns the region of the MapView. So: {"latitude": 4.50751184289841, "latitudeDelta": 0.09999884159289252, "longitude": -75.67515761717539, "longitudeDelta": 0.06322002503726765}
So, if you need to calculate a polygon with the screen area, you should do the following:
regionChange = (e) => {
areaLoadData = [
{
latitude: e.latitude + e.latitudeDelta,
longitude: e.longitude - e.longitudeDelta
},
{
latitude: e.latitude + e.latitudeDelta,
longitude: e.longitude + e.longitudeDelta
},
{
latitude: e.latitude - e.latitudeDelta,
longitude: e.longitude + e.longitudeDelta
},
{
latitude: e.latitude - e.latitudeDelta,
longitude: e.longitude - e.longitudeDelta
},
]
}

Vertical Accuracy in android GPS

I am working with GPS related app. I need to get vertical accuracy but it always gets fix 11.0000. I need it to be dynamic as lat and lng. I have used getAccuracy but it results in horizontal accuracy.
#Override
public void onLocationChanged(Location location) {
if (location != null) {
lat = location.getLatitude();
lon = location.getLongitude();
Geocoder geoCoder = new Geocoder(getBaseContext(), Locale.getDefault());
address = mailOb.getAddress(geoCoder, lat, lon);
if (!meterFootFlag) {
diameter = Math.round(location.getAccuracy()) + " m.";
altitude = Math.round(location.getAltitude()) + " m.";
} else {
diameter = Math.round(location.getAccuracy() * 3.28084) + " ft.";
altitude = Math.round(location.getAltitude() * 3.28084) + " ft.";
}
if (diameter.contains("+"))
diameter.replace("+", "");
else if (altitude.contains("+"))
altitude.replace("+", "");
} else {
lat = 0.0;
lon = 0.0;
if (!meterFootFlag) {
altitude = 0.0 + " m.";
diameter = 0.0 + " m.";
} else {
altitude = 0.0 + " ft.";
diameter = 0.0 + " ft.";
}
}
mlocManager.removeUpdates(MySettings.this);
pDialog.dismiss();
}
How can I get vertical accuracy?
Thanks in advance
Android does not provide the vertical accuracy.
Vertical accuracy usually is 2-3 times worse then horizontal accuracy.
A simple solution: use the androids accuracy for both horizontal and vertical.
advanced solution 1: find out what android uses as total accuracy (it could be a radial error of an error-sphere, including lat,long and altitude)
try to find out a conversion factor, e.g take accuracy and multiply *2,5
Another solution, look at iphone horizontal and vert accuracy, and compare to that of android. find out an average conversion factor from acc to vert acc.
Solution 3: think why you need vertical accuracy at all. why do you need that?
hints:examples from my iphone4: when iphone shows 30m hor, i have 57vert, 10hor: 15-20vert, 5 hor: 10vert
Starting with API 26 you can use getVerticalAccuracyMeters() method
#Override
#RequiresApi(Build.VERSION_CODES.O)
public void onLocationChanged(Location location) {
float accuracy = location.getVerticalAccuracyMeters();
}
Altitude accuracy heavily depends on core GPS accuracy, use of additional sensors as barometer and use of wifi/cell networks plus the fusion algorithms. It is NOT have a constant ratio. If u really want to get accuracy you can try the following: check variance of the signal while motionless, this will not always work as some devices will detect motionless and just repeat last output to save power. Another approach which is bit costly is to check with reference as https://developers.google.com/maps/documentation/elevation/intro
so u basically take lat lon measurement with the lat lon error and check the vertical error u get assuming you are in open area.

Map View errors when I used it for the second time in Android (Titanium)

I have records on the table list contains data that has latitude & longitude on the listing widow. When I click on each row, it passes to the detail window that display the mapview and its annotation of that record.
I zoom in & out, moved to different area and I clicked "back" button to go back to the record list.
Then, I selected on the different record to see the map on the detail window again, when I'm on the detail window suddenly I clicked on the map, there, it alerts me an error message which did not mention about the specific issues.
Here is my code:
self.listingAnnotation = Titanium.Map.createAnnotation({
pincolor: Titanium.Map.ANNOTATION_RED,
latitude: latitude,
longitude: longitude,
animate: true
});
self.region = {
latitude: latitude,
longitude: longitude
};
if(!self._mapview){
self._mapview = Titanium.Map.createView({
top: 130,
bottom: 0,
animate:true,
mapType: Titanium.Map.STANDARD_TYPE,
region: {latitude: latitude, longitude: longitude},
annotations: [self.listingAnnotation]
});
}
else{
self._mapview.removeAllAnnotations();
self._mapview.setLocation(self.region);
self._mapview.addAnnotation(self.listingAnnotation);
}
self._listingDetailWindow.add(self._mapview);

Categories

Resources