Geocoding and reverse geocoding [closed] - android

It's difficult to tell what is being asked here. This question is ambiguous, vague, incomplete, overly broad, or rhetorical and cannot be reasonably answered in its current form. For help clarifying this question so that it can be reopened, visit the help center.
Closed 10 years ago.
I am trying a simple app where i need to display a map.And when i click on any location it should return the address of that location.Can u please guide me as how to proceed with this.

I Found Google API is very handy for reverse Geo coding. For this I've created this class. You can directly use this class in your app :
public class getReverseGeoCoding
{
private String Address1 = "", Address2 = "", City = "", State = "", Country = "", County = "", PIN = "";
public void getAddress()
{
Address1 = ""; Address2 = ""; City = ""; State = ""; Country = ""; County = ""; PIN = "";
try {
JSONObject jsonObj = parser_Json.getJSONfromURL("http://maps.googleapis.com/maps/api/geocode/json?latlng="+ Global.curLatitude + "," + Global.curLongitude +"&sensor=true");
String Status = jsonObj.getString("status");
if(Status.equalsIgnoreCase("OK"))
{
JSONArray Results = jsonObj.getJSONArray("results");
JSONObject zero = Results.getJSONObject(0);
JSONArray address_components = zero.getJSONArray("address_components");
for(int i = 0; i<address_components.length(); i++)
{
JSONObject zero2 = address_components.getJSONObject(i);
String long_name = zero2.getString("long_name");
JSONArray mtypes = zero2.getJSONArray("types");
String Type = mtypes.getString(0);
if(TextUtils.isEmpty(long_name) == false || !long_name.equals(null) || long_name.length() > 0 || long_name != "" )
{
if(Type.equalsIgnoreCase("street_number"))
{
Address1 = long_name + " ";
}
else if(Type.equalsIgnoreCase("route"))
{
Address1 = Address1 + long_name;
}
else if(Type.equalsIgnoreCase("sublocality"))
{
Address2 = long_name;
}
else if(Type.equalsIgnoreCase("locality"))
{
// Address2 = Address2 + long_name + ", ";
City = long_name;
}
else if(Type.equalsIgnoreCase("administrative_area_level_2"))
{
County = long_name;
}
else if(Type.equalsIgnoreCase("administrative_area_level_1"))
{
State = long_name;
}
else if(Type.equalsIgnoreCase("country"))
{
Country = long_name;
}
else if(Type.equalsIgnoreCase("postal_code"))
{
PIN = long_name;
}
}
// JSONArray mtypes = zero2.getJSONArray("types");
// String Type = mtypes.getString(0);
// Log.e(Type,long_name);
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
public String getAddress1()
{
return Address1;
}
public String getAddress2()
{
return Address2;
}
public String getCity()
{
return City;
}
public String getState()
{
return State;
}
public String getCountry()
{
return Country;
}
public String getCounty()
{
return County;
}
public String getPIN()
{
return PIN;
}

Do you know how to display a map in your android app? If not you can take a look at this nice tutorial.
Then displaying address can be done like this:
Geocoder geocoder = new Geocoder(this, Locale.getDefault());
List<Address> addresses = geocoder.getFromLocation(lat, lng, 1);

for getting the coordinate of a click, check this thread:
Getting coordinates when clicking anywhere on a MapView
and you can turn a coordinate into an adress with this:
Address a = ((Address)geocoder.getFromLocation(latiAsDouble, longiAsDouble, 1).get(0));
String Position = a.getAddressLine(1) + " - " + a.getAddressLine(0);
this does a http call to a google server, so you might want to put this into some kind of thread.

Related

addresses from Geocoder size is always zero

i have the problem as this question and i also did the same hardcoding for the lat and lon.
i get the exception to confirm the size as
Exception for the locationjava.lang.IndexOutOfBoundsException: Invalid index 0, size is 0
When I try the same code on the Redmi a4, it works fine and give me the size as 1, and also the geocoding works fine, returning me all the addresses. The same code when I run on Lenovo it gives the exception. I checked the lat and lon and they have values which when i trace is pointing to my location. So what should I do to make the app run on both of the phones.
Lenovo phone running Android 4.4.4
Redmi running 6.0.0
if(lat != null && lon !=null) {
try{
Geocoder geocoder;
List<Address> addresses;
geocoder = new Geocoder(this, Locale.getDefault());
addresses = geocoder.getFromLocation(dlat, dlon, 1); // Here 1 represent max location result to returned, by documents it recommended 1 to 5
System.out.println("this is the size of address size"+addresses.size());
String address = addresses.get(0).getAddressLine(0); // If any additional address line present than only, check with max available address lines by getMaxAddressLineIndex()
String city = addresses.get(0).getLocality();
String state = addresses.get(0).getAdminArea();
String country = addresses.get(0).getCountryName();
String postalCode = addresses.get(0).getPostalCode();
String knownName = addresses.get(0).getFeatureName();
complete_address=address + "_" + city + "_" + address + "_" + postalCode + "_" + knownName + "_" + country;
txtOutputLat.setText(complete_address);
txtOutputLon.setText("Map Address");
}
catch(Exception e)
{
System.out.println("Exception for the location"+e.toString());
}
}
Create this class and copy the code this works perfectly for me also this works in background and stops the main thread from ANR dialog
import android.content.Context;
import android.location.Address;
import android.location.Geocoder;
import android.os.AsyncTask;
import java.io.IOException;
import java.util.List;
import java.util.Locale;
public class GetLocationAsync extends AsyncTask<String, Void, String> {
private String fulladdress = "";
private String smallAddress = "";
private String city = "";
private String state = "";
private String country = "";
private String zipcode = "";
private String placeName = "";
private AsyncResponse asyncResponseDelegate = null;
private double x, y;
private Context context;
public interface AsyncResponse {
void onProcessFinished(String fulladdress, String smallAddress, String state, String city, String country, String zipCode, String placeName);
}
public GetLocationAsync(double latitude, double longitude, final Context context, AsyncResponse asyncResponse) {
x = latitude;
y = longitude;
this.context = context;
this.asyncResponseDelegate = asyncResponse;
}
#Override
protected void onPreExecute() {
}
#Override
protected String doInBackground(String... params) {
Geocoder geocoder = new Geocoder(context, Locale.ENGLISH);
try {
List<Address> addressList = geocoder.getFromLocation(x, y, 1);
StringBuilder sb = new StringBuilder();
if (addressList != null && addressList.size() > 0) {
Address address = addressList.get(0);
fulladdress = "";
smallAddress = "";
placeName = "";
if (sb.append(address.getAddressLine(0)) != null) {
smallAddress = address.getAddressLine(0);
fulladdress = smallAddress;
}
if (address.getLocality() != null) {
city = address.getLocality();
if (!fulladdress.contains(city))
fulladdress = fulladdress + " " + city;
}
if (address.getFeatureName() != null) {
placeName = address.getFeatureName();
}
if (address.getAdminArea() != null) {
state = address.getAdminArea();
if (!fulladdress.contains(state))
fulladdress = fulladdress + " " + state;
}
if (address.getPostalCode() != null) {
zipcode = address.getPostalCode();
if (!fulladdress.contains(zipcode))
fulladdress = fulladdress + " " + zipcode;
}
if (address.getCountryName() != null) {
country = address.getCountryName();
if (!fulladdress.contains(country))
fulladdress = fulladdress + " " + country;
}
}
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(String result) {
try {
if (fulladdress != null && !fulladdress.isEmpty()) {
asyncResponseDelegate.onProcessFinished(fulladdress, smallAddress, state, city, country, zipcode, placeName);
} else {
asyncResponseDelegate.onProcessFinished("", "", "", "", "", "", "");
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
to call this class
GetLocationAsync locationAsync = new GetLocationAsync(latitude,
longitude, getActivity(), new GetLocationAsync.AsyncResponse() {
#Override
public void onProcessFinished(String fulladdress, String smallAddress, String state, String city, String country, String zipCode, String placeName) {
etAddress.setText(fulladdress);
}
});
locationAsync.execute();
What happens is when you try to get the postal code,city,country etc etc only from the address is that you might not recieve it for the very first time since its trying to get all zipcode, country, state and city from a single provider, which may not be available at times. Instead if you loop through the providers you may find it in one of them. Try this hope it helps!
List<Address> addresses = null;
try {
addresses =geocoder.getFromLocation(latitude,longitude, 5);
if (addresses.size() > 0) {
zipCode = addresses.get(0).getPostalCode();
city = addresses.get(0).getLocality();
country = addresses.get(0).getCountryName();
state = addresses.get(0).getAdminArea();
address = addresses.get(0).getAddressLine(0);
knownName = addresses.get(0).getFeatureName();
//if 1st provider does not have data, loop through other providers to find it.
int count = 0;
while ( count < addresses.size()) {
zipCode = addresses.get(count).getPostalCode();
city= addresses.get(count).getLocality();
country = addresses.get(count).getCountryName();
state = addresses.get(count).getAdminArea();
address = addresses.get(count).getAddressLine(0);
knownName = addresses.get(count).getFeatureName();
count++;
}
}
} catch (IOException e) {
e.printStackTrace();
}
Check for internet connection before calling geocoder.
if(isConnectingToInternet(getContext()){
//write your code of calling geocoder
}
public boolean isConnectingToInternet(Context context) {
try {
if (context != null) {
ConnectivityManager connectivity = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
if (connectivity != null) {
NetworkInfo[] info = connectivity.getAllNetworkInfo();
if (info != null)
for (int i = 0; i < info.length; i++)
if (info[i].getState() == NetworkInfo.State.CONNECTED) {
return true;
}
}
}
} catch (Exception e) {
e.printStacktrace
}
return false;
}

Android get Device Country Code

I want to get device country code with out using sim card.
e.g If Country : Sri lanka
Country code : LK
my final goal is get calling code (+94 for sri lanka)
i tried with this
TelephonyManager tm = (TelephonyManager)this.getSystemService(getApplicationContext().TELEPHONY_SERVICE);
String countryCodeValue = tm.getNetworkCountryIso();
but this return empty string
It's returning an empty string because the device doesn't have a sim card.
You might be able to use the device's current locale:
Locale current = getResources().getConfiguration().locale;
but that's not necessarily going to be the same as what you'd get by looking at the carrier iso and the user can update that in the settings whenever they want to whatever they want. As pointed out, you can also ask the location manager for the user's coordinates. But remember, users move around and their current location may not always correspond to their carrier's iso.
Here is a complete example. Try to get country code from TelephonyManager (from SIM or CDMA devices), and if not available try to get it from local configuration.
private static String getDeviceCountryCode(Context context) {
String countryCode;
// try to get country code from TelephonyManager service
TelephonyManager tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
if(tm != null) {
// query first getSimCountryIso()
countryCode = tm.getSimCountryIso();
if (countryCode != null && countryCode.length() == 2)
return countryCode.toLowerCase();
if (tm.getPhoneType() == TelephonyManager.PHONE_TYPE_CDMA) {
// special case for CDMA Devices
countryCode = getCDMACountryIso();
} else {
// for 3G devices (with SIM) query getNetworkCountryIso()
countryCode = tm.getNetworkCountryIso();
}
if (countryCode != null && countryCode.length() == 2)
return countryCode.toLowerCase();
}
// if network country not available (tablets maybe), get country code from Locale class
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
countryCode = context.getResources().getConfiguration().getLocales().get(0).getCountry();
} else {
countryCode = context.getResources().getConfiguration().locale.getCountry();
}
if (countryCode != null && countryCode.length() == 2)
return countryCode.toLowerCase();
// general fallback to "us"
return "us";
}
#SuppressLint("PrivateApi")
private static String getCDMACountryIso() {
try {
// try to get country code from SystemProperties private class
Class<?> systemProperties = Class.forName("android.os.SystemProperties");
Method get = systemProperties.getMethod("get", String.class);
// get homeOperator that contain MCC + MNC
String homeOperator = ((String) get.invoke(systemProperties,
"ro.cdma.home.operator.numeric"));
// first 3 chars (MCC) from homeOperator represents the country code
int mcc = Integer.parseInt(homeOperator.substring(0, 3));
// mapping just countries that actually use CDMA networks
switch (mcc) {
case 330: return "PR";
case 310: return "US";
case 311: return "US";
case 312: return "US";
case 316: return "US";
case 283: return "AM";
case 460: return "CN";
case 455: return "MO";
case 414: return "MM";
case 619: return "SL";
case 450: return "KR";
case 634: return "SD";
case 434: return "UZ";
case 232: return "AT";
case 204: return "NL";
case 262: return "DE";
case 247: return "LV";
case 255: return "UA";
}
} catch (ClassNotFoundException ignored) {
} catch (NoSuchMethodException ignored) {
} catch (IllegalAccessException ignored) {
} catch (InvocationTargetException ignored) {
} catch (NullPointerException ignored) {
}
return null;
}
Also another idea is to try an API request like in this answer, or to use fine location.
And in order to get country prefix you can use LibPhoneNumber library from Google.
References here and here
You can use this http://maps.googleapis.com/maps/api/geocode/json?latlng=7.0000,81.0000&sensor=false for getting country code ..The short name will give you country code ..
public void getAddress(double lat,double lng) {
Address1 = "";
Address2 = "";
City = "";
State = "";
Country = "";
County = "";
PIN = "";
try {
JSONObject jsonObj = JsonParser.getJSONfromURL("http://maps.googleapis.com/maps/api/geocode/json?latlng=" + lat + ","
+lng + "&sensor=false");
String Status = jsonObj.getString("status");
if (Status.equalsIgnoreCase("OK")) {
JSONArray Results = jsonObj.getJSONArray("results");
JSONObject zero = Results.getJSONObject(0);
JSONArray address_components = zero.getJSONArray("address_components");
for (int i = 0; i < address_components.length(); i++) {
JSONObject zero2 = address_components.getJSONObject(i);
String long_name = zero2.getString("long_name");
String short_name = zero2.getString("short_name");
JSONArray mtypes = zero2.getJSONArray("types");
String Type = mtypes.getString(0);
if (TextUtils.isEmpty(long_name) == false || !long_name.equals(null) || long_name.length() > 0 || long_name != "") {
if (Type.equalsIgnoreCase("street_number")) {
Address1 = long_name + " ";
} else if (Type.equalsIgnoreCase("route")) {
Address1 = Address1 + long_name;
} else if (Type.equalsIgnoreCase("sublocality")) {
Address2 = long_name;
} else if (Type.equalsIgnoreCase("locality")) {
// Address2 = Address2 + long_name + ", ";
City = long_name;
} else if (Type.equalsIgnoreCase("administrative_area_level_2")) {
County = long_name;
} else if (Type.equalsIgnoreCase("administrative_area_level_1")) {
State = long_name;
} else if (Type.equalsIgnoreCase("country")) {
Country = short_name;
} else if (Type.equalsIgnoreCase("postal_code")) {
PIN = long_name;
}
}
// JSONArray mtypes = zero2.getJSONArray("types");
// String Type = mtypes.getString(0);
// Log.e(Type,long_name);
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
But you need to get the current lat and long ..
Use this link for getting the current lat and lng
http://gabesechansoftware.com/location-tracking/
In my case telephonyManager.getNetworkCountryIso() is returning empty as i have two sim slots, you can pass slot as parameter if it returns "". Simply change your code to:
String iso=telephonyManager.getNetworkCountryIso();
if(TextUtils.isEmpty(iso))
iso=telephonyManager.getNetworkCountryIso(1);
if(TextUtils.isEmpty(iso))
iso=telephonyManager.getNetworkCountryIso(2);
// this code will give preference to Sim Slot 1
get iso country code => US
lookup this table => 1
https://countrycode.org/

Google Maps API calls failing on Android, "automated queries" error

I'm retrieving addresses from cooridnates using the Google API with the following method:
public static String[] getFromLocation(double lat, double lng, int retries) {
String address = String.format(Locale.getDefault(),
"https://maps.googleapis.com/maps/api/geocode/json?latlng=%1$f,%2$f&sensor=false&language="
+ Locale.getDefault(), lat, lng);
String[] res = new String[3];
String addressLine = "";
String locality = "";
String country = "";
String json = null;
HttpURLConnection conn = null;
StringBuilder jsonResults = new StringBuilder();
try {
URL url = new URL(address);
conn = (HttpURLConnection) url.openConnection();
InputStreamReader in = new InputStreamReader(conn.getInputStream());
int read;
char[] buff = new char[1024];
while ((read = in.read(buff)) != -1) {
jsonResults.append(buff, 0, read);
}
json = jsonResults.toString();
JSONObject jsonObject = new JSONObject(json);
if ("OK".equalsIgnoreCase(jsonObject.getString("status"))) {
JSONArray results = jsonObject.getJSONArray("results");
if (results.length() > 0) {
JSONObject result = results.getJSONObject(0);
//Address addr = new Address(Locale.getDefault());
JSONArray components = result.getJSONArray("address_components");
String streetNumber = "";
String route = "";
for (int a = 0; a < components.length(); a++) {
JSONObject component = components.getJSONObject(a);
JSONArray types = component.getJSONArray("types");
for (int j = 0; j < types.length(); j++) {
String type = types.getString(j);
if (type.equals("locality")) {
locality = component.getString("long_name");
} else if (type.equals("street_number")) {
streetNumber = component.getString("long_name");
} else if (type.equals("route")) {
route = component.getString("long_name");
} else if (type.equals("country")) {
country = component.getString("long_name");
}
}
}
addressLine = route + " " + streetNumber;
}
}
} catch (Exception e) {
Log.e(LOG_TAG, "Exception:", e);
LogsToServer.send(my_id, e);
if (json != null) LogsToServer.send(my_id, json);
System.out.println("retries: " + retries);
if (retries > 0){
try {
Thread.sleep(500);
} catch (InterruptedException e1) {
e1.printStackTrace();
}
return getFromLocation(lat, lng, retries-1);
}
}
res[0] = addressLine;
res[1] = locality;
res[2] = country;
return res;
}
The problem is that I very often get the exception:
03-12 23:54:01.387: E/GetAddressDetails(25248): java.io.FileNotFoundException: https://maps.googleapis.com/maps/api/geocode/json?latlng=48,2&sensor=false&language=en_GB
03-12 23:54:01.387: E/GetAddressDetails(25248): at com.android.okhttp.internal.http.HttpURLConnectionImpl.getInputStream(HttpURLConnectionImpl.java:197)
03-12 23:54:01.387: E/GetAddressDetails(25248): at com.android.okhttp.internal.http.DelegatingHttpsURLConnection.getInputStream(DelegatingHttpsURLConnection.java:210)
03-12 23:54:01.387: E/GetAddressDetails(25248): at com.android.okhttp.internal.http.HttpsURLConnectionImpl.getInputStream(HttpsURLConnectionImpl.java:25)
If I launch the method with 4 retries, they may all fail, or sometimes after 2 or 3 I get the address. Do you know why it fails so often? When I access the same site in my browser I always get the page without errors!
EDIT: I checked the error message returned by Google and it goes like this:
We're sorry... but your computer or network may be sending automated queries. To protect our users, we can't process your request right now.
Is it a joke? Automated queries? Isn't it the whole purpose of APIs to be called by automatic processes?
Also, this happens from many phones and started yesterday. How does google know that all the requests come from the same app?
If you want to get address from cooridnates, you can use Geocoder api.
I used following code in my app to get the city name:
private double mLongitude; // current longitude
private double mLatitude; // current latitude
private String mCityName; // output cityName
private void getCityName() {
Geocoder gcd = new Geocoder(this, Locale.getDefault());
List<Address> addresses;
try {
addresses = gcd.getFromLocation(mLatitude, mLongitude, 1);
if (addresses.size() != 0) {
mCityName = addresses.get(0).getAddressLine(1);
mCityName = mCityName.replaceAll("[\\d.]", "");
Log.d(TAG + "!!!!!!!!!!!", mCityName);
}
} catch (IOException e) {
e.printStackTrace();
}
}
If you want get whole address, as I changed a little bit, just do this way:
private double mLongitude; // current longitude
private double mLatitude; // current latitude
private String mAddress; // output address
private void getAddress() {
Geocoder gcd = new Geocoder(this, Locale.getDefault());
List<Address> addresses;
try {
addresses = gcd.getFromLocation(mLatitude, mLongitude, 1);
if (addresses.size() != 0) {
mAddress = addresses.get(0).getAddressLine(0) + " " +
addresses.get(0).getAddressLine(1) + " " +
addresses.get(0).getAddressLine(2);
//mAddress = mAddress.replaceAll("[\\d.]", "");
Log.d(TAG + "!!!!!!!!!!!", mAddress);
}
} catch (IOException e) {
e.printStackTrace();
}
}

Extracting the City and State from Geocoder in Android

I'm attempting to extract the City and State only from the Geocoder in Android. I've gotten pretty far to where it extracts the city fine, but the state I'm having issues with its printing the zip along side it.
I'm looking for "City, State" whereas the final output now is "City, State Zip"
Any ideas?
Geocoder geoCoder = new Geocoder(getActivity(), Locale.getDefault());
List<Address> addresses;
try {
addresses = geoCoder.getFromLocation(mLatitude, mLongitude, 10);
int i=1;
for(Address addObj:addresses)
{
// Looping once
if(i==1)
{
String add_line1_extract;
add_line1_extract=addObj.getAddressLine(1);
String string = add_line1_extract;
String[] parts = string.split(",");
//Setting city
mCity = parts[0];
//setting state
mState = parts[1];
// Final Output
String cityAndState = mCity + ", " + mState;
i++;
}
}
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
You could get the state name by calling the getAdminArea() method from Address class. However, it might not work for all the countries. Also, you could call the getLocality() to retrieve the city name.
So for your code, you can do the following:
String cityName = addObject.getLocality();
String stateName = addObject.getAdminArea();
String cityAndState = cityName + ", " + stateName;
If you want the abbreviation of a state name, you can do further split in your String[] parts. You can do the following:
String[] moreSplit = parts[1].split(" ");
String mStateAbbr = moreSplit[0];
String mCityAndStateAbbr = mCity + mStateAbbr;

Initialize the value of a arraylist

I can't understand what is wrong in my code . I am getting error in myAddressUniqueness. don't know why.Before i have tried it with string data type but got the same error. It is saying java.null exception.
ArrayList<String> myAddressUniqueness = null;
String name = "hello";
if (indexBody < 0 || !cursor.moveToFirst())
return;
smsList.clear();
do {
// int cursorPostion = cursor.getPosition();
String address;
String msgStr = cursor.getString(indexBody);
String senderNumber = cursor.getString(indexAddr);
Log.d("Name : ", senderNumber);
// String name = cursor.getString(cursor
// .getColumnIndex(PhoneLookup.DISPLAY_NAME));
// Log.d("Name : ",name);
if (name != null) {
address = name;
} else {
address = senderNumber;
}
Log.d("Address: ", address);
flag = 1;
//Log.e("Number: ", addressUniqueness.length + "");
for (j = 0; j < myAddressUniqueness.size(); j++) {
if (myAddressUniqueness.contains(address)) {
flag = 0;
break;
}
}
if (flag == 1) {
myAddressUniqueness.add(new String(address));
i++;
String str = "Sender: " + address + "\n";
smsList.add(str);
}
// TODO Auto-generated catch block
} while (cursor.moveToNext());
Change your declaration to
ArrayList<String> myAddressUniqueness = new ArrayList<String>();
You have it initialized to null. This will instantiate it then you can add data to it.
You should instantiate myAddressUniqueness by myAddressUniqueness = new ArrayList<String>() before using it.

Categories

Resources