I trying to match hardcoded latitude an longitude with dynamic latitude and longitude, but its not showing correct output, can anyone help me to sort out this error
My code is
String Log = "-122.084095";
String Lat = "37.422005";
try {
if ((Lat.equals(latitude)) && (Log.equals(longitude))) {
AudioManager audiM = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
audiM.setRingerMode(AudioManager.RINGER_MODE_SILENT);
Toast.makeText(getApplicationContext(),
"You are at home",
Toast.LENGTH_LONG).show();
} else {
AudioManager auMa = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
auMa.setRingerMode(AudioManager.RINGER_MODE_NORMAL);
Toast.makeText(getApplicationContext(),
"You are at office ", Toast.LENGTH_LONG)
.show();
}
} catch (Exception e) {
e.printStackTrace();
}
it always goes for else part...
You don't want to use a String comparison here as you can't guarantee the level of accuracy with the real-time location.
The best way to handle this would be to determine the distance between the points and then determine if it's close enough for you to consider, approx, the same.
For this, we use distanceBetween or distanceTo
Docs are here and here
Examples can be found here. Here's one of those examples:
Location locationA = new Location("point A");
locationA.setLatitude(pointA.getLatitudeE6() / 1E6);
locationA.setLongitude(pointA.getLongitudeE6() / 1E6);
Location locationB = new Location("point B");
locationB.setLatitude(pointB.getLatitudeE6() / 1E6);
locationB.setLongitude(pointB.getLongitudeE6() / 1E6);
double distance = locationA.distanceTo(locationB);
The latitude and longitude are variables which vary from point to point, matter of fact they keep on changing while standing on the same spot, because it is not precise.
Instead of comparing the Strings, take a rounded value of the lat and long (in long or float ) and check those values within a certain range. That will help you out with the "Home" and "Office " thing.
For e.g :
String Log = "22.084095";
String Lat = "37.422005";
double lng=Double.parseDouble(Log);
double lat=Double.parseDouble(Lat);
double upprLogHome=22.1;
double lwrLogHome=21.9;
double upprLatHome=37.5;
double lwrLatHome=37.3;
// double upprLogOfc=;
// double lwrLogOfc=;
// double upprLatOfc=;
// double lwrLatOfc=;
if(lng<upprLogHome && lng>lwrLogHome && lat<upprLatHome &&lat>lwrLatHome )
{
System.out.println("You are Home");
}
/* else if(lng<upprLogOfc && lng>lwrLogOfc && lat<upprLatOfc &&lat>lwrLatOfc )
{
System.out.println("You are Home");
}*/
else
System.out.println("You are neither Home nor Ofc");
But for the negative lat long you have to reverse the process of checking.
your matching is okay but you probably should not check for a gps location like this.
You should convert the location to something where you can check that you are in 10m radius of the location.
A nicer way would be to leave the long/lat as doubles and compare the numbers.
if(lat > HOME_LAT - 0.1 && lat < HOME_LAT + 0.1 && ...same for lon... ){}
Try this,
Use google map api to pass lat and long value you will get formatted address. And also pass dynamic lat and lng value same google api you will get formatted address. And then match two formatted address you will get result. i suggest this way you can try this
Use this google api. http://maps.googleapis.com/maps/api/geocode/json?latlng=11.029494,76.954422&sensor=true
Reena, its very easy, Check out below code. You need to use "equalsIgnoreCase()" instead of
"equals".
if ((Lat.equalsIgnoreCase(latitude)) && (Log.equalsIgnoreCase(longitude))) {
should work
Example below :
// Demonstrate equals() and equalsIgnoreCase().
class equalsDemo {
public static void main(String args[]) {
String s1 = "Hello";
String s2 = "Hello";
String s3 = "Good-bye";
String s4 = "HELLO";
System.out.println(s1 + " equals " + s2 + " -> " +
s1.equals(s2));
System.out.println(s1 + " equals " + s3 + " -> " +
s1.equals(s3));
System.out.println(s1 + " equals " + s4 + " -> " +
s1.equals(s4));
System.out.println(s1 + " equalsIgnoreCase " + s4 + " -> " +
s1.equalsIgnoreCase(s4));
}
}
You can print dynamice Latitute and Longitute to Logcat and check with hardcoded Latitute and Longitute
Related
DIRECTION_URL_API = "https://maps.googleapis.com/maps/api/directions/json?"
DIRECTION_URL_API + "origin=" + origin + "&destination=" + destination + "&sensor=true" + "&mode=" +typeOpt+"&key=" + GOOGLE_API_KEY ;
I am using this format but its not working
Please suggest me :)
You can find distance following way
http://maps.googleapis.com/maps/api/directions/json?origin=21.1702,72.8311&destination=21.7051,72.9959&sensor=false&units=metric&mode=driving
origin=lat1,long1
destination=lat2,long2
Please use the below method to calculate the distance between two points
/**
* Returns Distance in kilometers (km)
*/
public static String distance(double startLat, double startLong, double endLat, double endLong) {
Location startPoint = new Location("locationA");
startPoint.setLatitude(startLat);
startPoint.setLongitude(startLong);
Location endPoint = new Location("locationA");
endPoint.setLatitude(endLat);
endPoint.setLongitude(endLong);
return String.format("%.2f", startPoint.distanceTo(endPoint) / 1000); //KMs
}
Method usage -
String mDistance = distance(startLat,
startLong,
endLat,endLng)).concat("km");
My goal is to do autocomplete prediction using Google Places API, and now I want to make some kind algorithm that will take current location lat and lng, and make a prediction of places only in 100-200 km diameter.
So, at this moment I get user's current location lat and lng, how to set 100-200 km?
private void getCurrentLocation() {
mLastLocation = LocationServices.FusedLocationApi
.getLastLocation(mGoogleApiClient);
if (mLastLocation != null) {
double latitude = mLastLocation.getLatitude();
double longitude = mLastLocation.getLongitude();
mLatLonBounds = new LatLngBounds(new LatLng(latitude,longitude),
new LatLng(latitude,longitude));
Log.d("myTag","lat = "+mLatLonBounds.northeast.latitude+" ,lon = "+mLatLonBounds.northeast.longitude);
//Log.d("myTag","lat = "+mLatLonBounds.southwest.latitude+" ,lon = "+mLatLonBounds.southwest.longitude);
}else {
//some code
}
}
Here is how I set bounds to auto prediction:
#Nullable
private ArrayList<AutoCompletePlace> getAutocomplete(CharSequence constraint) {
if (mGoogleApiClient.isConnected()) {
Log.i(Constants.AUTO_COMPLETE_TAG, "Starting autocomplete query for: " + constraint);
// Submit the query to the autocomplete API and retrieve a PendingResult that will
// contain the results when the query completes.
PendingResult<AutocompletePredictionBuffer> results = Places.GeoDataApi
.getAutocompletePredictions(mGoogleApiClient, constraint.toString(),
**mBounds**, mPlaceFilter);
// This method should have been called off the main UI thread. Block and wait for at most 60s
// for a result from the API.
AutocompletePredictionBuffer autocompletePredictions = results.await(60, TimeUnit.SECONDS);
// Confirm that the query completed successfully, otherwise return null
final Status status = autocompletePredictions.getStatus();
if (!status.isSuccess()) {
Toast.makeText(getContext(), "Error contacting API: " + status.toString(),
Toast.LENGTH_SHORT).show();
Log.e(Constants.AUTO_COMPLETE_TAG, "Error getting autocomplete prediction API call: " + status.toString());
autocompletePredictions.release();
return null;
}
Log.i(Constants.AUTO_COMPLETE_TAG, "Query completed. Received " + autocompletePredictions.getCount()
+ " predictions.");
// Copy the results into our own data structure, because we can't hold onto the buffer.
// AutocompletePrediction objects encapsulate the API response (place ID and description).
Iterator<AutocompletePrediction> iterator = autocompletePredictions.iterator();
ArrayList resultList = new ArrayList<>(autocompletePredictions.getCount());
while (iterator.hasNext()) {
AutocompletePrediction prediction = iterator.next();
// Get the details of this prediction and copy it into a new PlaceAutocomplete object.
resultList.add(new AutoCompletePlace(prediction.getPlaceId(),
prediction.getDescription()));
}
// Release the buffer now that all data has been copied.
autocompletePredictions.release();
return resultList;
}
Log.e(Constants.AUTO_COMPLETE_TAG, "Google API client is not connected for autocomplete query.");
return null;
Example my current location 48.6180288,22.2984587.
UPDATE: Before the Francois Wouts give me the answer, I found another solution on stackoverflow, you can use it too.
public static final LatLngBounds setBounds(Location location, int mDistanceInMeters ){
double latRadian = Math.toRadians(location.getLatitude());
double degLatKm = 110.574235;
double degLongKm = 110.572833 * Math.cos(latRadian);
double deltaLat = mDistanceInMeters / 1000.0 / degLatKm;
double deltaLong = mDistanceInMeters / 1000.0 / degLongKm;
double minLat = location.getLatitude() - deltaLat;
double minLong = location.getLongitude() - deltaLong;
double maxLat = location.getLatitude() + deltaLat;
double maxLong = location.getLongitude() + deltaLong;
Log.d("Location", "Min: " + Double.toString(minLat) + "," + Double.toString(minLong));
Log.d("Location","Max: "+Double.toString(maxLat)+","+Double.toString(maxLong));
// Set up the adapter that will retrieve suggestions from the Places Geo Data API that cover
// the entire world.
return new LatLngBounds(new LatLng(minLat,minLong),new LatLng(maxLat,maxLong));
According to Wikipedia, you probably want to allow around 1 degree in each direction around the user's location to cover 100-200km. The exact area covered will depend on where the user is, but this should be a good enough approximation for most use cases.
Try the following, for example:
double radiusDegrees = 1.0;
LatLng center = /* the user's location */;
LatLng northEast = new LatLng(center.latitude + radiusDegrees, center.longitude + radiusDegrees);
LatLng southWest = new LatLng(center.latitude - radiusDegrees, center.longitude - radiusDegrees);
LatLngBounds bounds = LatLngBounds.builder()
.include(northEast)
.include(southWest)
.build();
I believe this should work correctly even across the antemeridian. Let me know how you go!
I've an app that gets the current user's location from a location service. When i get the lon and lat from the location object, they are as follows
lat = 53.653770446777344
lon = -1.520833969116211
.
I then store these in a GeoPoint object which is passed to a query string for Google Servers. This eventually plots a polyline between the current location and a destination.
It all works fine and the polyline is drawn, however it is drawn incorrectly as the current location is set about 100 mile away. I've logged out some values and there is a loss of precision when the lon and lat get passed to the geopoint.
How can i get around this.
#Override
public void onLocationChanged(Location location) {
lati = (location.getLatitude());
lngi = (location.getLongitude());
startAddr = new GeoPoint((int)lati, (int)lngi);
Log.e(TAG, "lat = " + lati);
Log.e(TAG, "lon = " + lngi);
Log.e(TAG, "lat after cast = " + (int)(lati * 1000000));
Log.e(TAG, "lon after cast = " + (int)(lngi * 1000000));
locationManager.removeUpdates(this);
StringBuilder sb = new StringBuilder();
sb.append("http://maps.google.com/maps/api/directions/json?origin=");
sb.append(startAddr);
sb.append("&destination=");
sb.append(endAddr);
sb.append("&sensor=false");
stringUrl = sb.toString();
Log.e(TAG, "url = " + stringUrl);
AsyncGetRoute agr = new AsyncGetRoute();
agr.execute();
.
11-15 12:45:17.280: E/GetClientDirections(23220): lat = 53.653770446777344
11-15 12:45:17.280: E/GetClientDirections(23220): lon = -1.520833969116211
11-15 12:45:17.280: E/GetClientDirections(23220): lat after cast = 53653770
11-15 12:45:17.280: E/GetClientDirections(23220): lon after cast = -1520833
11-15 12:45:17.290: E/GetClientDirections(23220): url = http://maps.google.com/maps/api/directions/json?origin=53,-1&destination=AL73EZ&sensor=false
This is the problem:
startAddr = new GeoPoint((int)lati, (int)lngi);
This truncates the fractions, so effectively for your input, your result is:
startAddr = new GeoPoint(53, -1);
As the API doc says, the GeoPoint accepts integer values: the two angles multiplied by 10^6. And because of this, the coordinates given would correspond to these values:
Latitude: 0.000053
Longitude: -0.000001
You should multiply first with 10^6, then truncate, so you should try:
startAddr = new GeoPoint((int)(lati*1000000.0), (int)(lngi*1000000.0));
I Have an address that I would like to know the coordinates of. For instance the address is "Skillman Ave" Queens, NY. The coordinates is: 40.747281, -73.9283169 according to maps.google.com. In my app I have a function like this:
public GeoPoint addressToGeo(String adr) {
Geocoder coder = new Geocoder(this);
List<Address> address = null;
GeoPoint coordinates;
try {
address = coder.getFromLocationName(adr, 1);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if (address == null) {
return null;
}
Address location = address.get(0);
location.getLatitude();
location.getLongitude();
coordinates = new GeoPoint((int) (location.getLatitude() *1E6),
(int) (location.getLongitude() * 1E6));
return coordinates;
}
Which takes an address as parameter, and hopefully it will return the coordinates. My debugger says the the first element in the list adress contains this information:
[Address[addressLines=[0:"Skillman Ave",1:"Queens, New York",2:"Amerikas forente stater"],feature=Skillman Ave,admin=New York,sub-admin=Queens,locality=Queens,thoroughfare=Skillman Ave,postalCode=null,countryCode=US,countryName=Amerikas forente stater,hasLatitude=true,latitude=40.747281,hasLongitude=true,longitude=-73.9283169,phone=null,url=null,extras=null]]
which seems correct if you look at the latitude and longitude variables. But when I type in this code:
GeoPoint test;
test = addressToGeo("Skillman Ave");
double latitude = test.getLatitudeE6();
double longitude = test.getLongitudeE6();
String lat = Double.toString(latitude);
String lng = Double.toString(longitude);
String total = lat + " " + lng;
toAdress.setText(total);
the toAdress textField will contain 4.0747281E7, -7.3928316E7 The comma is not in the right spot, and what is the E7 in the end of each double?
'E7' is notation meaning that you need to multiply by 10^7 to get the actual number. In this case it would give you 40747281. You then need to format that into a proper coordinate.
Ankit's code looks like it might do that, but test to make sure.
Try this.
String lat = Double.toString(latitude);
String lng = Double.toString(longitude);
lat= (float) (lat / 1E6);
lng = (float)(lon / 1E6);
System.out.println("lat :" + (float) lat / 1E6);
System.out.println("lon :" + (float) lon / 1E6);
You've got all the right data, so this question is really about formatting a double. Use DecimalFormat.
Use this to display the lat/lon points in your test:
DecimalFormat formatter = new DecimalFormat("0.0000000");
String lat = formatter.format(test.getLatitudeE6() / 1E6);
String lon = formatter.format(test.getLongitudeE6() / 1E6);
toAddress.setText(lat + " " + lon);
I am writing GPS coordinates to my JPEG image, and the coordinates are correct (as demonstrated by my logcat output) but it appears that it's being corrupted somehow. Reading the exif data results in either null values or, in the case of my GPS: 512.976698 degrees, 512.976698 degrees. Can anyone shed some light on this problem?
writing it:
try {
ExifInterface exif = new ExifInterface(filename);
exif.setAttribute(ExifInterface.TAG_GPS_LATITUDE, latitude);
exif.setAttribute(ExifInterface.TAG_GPS_LONGITUDE, longitude);
exif.saveAttributes();
Log.e("LATITUDE: ", latitude);
Log.e("LONGITUDE: ", longitude);
} catch (IOException e) {
e.printStackTrace();
}
and reading it:
try {
ExifInterface exif = new ExifInterface("/sdcard/globetrotter/mytags/"+ TAGS[position]);
Log.e("LATITUDE EXTRACTED", exif.getAttribute(ExifInterface.TAG_GPS_LATITUDE));
Log.e("LONGITUDE EXTRACTED", exif.getAttribute(ExifInterface.TAG_GPS_LONGITUDE));
} catch (IOException e) {
e.printStackTrace();
}
It goes in (for example) 37.715183, -117.260489 and comes out 33619970/65540, 14811136/3368550, 33619970/65540, 14811136/3368550. Am I doing it wrong?
EDIT:
So, the problem is I am not encoding it in the properly defined format, which is something like you see here:
Can anyone explain what this format is? Obviously the first number is 22/1 = 22 degrees, but I can't figure out how to compute the decimal there.
GPSLatitude
Indicates the latitude. The latitude is expressed as three
RATIONAL values giving the degrees,
minutes, and seconds, respectively.
If latitude is expressed as degrees,
minutes and seconds, a typical format
would be dd/1,mm/1,ss/1. When degrees
and minutes are used and, for
example, fractions of minutes are
given up to two decimal places, the
format would be dd/1,mmmm/100,0/1.
https://docs.google.com/viewer?url=http%3A%2F%2Fwww.exif.org%2FExif2-2.PDF
The Android docs specify this without explanation: http://developer.android.com/reference/android/media/ExifInterface.html#TAG_GPS_LATITUDE
Exif data is standardized, and GPS data must be encoded using geographical coordinates (minutes, seconds, etc) described above instead of a fraction. Unless it's encoded in that format in the exif tag, it won't stick.
How to encode: http://en.wikipedia.org/wiki/Geographic_coordinate_conversion
How to decode: http://android-er.blogspot.com/2010/01/convert-exif-gps-info-to-degree-format.html
Here is some code I've done to geotag my pictures. It's not heavily tested yet, but it seems to be ok (JOSM editor and exiftool read location).
ExifInterface exif = new ExifInterface(filePath.getAbsolutePath());
exif.setAttribute(ExifInterface.TAG_GPS_LATITUDE, GPS.convert(latitude));
exif.setAttribute(ExifInterface.TAG_GPS_LATITUDE_REF, GPS.latitudeRef(latitude));
exif.setAttribute(ExifInterface.TAG_GPS_LONGITUDE, GPS.convert(longitude));
exif.setAttribute(ExifInterface.TAG_GPS_LONGITUDE_REF, GPS.longitudeRef(longitude));
exif.saveAttributes();
And class GPS is here. (method could be shorter, but it's readable at least)
/*
* #author fabien
*/
public class GPS {
private static StringBuilder sb = new StringBuilder(20);
/**
* returns ref for latitude which is S or N.
* #param latitude
* #return S or N
*/
public static String latitudeRef(double latitude) {
return latitude<0.0d?"S":"N";
}
/**
* returns ref for latitude which is S or N.
* #param latitude
* #return S or N
*/
public static String longitudeRef(double longitude) {
return longitude<0.0d?"W":"E";
}
/**
* convert latitude into DMS (degree minute second) format. For instance<br/>
* -79.948862 becomes<br/>
* 79/1,56/1,55903/1000<br/>
* It works for latitude and longitude<br/>
* #param latitude could be longitude.
* #return
*/
synchronized public static final String convert(double latitude) {
latitude=Math.abs(latitude);
int degree = (int) latitude;
latitude *= 60;
latitude -= (degree * 60.0d);
int minute = (int) latitude;
latitude *= 60;
latitude -= (minute * 60.0d);
int second = (int) (latitude*1000.0d);
sb.setLength(0);
sb.append(degree);
sb.append("/1,");
sb.append(minute);
sb.append("/1,");
sb.append(second);
sb.append("/1000");
return sb.toString();
}
}
Other answers delivered nice background info and even an example. This is not a direct answer to the question but I would like to add an even simpler example without the need to do any math. The Location class delivers a nice convert function:
public String getLonGeoCoordinates(Location location) {
if (location == null) return "0/1,0/1,0/1000";
// You can adapt this to latitude very easily by passing location.getLatitude()
String[] degMinSec = Location.convert(location.getLongitude(), Location.FORMAT_SECONDS).split(":");
return degMinSec[0] + "/1," + degMinSec[1] + "/1," + degMinSec[2] + "/1000";
}
I stored the return value in my image and the tag is parsed fine. You can check your image and the geocoordinates inside here: http://regex.info/exif.cgi
Edit
#ratanas comment translated to code:
public boolean storeGeoCoordsToImage(File imagePath, Location location) {
// Avoid NullPointer
if (imagePath == null || location == null) return false;
// If we use Location.convert(), we do not have to worry about absolute values.
try {
// c&p and adapted from #Fabyen (sorry for being lazy)
ExifInterface exif = new ExifInterface(imagePath.getAbsolutePath());
exif.setAttribute(ExifInterface.TAG_GPS_LATITUDE, getLatGeoCoordinates(location));
exif.setAttribute(ExifInterface.TAG_GPS_LATITUDE_REF, location.getLatitude() < 0 ? "S" : "N");
exif.setAttribute(ExifInterface.TAG_GPS_LONGITUDE, getLonGeoCoordinates(location));
exif.setAttribute(ExifInterface.TAG_GPS_LONGITUDE_REF, location.getLongitude() < 0 ? "W" : "E");
exif.saveAttributes();
} catch (IOException e) {
// do something
return false;
}
// Data was likely written. For sure no NullPointer.
return true;
}
Here are some nice LatLong converter: latlong.net
ExifInterface exif = new ExifInterface(compressedImage.getPath());
exif.setAttribute(ExifInterface.TAG_GPS_LATITUDE,gpsTracker.dec2DMS(gpsTracker.getLatitude()));
exif.setAttribute(ExifInterface.TAG_GPS_LONGITUDE,gpsTracker.dec2DMS(gpsTracker.getLongitude()));
Convertor double to String
String dec2DMS(double coord) {
coord = coord > 0 ? coord : -coord;
String sOut = Integer.toString((int)coord) + "/1,";
coord = (coord % 1) * 60;
sOut = sOut + Integer.toString((int)coord) + "/1,";
coord = (coord % 1) * 60000;
sOut = sOut + Integer.toString((int)coord) + "/1000";
return sOut;
}
The most modern and shortest solution (with AndroidX) is using ExifInterface.setGpsInfo(Location), for example:
ExifInterface exif = new ExifInterface(filename);
Location location = new Location(""); //may be empty
location.setLatitude(latitude); //double value
location.setLongitude(longitude); //double value
exif.setGpsInfo(location)
exif.saveAttributes();
Sources: one and two
check android source code: https://android.googlesource.com/platform/frameworks/base/+/android-4.4.2_r2/core/java/android/hardware/Camera.java
/**
* Sets GPS longitude coordinate. This will be stored in JPEG EXIF
* header.
*
* #param longitude GPS longitude coordinate.
*/
public void setGpsLongitude(double longitude) {
set(KEY_GPS_LONGITUDE, Double.toString(longitude));
}
So it's a direct print, my log supports it as well: ExifInterface.TAG_GPS_LONGITUDE : -121.0553966
My conclusion is setting it as direct print is fine.