I'm developing an application where user can set multiple locations. I get succeed to show notifications when user get Enter or Leave specific region using GeoFencing.
Now, there is situation that i need to provide monitoring for all saved locations and it can be hundreds and more. I've read at the given link "You can have multiple active geofences, with a limit of 100 per device user."
Is there any way add more then 100 geofences per device user ?
Thanks!
Have an ArrayList with all the geofences you want to monitor +100.
Listen to location updates.
When you get a location update, if the ArrayList of all your geofences is more than 100, remove all geofences been monitored and then calculate the 100 nearest geofences using the harvesine formula:
public static final double R = 6372.8; // In kilometers
public static double haversine(double lat1, double lon1, double lat2, double lon2) {
double dLat = Math.toRadians(lat2 - lat1);
double dLon = Math.toRadians(lon2 - lon1);
lat1 = Math.toRadians(lat1);
lat2 = Math.toRadians(lat2);
double a = Math.sin(dLat / 2) * Math.sin(dLat / 2) + Math.sin(dLon / 2) * Math.sin(dLon / 2) * Math.cos(lat1) * Math.cos(lat2);
double c = 2 * Math.asin(Math.sqrt(a));
return R * c;
}
That will give you the distance between the two locations. After that you could compare that distance with the geofence region radius to know if is inside the region.
Note: This distance will be in kilometers if your radius is on meters then just multiply the haversine method result with 1000 so that it's converted to meters.
Reference
Start monitoring the result list of the 100 nearest geofences.
This will allow you to always monitor the 100 nearest geofences based on your location. Been able to monitor more than 100 since it will change the monitoring geofence regions always to the 100 nearest geofence regions.
Related
I want to create an app in which I want to show how much distance does the user has been traveled.
I have tried using float distance = locationA.distanceTo(locationB); but it just draws a simple straight line from start to end and then calculates the distance.
I want to calculate the traveled distance based on the traveled route. Is it possible to do so using any Google maps API?
you just need service to continuously observer that user change it's location then you can use these function to calculate the distance.
public double GetDistanceInKm(double lat1, double lon1, double lat2, double lon2)
{
final int R = 6371;
// Radius of the earth in km
double dLat = deg2rad(lat2 - lat1);
// deg2rad below
double dLon = deg2rad(lon2 - lon1);
double a = Math.sin(dLat / 2) * Math.sin(dLat / 2) + Math.cos(deg2rad(lat1)) * Math.cos(deg2rad(lat2)) * Math.sin(dLon / 2) * Math.sin(dLon / 2);
double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
double d = R * c;
// Distance in km
return d;
}
private double deg2rad(double deg)
{
return deg * (Math.PI / 180);
}
Assuming you have a bunch of lat long points making up a route. You have to take the distance from the previous point to the next point for all points and keep a total of that. In other words you need a-lot of lat lon data in between the route or you are just going to get a straight line.
You can use google maps api to get the distance
use this link to understand how to use it.
Let's say i have set a walking route on google maps API from point A to point B.
I start at point A (duh). How can i, or is it possible, to update current location on map given the distance walked? (I'm getting distance walked from Google fit SDK).
Example:
From point A to point B is 1.5Km (A route marked on google maps)
I have ran 450m
How do i update map current position based on that?
PS: I can't use GPS as the app i'm making does not show your real current location. It's a false location
ok it is possible but you need to have the bearing of your direction.
for this you need three things -
bearing of your movement from source to destination.
the source latlong.
the distance travelled.
if you have those 3 things then this is how you do it-
private LatLng getDestinationPoint (LatLng source,double brng, double dist){
dist = dist / 6371;
brng = Math.toRadians(brng);
double lat1 = Math.toRadians(source.latitude), lon1 = Math.toRadians(source.longitude);
double lat2 = Math.asin(Math.sin(lat1) * Math.cos(dist) +
Math.cos(lat1) * Math.sin(dist) * Math.cos(brng));
double lon2 = lon1 + Math.atan2(Math.sin(brng) * Math.sin(dist) *
Math.cos(lat1),
Math.cos(dist) - Math.sin(lat1) *
Math.sin(lat2));
if (Double.isNaN(lat2) || Double.isNaN(lon2)) {
return null;
}
return new LatLng(Math.toDegrees(lat2), Math.toDegrees(lon2));
}
use my code from above function and put the arguments to function and in return you will get the destination latlng .
let me know if it was helpful to you.
thank you
I need to calculate distance as the user moves in android. I have the starting point coordinates and can get the user's current location. How should I calculate distance.
I don't think I can call GoogleDistance Api as my application would be a real time application and calling this API would be extremely overhead or should calling GoogleDirectionsAPI would work fine.
Also I would like to test the distance travelled. How should I do it? Is there some way of sampling the data or do I really need to go out in the real world and actually travel and then test my application?
Edited: I want the distance travelled by the user and not the straight line distance between the points
I hope following will help:
In my app i started collecting lat longs after every 3fts (I set 3ft just for testing). I collected lat longs as follows:
Now I started calculating distance from point 1 to 2 and then 2 to 3 and then 3 to 4 and so on. After summing up I got total distance from 1 to 5.
I used following functions to calculate distance:
public double GetDistanceFromLatLonInKm(double lat1, double lon1, double lat2, double lon2)
{
final int R = 6371;
// Radius of the earth in km
double dLat = deg2rad(lat2 - lat1);
// deg2rad below
double dLon = deg2rad(lon2 - lon1);
double a = Math.sin(dLat / 2) * Math.sin(dLat / 2) + Math.cos(deg2rad(lat1)) * Math.cos(deg2rad(lat2)) * Math.sin(dLon / 2) * Math.sin(dLon / 2);
double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
double d = R * c;
// Distance in km
return d;
}
private double deg2rad(double deg)
{
return deg * (Math.PI / 180);
}
This method is calculating exact distance for me.
You can calculate the distance between two point using the following function
double distanceBetweenTwoPoint(double srcLat, double srcLng, double desLat, double desLng) {
double earthRadius = 3958.75;
double dLat = Math.toRadians(desLat - srcLat);
double dLng = Math.toRadians(desLng - srcLng);
double a = Math.sin(dLat / 2) * Math.sin(dLat / 2)
+ Math.cos(Math.toRadians(srcLat))
* Math.cos(Math.toRadians(desLat)) * Math.sin(dLng / 2)
* Math.sin(dLng / 2);
double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
double dist = earthRadius * c;
double meterConversion = 1609;
return (int) (dist * meterConversion);
}
For the second Part: To use mock or sample data you can use "Fake GPS" app from the play store, which will generate mock location in your device.
Happy Coding
There are basically three ways to check the traveled distance -
By using GPS, check the coordinate between two points using distanceTo of Location class.
Using Accelerometer , you can check the movement of device using Accelerometer.
Using Step detector - this is recently updated by Android.
Hope this helps you to achieve your goal :)
For the first question . You have origin coordinates and the present user location coordinates so what you can do is google api v3 library provides a method that takes origin LatLng and destination LatLng and gives the distance . Add api v3 jar to your android build path.
For the second one goto google maps and give the location details it is accurate..
I am getting two GEO locations in my application and I have to calculate distance between them and after distance calculation I have to compare that result with the a defined threshold which is in my case 50 meters, how would I define that threshold in float. Also, Currently I my android fone is at the same location, but I always get the calculated distance between my 2 two geolocations determined after an interval to be more than 50 meters. How is it possible? I am taking threshold of 50 meters as:
private static final float DISTANCE_CHANGE_METERS = 50.0f; //50 meters
and I am calculating distance through following formula I found on StackOverflow:
public static float distFrom(double lat1, double lng1, double lat2, double lng2) {
double earthRadius = 3958.75;
double dLat = Math.toRadians(lat2 - lat1);
double dLng = Math.toRadians(lng2 - lng1);
double a = Math.sin(dLat / 2) * Math.sin(dLat / 2) + Math.cos(Math.toRadians(lat1)) * Math.cos(Math.toRadians(lat2)) * Math.sin(dLng / 2) * Math.sin(dLng / 2);
double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
double dist = earthRadius * c;
int meterConversion = 1609;
return new Float(dist * meterConversion).floatValue();
}
Kindly help me out in this regard. Thanks!
Currently my android phone is at the same location, but I always get the calculated distance between my 2 two geolocations determined after an interval to be more than 50 meters. How is that possible?
It actually depends on how you are passing the latitude and longitude to the distFrom function. Just to remind you that there is a simpler way to calculate the distance.
You can use just distanceTo() function in android API using Location to calculate the distance between two places like this:
Location locationA = new Location("point A");
locationA.setLatitude(latA); // co-ordinates in double
locationA.setLongitude(lngA);
Location locationB = new Location("point B");
locationB.setLatitude(latB);
locationB.setLongitude(lngB);
float distance = locationA.distanceTo(locationB);
If after using this also you are getting a distance greater than 50 meters then your co-ordinates that you are providing are not that accurate. Its perfectly fine because its tough to get accuracy with less that 50 meter precision. It would be most accurate if you are using internet along with GPS. If you see here, even if you use ACCURACY_HIGH as a criteria to choose a Location Provider, it provides accuracy of less than 100 meters. It can be accurate upto 100, 70 or even 50 meters. So even the most accurate option is not guaranteed to give extreme accuracy. If you are using GPS/Network provider for getting Location, then it your situation is very much possible. Getting location using `Network Provider1 is also not that accurate as it can catch signals of 2 network towers on different occasions, which can be well apart physically.
Hope it helps and clears the point to some extent. Its the problem to accuracy of your Location Provider.
Could you just do:
if (distFrom(lat1,lng1,lat2,lng2) > DISTANCE_CHANGE_METERS)
{
//greater than threshhold
}
I am searching for a solution in Android to check whether a GPS point will lie in given set of Start and End GPS location or not. For Example Mr A will start from point X and will reach point Z via Y. Now if Mr B given a location P then we want to check whether this point P is lying on the Mr A's route or not.
If it appears that GPS is not sufficient for it then you can suggest any other ways as well.
I am looking forward to hear back from you!!
I am assuming that "Given Set of Starting and Ending" means you have one defined root in your Database. My answer is based on same purpose. Have a look at to following method,
public static float getDistance (float lat1, float lng1, float lat2, float lng2 )
{
double earthRadius = 3958.75;
double dLat = Math.toRadians(lat2-lat1);
double dLng = Math.toRadians(lng2-lng1);
double a = Math.sin(dLat/2) * Math.sin(dLat/2) +
Math.cos(Math.toRadians(lat1)) * Math.cos(Math.toRadians(lat2)) *
Math.sin(dLng/2) * Math.sin(dLng/2);
double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
double dist = earthRadius * c;
int meterConversion = 1609;
return new Float(dist * meterConversion).floatValue();
}
Now you need to compare your Mr A's lat-lon values with the DB's one by one. If you the distance is few meters that means Mr A has visited that point. Using this logic you need to check all the GPS Point of Mr A with the root stored in your DB.