I am trying to parse this: https://s3.amazonaws.com/dolartoday/data.json for an Android app that shows the dollar to bolivar unofficial exchange rate.
I am using this tutorial: http://www.androidhive.info/2012/01/android-json-parsing-tutorial/, which I have used successfully before, however previous APIs I have used consisted of a JSON array with child objects. This one, however, has 12 JSON objects with strings. No square brackets to be seen.
The part (I think) I'm having trouble with is:
if (jsonStr != null) {
try {
JSONObject jsonObj = new JSONObject(jsonStr);
// Getting JSON Array node
JSONArray contacts = jsonObj.getJSONArray("contacts");
// looping through All Contacts
for (int i = 0; i < contacts.length(); i++) {
JSONObject c = contacts.getJSONObject(i);
String id = c.getString("id");
String name = c.getString("name");
String email = c.getString("email");
String address = c.getString("address");
String gender = c.getString("gender");
// Phone node is JSON Object
JSONObject phone = c.getJSONObject("phone");
String mobile = phone.getString("mobile");
String home = phone.getString("home");
String office = phone.getString("office");
}
} catch (final JSONException e) {
Log.e(TAG, "Json parsing error: " + e.getMessage());
runOnUiThread(new Runnable() {
#Override
public void run() {
Toast.makeText(getApplicationContext(),
"Json parsing error: " + e.getMessage(),
Toast.LENGTH_LONG)
.show();
}
});
}
}
I'm no expert, since I'm trying to learn programming on my own and I'm still very new. However, I have made some changes including getting rid of the ListView, and adapting the code to the new JSON.
if (jsonStr != null) {
try {
JSONObject jsonObj = new JSONObject(jsonStr);
// Getting JSON Object node
JSONObject c = jsonObj.getJSONObject("USD");
JSONObject d = jsonObj.getJSONObject("EUR");
String usdtrans = c.getString("dolartoday");
String usdreal = c.getString("efectivo_real");
String usddicom = c.getString("sicad2");
String eurtrans = d.getString("dolartoday");
String eurreal = d.getString("efectivo_real");
String eurdicom = d.getString("sicad2");
}
} catch (final JSONException e) {
Log.e(TAG, "Json parsing error: " + e.getMessage());
runOnUiThread(new Runnable() {
#Override
public void run() {
Toast.makeText(getApplicationContext(),
"Json parsing error: " + e.getMessage(),
Toast.LENGTH_LONG)
.show();
}
});
}
}
The code does not compile, and Android Studio detects an "unhandled exception: org.json.JSONException". What can I do to change this?
Any help would be appreciated. The rest of my code has other issues as well, but I think I can sort those out once I can get this one done.
While using org.json library classes, If the JSON response consists of square bracket "[" then we need to get that element as JSONArray else get the element as JSONObject.
try {
JSONObject jsonObject = new JSONObject(jsonString);
JSONObject antibloqueo = jsonObject.getJSONObject("_antibloqueo");
JSONObject labels = jsonObject.getJSONObject("_labels");
JSONObject timestamp = jsonObject.getJSONObject("_timestamp");
JSONObject USD = jsonObject.getJSONObject("USD");
JSONObject EUR = jsonObject.getJSONObject("EUR");
JSONObject COL = jsonObject.getJSONObject("COL");
JSONObject GOLD = jsonObject.getJSONObject("GOLD");
JSONObject USDVEF = jsonObject.getJSONObject("USDVEF");
JSONObject USDCOL = jsonObject.getJSONObject("USDCOL");
JSONObject EURUSD = jsonObject.getJSONObject("EURUSD");
JSONObject BCV = jsonObject.getJSONObject("BCV");
JSONObject MISC = jsonObject.getJSONObject("MISC");
//To get Values From antibloqueo
String mobile = antibloqueo.getString("mobile");
String video = antibloqueo.getString("video");
//To get Values From labels
String a = labels.getString("DOLARTODAY");
String a1 = labels.getString("a1");
} catch (JSONException e) {
Log.e("TAG", "Json parsing error: " + e.getMessage());
}
Note:
While working with smaller projects you can use org.json library as the JSON Convertor. For the bigger projects you have to use other libraries like Gson /Jackson
https://www.mkyong.com/java/how-do-convert-java-object-to-from-json-format-gson-api/
I could not find the correct information on this subject. The problem has already been mentioned, but there is no correct solution. No problem with request like:
#FormUrlEncoded
#POST("/guide/confirm")
Call<Model> confirm(#Field("step") String step, #Field("code") String code);
But, what is correct (!) way do encode all object, which has three or more list of other object. Parent and child object fields most converted with UrlEncoded.
// What need to do, to encode all data below?
#POST("/guide/loadinfo")
Call<Model> confirm(#Body VeryBigJsonObject object);
There was solution using TypedObject - but now is functions is deprecated, and it is not a new retrofit. I hope you can help.
JakeWharton says in some issues, that my json is not url enoded form (its too large). That is mean, that I cannot send my request to server using Retrofit? Some example json: http://www.jsoneditoronline.org/?id=661b2bae9eb520902825a58f8d44c338
I have so much troubles with sending whole class with form-urlencoded, because our server does not allow json.
I don't think it's correct way, but i dont find any better solution.
(i tried send my class by fields, but retrofit can't encode arrays in fields correctly)
After spending a lot of time, i did it like this:
public static RequestBody objectToRequestBody(Object obj)
{
String jsonString = new Gson().toJson(obj);
String reqestText = "";
try {
Object jsonObj = new JSONObject(jsonString);
reqestText = Tools.jsonToURLEncodingAux(jsonObj,"",0);
} catch (JSONException e) {
e.printStackTrace();
}
String mediaType = "application/x-www-form-urlencoded";
return RequestBody.create(okhttp3.MediaType.parse(mediaType), reqestText);
}
public static String jsonToURLEncodingAux(Object json, String prefix, int level) {
String output = "";
if (json instanceof JSONObject) {
JSONObject obj = (JSONObject)json;
Iterator<String> keys1 = obj.keys();
while (keys1.hasNext())
{
String currKey = keys1.next();
String subPrefix = "";
if(level>0) {
subPrefix = prefix + "[" + currKey + "]";
} else {
subPrefix = prefix + currKey;
}
try {
output += jsonToURLEncodingAux(obj.get(currKey), subPrefix, level + 1);
} catch (JSONException e) {
e.printStackTrace();
}
}
} else if (json instanceof JSONArray) {
JSONArray jsonArr = (JSONArray) json;
int arrLen = jsonArr.length();
for (int i = 0; i < arrLen; i++) {
String subPrefix = prefix + "[" + i + "]";
Object child = null;
try {
child = jsonArr.get(i);
output += jsonToURLEncodingAux(child, subPrefix, level + 1);
} catch (JSONException e) {
e.printStackTrace();
}
}
} else {
output = prefix + "=" + json.toString() + "&";
}
return output;
}
interface:
#Headers("Cache-Control: max-age=259200")
#POST("api/route/report/")
Observable<ReportResponsePOJO> sendReport(
#Header("Content-Type") String content_type,
#Body RequestBody report
);
and send it like this
Observable<ReportResponsePOJO> myResponsePOJOObservable = apiInterface
.sendReport(
"application/x-www-form-urlencoded",
objectToRequestBody(report))
.subscribeOn(Schedulers.io());
I hope it will work, at least for me.
In my app user types a location and I have to get latitude and longitude for that location. So here I don't have Location object but a String.
I thought of an option to create a Location object using this String but it is not possible.
I know using Google's places API it is possible and I know how to use that, but I prefer using any method available in SDK.
Is there any way to do so?
You can use Geocoder. Like this :
Geocoder geocoder = new Geocoder(App.getContext(), Locale.US);
List<Address> listOfAddress;
try {
listOfAddress = geocoder.getFromLocation(theLatitude, theLongitude, 1);
if(listOfAddress != null && !listOfAddress.isEmpty()){
Address address = listOfAddress.get(0);
String country = address.getCountryCode();
String adminArea= address.getAdminArea();
String locality= address.getLocality();
}
} catch (IOException e) {
e.printStackTrace();
}
Updated : to get location from address use :
listOfAddress = geocoder.getFromLocationName("Address", 1);
and to get lat, lon :
double latitude = address.getLatitude();
double longitude = address.getLongitude();
Updated : using this snippet to get Location when Geocoder returns null:
private static final String URL = "http://maps.googleapis.com/maps/api/geocode/xml";
public static RemoteCommand getLocation(String theAddress){
RemoteCommand result = new RemoteCommand();
result.setType(Type.GET);
result.setUrl(URL);
result.addGetParam("address", theAddress);
result.addGetParam("sensor", "false");
result.addGetParam("language", "en");
// See description about GeocoderXMLHandler
result.setXmlHandler(new GeocoderXMLHandler());
return result;
}
Best wishes.
String UrlCity = "http://maps.googleapis.com/maps/api/geocode/json?address=" + NameString + "&sensor=false";
JsonObjectRequest stateReq = new JsonObjectRequest(Request.Method.GET, UrlState, null, new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
JSONObject location;
try {
// Get JSON Array called "results" and then get the 0th
// complete object as JSON
location = response.getJSONArray("results").getJSONObject(0).getJSONObject("geometry").getJSONObject("location");
// Get the value of the attribute whose name is
// "formatted_string"
stateLocation = new LatLng(location.getDouble("lat"), location.getDouble("lng"));
// System.out.println(stateLocation.toString());
} catch (JSONException e1) {
e1.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Log.d("Error.Response", error.toString());
}
});
// add it to the RequestQueue
reqQueue.add(stateReq);
you get coordinates from given name. This is done by using Google Volley library, or you can do it by a simple http call wrapped in AsyncTask or runnable.
Hope it helps!
There is only one possibilty(other than Google geocode API) to get latitude and longitude as stated by yakiv.mospan. But Geocoder always returns me null and so is the case for many people. This I come to know by searching this issue of returning null on stackoverflow.com.
After all, I decided to use Google places API as there is no other option available.
You can look at :
http://developer.android.com/reference/android/location/Geocoder.html
The getFromLocationName method can help you.
Use the Google Geocoding API to get coordinates for an address. http://code.google.com/apis/maps/documentation/javascript/services.html#Geocoding
In this detail infromation on how to use is given.
Also below is sample URL so check response and see whether this is useful for you or not.
http://maps.googleapis.com/maps/api/geocode/json?address=ahmedabad&sensor=false
Here you can use this code:
String add = address + "," + city + "," + country;
String addressUrl = "http://maps.googleapis.com/maps/api/geocode/json?address="
+ URLEncoder.encode(add.replaceAll(" ", "+"))
+ "&sensor=true";
try {
HttpClient httpClient = new DefaultHttpClient();// Client
HttpGet getRequest = new HttpGet();
getRequest.setURI(new URI(addressUrl));
// HttpPost postRequest = new HttpPost();
// postRequest.setURI(new URI(url));
HttpResponse response = httpClient.execute(getRequest);
in = new BufferedReader(new InputStreamReader(response
.getEntity().getContent()));
StringBuffer sb = new StringBuffer("");
String line = "";
String NL = System.getProperty("line.separator");
while ((line = in.readLine()) != null) {
sb.append(line + NL);
}
in.close();
String page = sb.toString();
JSONObject jsonObject = new JSONObject(page);
if (jsonObject.has("results")) {
JSONArray jsonArray = (JSONArray) jsonObject.get("results");
if (jsonArray.length() > 0) {
jsonObject = (JSONObject) jsonArray.get(0);
if (jsonObject.has("geometry")) {
jsonObject = (JSONObject) jsonObject
.get("geometry");
if (jsonObject.has("location")) {
JSONObject location = (JSONObject) jsonObject
.get("location");
latitude = (Double) location.get("lat");
longitude = (Double) location.get("lng");
Log.e(TAG, "lat : " + latitude + " long : "
+ longitude);
}
}
}
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (in != null) {
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
Here are more links that can help you:
Google Map V2
Google Places API Demo
you can use this,
Geocoder geocoder = new Geocoder(this, Locale.getDefault());
geocoder.getFromLocation(LATITUDE, LONGITUDE, 3);
I know sometimes google back-end service might not be available.
Hence a solution might be to loop until i get the data.
private class getLocationDetails extends AsyncTask<String, Void, String> {
#Override
protected String doInBackground(String... params) {
Log.d("looping", "" + count + "");
count++;
double lat = Double.parseDouble(params[0]);
double lng = Double.parseDouble(params[1]);
List<Address> addresses = null;
try {
Geocoder gCoder = new Geocoder(ImageAndLocationActivity.this,
Locale.getDefault());
addresses = gCoder.getFromLocation(lat, lng, 1);
Address addr = addresses.get(0);
user_country = addr.getCountryName();
user_city = addr.getLocality();
user_district = addr.getSubAdminArea();
if (user_city == null) {
user_city = user_district;
}
} catch (Exception e) {
Log.e("Exception in getLocationDetails - ", e.getMessage());
return null;
}
return "";
}
#Override
protected void onPostExecute(String result) {
if (result != null) {
Log.d("user_city = ", "" + user_city);
} else {
new getLocationDetails().execute(CurrentLat + "", CurrentLng
+ "");
}
}
#Override
protected void onPreExecute() {
}
#Override
protected void onProgressUpdate(Void... values) {
}
}
But i am not able to get the location at all:
LogCat:
02-27 16:29:49.568: D/looping(10966): 110355
02-27 16:29:49.568: E/Exception in getLocationDetails -(10966): Service not Available
02-27 16:29:49.573: D/looping(10966): 110356
02-27 16:29:49.573: E/Exception in getLocationDetails -(10966): Service not Available
02-27 16:29:49.573: D/looping(10966): 110357
02-27 16:29:49.573: E/Exception in getLocationDetails -(10966): Service not Available
and ofcourse i have added all the needed permissions:
<uses-permission android:name="android.permission.INTERNET" />
I am trying this on Samsung Galaxy Note GT-N7000 (4.0.4 version)
Am i missing any settings? related to device or application ? Or this usually happens? If so any better solution to resolve this??
Thank You
The actual reason why Geocoder was not working is because the NetworkLocator was killed in action. Probably due to less memory or maybe you used the Task Manager to kill all services?
I'm not sure but this is a guess. I've seen this before. Last year I wrote a reconnect mechanism to load the NetworkLocator.apk and bind to the GeocoderService. I think this change has not merged into JellyBean so this problem persists.
It can be only solved by reboot. (The NetworkLocationService is loaded at boot)
Edit: You won't see this problem in JBP or KK, this service is moved into the playstore app .
Workaround using direct access to google maps:
public static LatLng getLocationFromString(String address)
throws JSONException {
HttpGet httpGet = new HttpGet(
"http://maps.google.com/maps/api/geocode/json?address="
+ URLEncoder.encode(address, "UTF-8") + "&ka&sensor=false");
HttpClient client = new DefaultHttpClient();
HttpResponse response;
StringBuilder stringBuilder = new StringBuilder();
try {
response = client.execute(httpGet);
HttpEntity entity = response.getEntity();
InputStream stream = entity.getContent();
int b;
while ((b = stream.read()) != -1) {
stringBuilder.append((char) b);
}
} catch (ClientProtocolException e) {
} catch (IOException e) {
}
JSONObject jsonObject = new JSONObject(stringBuilder.toString());
double lng = ((JSONArray) jsonObject.get("results")).getJSONObject(0)
.getJSONObject("geometry").getJSONObject("location")
.getDouble("lng");
double lat = ((JSONArray) jsonObject.get("results")).getJSONObject(0)
.getJSONObject("geometry").getJSONObject("location")
.getDouble("lat");
return new LatLng(lat, lng);
}
public static List<Address> getStringFromLocation(double lat, double lng)
throws ClientProtocolException, IOException, JSONException {
String address = String
.format(Locale.ENGLISH, "http://maps.googleapis.com/maps/api/geocode/json?latlng=%1$f,%2$f&sensor=true&language="
+ Locale.getDefault().getCountry(), lat, lng);
HttpGet httpGet = new HttpGet(address);
HttpClient client = new DefaultHttpClient();
HttpResponse response;
StringBuilder stringBuilder = new StringBuilder();
List<Address> retList = null;
response = client.execute(httpGet);
HttpEntity entity = response.getEntity();
InputStream stream = entity.getContent();
int b;
while ((b = stream.read()) != -1) {
stringBuilder.append((char) b);
}
JSONObject jsonObject = new JSONObject(stringBuilder.toString());
retList = new ArrayList<Address>();
if ("OK".equalsIgnoreCase(jsonObject.getString("status"))) {
JSONArray results = jsonObject.getJSONArray("results");
for (int i = 0; i < results.length(); i++) {
JSONObject result = results.getJSONObject(i);
String indiStr = result.getString("formatted_address");
Address addr = new Address(Locale.getDefault());
addr.setAddressLine(0, indiStr);
retList.add(addr);
}
}
return retList;
}
Restart the device and it will fix the issue.
API will throw a "Service not Available exception" if such service is unavailable on the device. Use method isPresent() to check for the existence of the service.
See also: http://developer.android.com/reference/android/location/Geocoder.html
The best fix for this problem is to use the same like Google Geocoder class if the original Geocoder fail
List<Address> addresses = null;
Geocoder geocoder = new Geocoder(this);
addresses = geocoder.getFromLocation(...);
if (addresses == null || addresses.isEmpty())
addresses = MyGeocoder.getFromLocation(...);
import android.location.Address;
import android.util.Log;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.params.AllClientPNames;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.util.EntityUtils;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
public class MyGeocoder {
public static List<Address> getFromLocation(double lat, double lng, int maxResult) {
String address = String.format(Locale.ENGLISH, "http://maps.googleapis.com/maps/api/geocode/json?latlng=%1$f,%2$f&sensor=false&language=" + Locale.getDefault().getCountry(), lat, lng);
HttpGet httpGet = new HttpGet(address);
HttpClient client = new DefaultHttpClient();
client.getParams().setParameter(AllClientPNames.USER_AGENT, "Mozilla/5.0 (Java) Gecko/20081007 java-geocoder");
client.getParams().setIntParameter(AllClientPNames.CONNECTION_TIMEOUT, 5 * 1000);
client.getParams().setIntParameter(AllClientPNames.SO_TIMEOUT, 25 * 1000);
HttpResponse response;
List<Address> retList = null;
try {
response = client.execute(httpGet);
HttpEntity entity = response.getEntity();
String json = EntityUtils.toString(entity, "UTF-8");
JSONObject jsonObject = new JSONObject(json);
retList = new ArrayList<Address>();
if ("OK".equalsIgnoreCase(jsonObject.getString("status"))) {
JSONArray results = jsonObject.getJSONArray("results");
if (results.length() > 0) {
for (int i = 0; i < results.length() && i < maxResult; i++) {
JSONObject result = results.getJSONObject(i);
//Log.e(MyGeocoder.class.getName(), result.toString());
Address addr = new Address(Locale.getDefault());
// addr.setAddressLine(0, result.getString("formatted_address"));
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")) {
addr.setLocality(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");
}
}
}
addr.setAddressLine(0, route + " " + streetNumber);
addr.setLatitude(result.getJSONObject("geometry").getJSONObject("location").getDouble("lat"));
addr.setLongitude(result.getJSONObject("geometry").getJSONObject("location").getDouble("lng"));
retList.add(addr);
}
}
}
} catch (ClientProtocolException e) {
Log.e(MyGeocoder.class.getName(), "Error calling Google geocode webservice.", e);
} catch (IOException e) {
Log.e(MyGeocoder.class.getName(), "Error calling Google geocode webservice.", e);
} catch (JSONException e) {
Log.e(MyGeocoder.class.getName(), "Error parsing Google geocode webservice response.", e);
}
return retList;
}
}
use this trick.
simply edit the project.properties
# Project target
target=Google Inc.:Google APIs:16
The reason is that the Geocoder class is present in the core Android framework, but depends on code contributed by the Google APIs to function properly. Even if your AVD includes the Google APIs, your project still needs to be built against that specific build target.
Service not Available - Geocoder Android when i get this error in some cooked roms i wrote this library i hope could be useful. https://github.com/dnocode/gapis
I'm using the code that is up (direct access to Google Maps) "merged" with Geocoder code, as shown below (Pay special attention to "try catch"):
...
//address is String
if (address != null) {
new GeocoderTask().execute(address);
}
...
// An AsyncTask class for accessing the GeoCoding Web Service
private class GeocoderTask extends AsyncTask<String, Void, List<Address>> {
private LatLng latLng;
private MarkerOptions markerOptions;
#Override
protected List<Address> doInBackground(String... locationName) {
// Creating an instance of Geocoder class
Geocoder geocoder = new Geocoder(getBaseContext());
List<Address> addresses = null;
try {
// Getting a maximum of 3 Address that matches the input text
addresses = geocoder.getFromLocationName(locationName[0], 3);
} catch (IOException e) {
e.printStackTrace();
try {
addresses = getLocationFromString(locationName[0]);
} catch (UnsupportedEncodingException e1) {
e1.printStackTrace();
} catch (JSONException e1) {
e1.printStackTrace();
}
}
return addresses;
}
#Override
protected void onPostExecute(List<Address> addresses) {
if (addresses == null || addresses.size() == 0) {
Toast.makeText(getBaseContext(), "No Location found",
Toast.LENGTH_SHORT).show();
return;
}
// Clears all the existing markers on the map
googleMap.clear();
// Adding Markers on Google Map for each matching address
for (int i = 0; i < addresses.size(); i++) {
Address address = (Address) addresses.get(i);
// Creating an instance of GeoPoint, to display in Google Map
latLng = new LatLng(address.getLatitude(),
address.getLongitude());
String addressText = String.format(
"%s, %s",
address.getMaxAddressLineIndex() > 0 ? address
.getAddressLine(0) : "", address
.getCountryName());
markerOptions = new MarkerOptions();
markerOptions.position(latLng);
markerOptions.title(addressText);
googleMap.addMarker(markerOptions);
// Locate the first location
if (i == 0) {
CameraUpdate center = CameraUpdateFactory.newLatLng(latLng);
CameraUpdate zoom = CameraUpdateFactory.zoomTo(13);
googleMap.moveCamera(center);
googleMap.animateCamera(zoom);
}
}
}
}
public static LatLng getLocationFromString(String address)
throws JSONException {
HttpGet httpGet = new HttpGet(
"http://maps.google.com/maps/api/geocode/json?address="
+ URLEncoder.encode(address, "UTF-8") + "&ka&sensor=false");
HttpClient client = new DefaultHttpClient();
HttpResponse response;
StringBuilder stringBuilder = new StringBuilder();
try {
response = client.execute(httpGet);
HttpEntity entity = response.getEntity();
InputStream stream = entity.getContent();
int b;
while ((b = stream.read()) != -1) {
stringBuilder.append((char) b);
}
} catch (ClientProtocolException e) {
} catch (IOException e) {
}
JSONObject jsonObject = new JSONObject(stringBuilder.toString());
double lng = ((JSONArray) jsonObject.get("results")).getJSONObject(0)
.getJSONObject("geometry").getJSONObject("location")
.getDouble("lng");
double lat = ((JSONArray) jsonObject.get("results")).getJSONObject(0)
.getJSONObject("geometry").getJSONObject("location")
.getDouble("lat");
return new LatLng(lat, lng);
}
public static List<Address> getStringFromLocation(double lat, double lng)
throws ClientProtocolException, IOException, JSONException {
String address = String
.format(Locale.ENGLISH, "http://maps.googleapis.com/maps/api/geocode/json?latlng=%1$f,%2$f&sensor=true&language="
+ Locale.getDefault().getCountry(), lat, lng);
HttpGet httpGet = new HttpGet(address);
HttpClient client = new DefaultHttpClient();
HttpResponse response;
StringBuilder stringBuilder = new StringBuilder();
List<Address> retList = null;
response = client.execute(httpGet);
HttpEntity entity = response.getEntity();
InputStream stream = entity.getContent();
int b;
while ((b = stream.read()) != -1) {
stringBuilder.append((char) b);
}
JSONObject jsonObject = new JSONObject(stringBuilder.toString());
retList = new ArrayList<Address>();
if ("OK".equalsIgnoreCase(jsonObject.getString("status"))) {
JSONArray results = jsonObject.getJSONArray("results");
for (int i = 0; i < results.length(); i++) {
JSONObject result = results.getJSONObject(i);
String indiStr = result.getString("formatted_address");
Address addr = new Address(Locale.getDefault());
addr.setAddressLine(0, indiStr);
retList.add(addr);
}
}
return retList;
}
This worked excellent for me because when Geocoder not work, i use direct access to Google Maps.
Cheers!
You can go to a map app in your phone and clear cached and will find the address work correctly.
I had the same geocoder error but non of the above applied. It would not run one of my Android devices. Then I remembered that I had accedently killed some running service.
The solution was to remove the battery for some seconds and re-install it.
And it worked without changing the code :))
Some devices do not have suport for Geocoder, so what you need to do is create your own geocoder.
Basicaly you need create a async task to request google for the address and treat the json response.
Using aquery, i do something like this:
public void asyncJson(String address){
address = address.replace(" ", "+");
String url = "http://maps.googleapis.com/maps/api/geocode/json?address="+ address +"&sensor=true";
aq.ajax(url, JSONObject.class, new AjaxCallback<JSONObject>() {
#Override
public void callback(String url, JSONObject json, AjaxStatus status) {
if(json != null){
//here you work with the response json
JSONArray results = json.getJSONArray("results");
Toast.makeText(context, results.getJSONObject(1).getString("formatted_address"));
}else{
//ajax error, show error code
Toast.makeText(aq.getContext(), "Error:" + status.getCode(), Toast.LENGTH_LONG).show();
}
}
});
}
For the following line
Geocoder gCoder = new Geocoder(context, Locale.getDefault());
Use Context of your Activity and don't use getApplicationContext()
I have also had trouble with this error. It happened when I updated my device to Marshmallow recently.
If I reboot, it works once, but then will fail, and not work at all thereafter.
I created an AsyncTask like other people, that only returns the address from the first result of the json response.
To use the code below, call it constructed with your api key, and you use a Location object as input to execute the AsyncTask. You can import Location with the following. import android.location.Location; You will have to get the current Location with the LocationManager, by requesting an update to it.
new ReverseGeoCodeTask(GOOGLE_API_KEY).execute(location);
Make sure you replace the api key with your own, and also make sure you enable it in the google cloud console. That is where you manage all the google apis for your particular project.
Copy this class as an Inner Class in the Activity that you are needing the reverse geocoded address.
/**
* Reverse geocode request - takes a Location in as parameters,
* and does a network request in the background to get the first address in
* json response. The address is returned in the onPostExecute so you
* can update the UI with it
*/
private class ReverseGeoCodeTask extends AsyncTask<Location, Void, String>{
private final static String GEOCODE_API_ENDPOINT_BASE = "https://maps.googleapis.com/maps/api/geocode/json?latlng=";
private final static String JSON_PROPERTY_RESULTS = "results";
private final static String JSON_PROPERTY_FORMATTED_ADDRESS = "formatted_address";
private final static String JSON_PROPERTY_REQUEST_STATUS = "status";
private final static String STATUS_OK = "OK";
private String apiKey;
public ReverseGeoCodeTask(final String apiKey){
this.apiKey = apiKey;
}
#Override
protected String doInBackground(Location... params) {
if(apiKey == null){
throw new IllegalStateException("Pass in a geocode api key in the ReverseGeoCoder constructor");
}
Location location = params[0];
String googleGeocodeEndpoint = GEOCODE_API_ENDPOINT_BASE + location.getLatitude() + "," + location.getLongitude() + "&key=" + apiKey;
Log.d(TAG, "Requesting gecoding endpoint : " + googleGeocodeEndpoint);
try {
URL url = new URL(googleGeocodeEndpoint);
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
InputStream in = new BufferedInputStream(urlConnection.getInputStream());
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
StringBuilder result = new StringBuilder();
String line;
while ((line = reader.readLine()) != null) {
result.append(line);
}
JSONObject json = new JSONObject(result.toString());
String requestStatus = json.getString(JSON_PROPERTY_REQUEST_STATUS);
if(requestStatus.equals(STATUS_OK)){
JSONArray results = json.getJSONArray(JSON_PROPERTY_RESULTS);
if(results.length() > 0){
JSONObject result1 = results.getJSONObject(0);
String address = result1.getString(JSON_PROPERTY_FORMATTED_ADDRESS);
Log.d(TAG, "First result's address : " + address );
return address;
}
else{
Log.d(TAG, "There were no results.");
}
}
else{
Log.w(TAG, "Geocode request status not " + STATUS_OK + ", it was " + requestStatus );
Log.w(TAG, "Did you enable the geocode in the google cloud api console? Is it the right api key?");
}
}catch ( IOException | JSONException e){
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(String address) {
super.onPostExecute(address);
if(address != null){
// update the UI here with the address, if its not null
originEditText.setText(address);
}
else{
Log.d(TAG, "Did not find an address, UI not being updated");
}
}
}
Had the same issue on Android 6.
The problem was in App permissions.
Even if the maps works properly you must allow the "Get position" permission in app permissions.
The best case is always to check this permission allowed
when you expect to get the place in result.
I use this method to get the full address from place:
public Address getFullAddress(Place place){
Address address;
Locale aLocale = new Locale.Builder().setLanguage("en").build();
Geocoder geocoder = new Geocoder(this, aLocale);
try {
List<Address> addresses = geocoder.getFromLocation(place.getLatLng().latitude,place.getLatLng().longitude, 1);
address = addresses.get(0);
return address;
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
I had the same error, add below permissions to resolve it.
<uses-permission android:name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS" />
<uses-permission android:name="android.permission.INTERNET" />
new Volly_Services(map, "https://maps.googleapis.com/maps/api/place/textsearch/json?query=" + mBinding.loc.getText().toString().trim() + "&key=Ap", getActivity()).vollyPostService().continueWithTask(task - > {
mBinding.progressBaar.setVisibility(View.GONE);
if (task.getResult() != null) {
Log.e("<<<", "" + task.getResult());
JSONObject jsonObject = new JSONObject("" + task.getResult());
if ("OK".equalsIgnoreCase(jsonObject.getString("status"))) {
JSONArray results = jsonObject.getJSONArray("results");
if (results.length() > 0) {
mBinding.loc.setVisibility(View.GONE);
for (int i = 0; i < results.length(); i++) {
JSONObject result = results.getJSONObject(i);
String indiStr = result.getString("formatted_address");
Address addr = new Address(Locale.getDefault());
addr.setAddressLine(0, indiStr);
addr.setLocality(result.getString("name"));
JSONObject geometry = result.getJSONObject("geometry").getJSONObject("location");
addr.setLatitude(geometry.getDouble("lat"));
addr.setLongitude(geometry.getDouble("lng"));
addresses.add(addr);
}
adapter = new SerchLocationAdapter(getActivity(), addresses);
mBinding.serchreg.setAdapter(adapter);
} else {
Toast.makeText(getActivity(), "No result found", Toast.LENGTH_LONG).show();
}
} else {
Toast.makeText(getActivity(), "No result found", Toast.LENGTH_LONG).show();
}
} else {
Log.e("<<<<<<", "" + task.getError().getMessage());
Toast.makeText(getActivity(), task.getError().getMessage(), Toast.LENGTH_LONG).show();
}
return null;
});
I use Volley and it work fine
private void callAppFromUrl(final String strAddress, final String app, final boolean isGeo) {
try {
Volley.newRequestQueue(this).add(new StringRequest(0, String.format("https://www.google.com/maps?q=%s", URLEncoder.encode(strAddress, "UTF-8")), new Response.Listener<String>() {
public void onResponse(String response) {
try {
try {
Matcher m = Pattern.compile("null,null,(\\d+.\\d+),(\\d+.\\d+)").matcher(response);
String strLatLong = "";
if (m.find()) {
strLatLong = m.group(0).replace("null,null,", "");
}
String[] latlong = strLatLong.split(",");
LatLng latLng = new LatLng(Double.parseDouble(latlong[0]), Double.parseDouble(latlong[1]));
Log.d("OsK",String.valueOf(latLng));
} catch (Exception e) {
Toast.makeText(getApplicationContext(), "Không tìm thấy địa chỉ", Toast.LENGTH_LONG).show();
}
} catch (Exception e2) {
Toast.makeText(getApplicationContext(), "Không tìm thấy địa chỉ", Toast.LENGTH_LONG).show();
}
}
}, new Response.ErrorListener() {
/* class com.cantho.roadtech.MainActivity.AnonymousClass5 */
#Override // com.android.volley.Response.ErrorListener
public void onErrorResponse(VolleyError error) {
}
}) {
#Override
public Map<String, String> getHeaders() throws AuthFailureError {
Map<String, String> params = new HashMap<>();
params.put("User-Agent", "Mozilla");
params.put("Accept-Language", "en-US,en;q=0.8");
params.put("Referer", "google.com");
return params;
}
});
} catch (Exception ex) {
}
}
In my application, when the user insert data i want to capture the user's exact place. I've tried so many methods. But none of them shown the exact place. (I meant that they display the country and admin area details only. I used getLocality and getFeatureName. If no Locality or Featurename found at that latitude and longitude then it will return a null value). My code is
Geocoder coder=new Geocoder(MainActivity.mContext,Locale.getDefault());
try
{
List<Address> listaddress=coder.getFromLocation(lat, lon, 1);
Address obj=listaddress.get(0);
String add=obj.getAddressLine(0);
add = add+"\n"+obj.getLatitude();
add = add+","+obj.getLongitude();
add = add + "," + obj.getCountryName();
add = add + "," + obj.getAdminArea();
add = add + "\n" + obj.getPostalCode();//null
add = add + "," + obj.getSubAdminArea();
add = add +","+obj.getFeatureName();//null
add = add+ "," +obj.getPremises();//null
add = add + "\n" + obj.getLocality();//null
add = add + "," + obj.getSubThoroughfare();//null
add = add+ "," +obj.getSubLocality();//null
add = add+"\n"+obj.getThoroughfare();
Log.v("IGA", "Address" + add);
//Toast.makeText(this, "Address=>" + add,Toast.LENGTH_SHORT).show();
t.setText(" "+add);
}
So I don't know how to solve it. But I have an idea. I need to find the nearest place to my exact latitude and longitude value, so that i can use that place. But I don't know how to find the nearest place (Nearest place means Village or Street not any others).
Also, In Android phones one application "Places" is there. It shows the correct area about where exactly I'm. Is there any possibilities to use the application "Places" to find my exact or nearest area. (I need the closest village or street, not subAdminArea (state). If yes, please explain.
Can anyone help me please
Using google reverse geocoding api you could get your actual street address by giving latitude and lantitude values.
Get Lat & Lan through GPS Receiver in Android
Then call google reverse geocoding api top fecth the actual street address:
MapManager in = new MapManager(
"http://maps.google.com/maps/geo?output=xml&oe=utf-8&ll="
+ lattitude + "%2C"
+ lantitude + "&key=get-key-from-google-map-api");
content = in.URLRequest();
System.out.println("Addrss:"+in.parseMapData(content));
Class MapManager{
String url ="";
MapManager(String url){
this.url = url;
}
public String parseMapData(String data) {
String addr = "";
try {
InputStream in = new ByteArrayInputStream(data.getBytes());
DocumentBuilder builder = DocumentBuilderFactory.newInstance()
.newDocumentBuilder();
Document doc = builder.parse(in, null);
NodeList address = doc.getElementsByTagName("address");
addr = address.item(0).getTextContent();
} catch (Throwable t) {
Log.v("Exception", "Exception: " + t.toString());
}
return addr;
}
public String URLRequest() {
httpclient = new DefaultHttpClient();
try {
httpget = new HttpGet(url);
httpresponse = httpclient.execute(httpget);
httpentity = httpresponse.getEntity();
response = EntityUtils.toString(httpentity);
response = response.trim();
} catch (ClientProtocolException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
IsServerConn = false;
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (Exception e) {
IsServerConn = false;
}
return response;
}
}
private class MatchingNearByLocationTask extends
AsyncTask<Void, Void, Void> {
#Override
protected void onPreExecute() {
super.onPreExecute();
// Showing progress dialog
progressDialog = new ProgressDialog(getContext());
progressDialog.setMessage("Loading...");
progressDialog.setCancelable(true);
progressDialog.show();
}
#Override
protected Void doInBackground(Void... arg0) {
jsonStr = getLocationInfo(latitude, longitude).toString(); // put longitude and latitude value from which u want find nearer palce
if (jsonStr != null) {
Log.i("location--??", jsonStr);
JSONObject jsonObj;
try {
jsonObj = new JSONObject(jsonStr);
JSONObject responseJsonObject = jsonObj
.getJSONObject("response");
JSONArray venues = responseJsonObject
.getJSONArray(("venues"));
for (int index = 0; index < venues.length(); index++) {
locationObject = new NearByLocationObject();
String id = "", name = "", longitude = "", latitude = "";
JSONObject venuesJsonObj = venues.getJSONObject(index);
id = venuesJsonObj.getString("id");
name = venuesJsonObj.getString("name");
JSONObject latLngJsonObj = venuesJsonObj
.getJSONObject("location");
longitude = latLngJsonObj.getString("lng");
latitude = latLngJsonObj.getString("lat");
locationObject.setId(id);
locationObject.setNameOfLocation(name);
locationObject.setLocationOfLatitude(latitude);
locationObject.setLocationOfLongitude(longitude);
nearByLocationArrayList.add(locationObject);
}
} catch (JSONException e) {
e.printStackTrace();
}
}
return null;
}
#Override
protected void onPostExecute(Void result) {
super.onPostExecute(result);
// Dismiss the progress dialog
if (progressDialog.isShowing()) {
progressDialog.dismiss();
}
adapter = new NearByLocationArrayAdapter(getContext(),
R.layout.nearby_location_item, nearByLocationArrayList);
nearByLocationListView.setAdapter(adapter);
}
#Override
protected void onCancelled() {
super.onCancelled();
progressDialog.dismiss();
}
}
private JSONObject getLocationInfo(double lat, double lng) {
HttpGet httpGet = new HttpGet(
"https://api.foursquare.com/v2/venues/search?ll="
+ lat
+ ","
+ lng
+ "&radius=100&oauth_token=TNFKWLITLCJYWPSLAXQNHCSDPHZ4IS5PWVDD45OI224JGFFM&v=20140407&intent=checkin");
HttpClient client = new DefaultHttpClient();
HttpResponse response;
StringBuilder stringBuilder = new StringBuilder();
try {
response = client.execute(httpGet);
HttpEntity entity = response.getEntity();
InputStream stream = entity.getContent();
int b;
while ((b = stream.read()) != -1) {
stringBuilder.append((char) b);
}
} catch (ClientProtocolException e) {
} catch (IOException e) {
}
JSONObject jsonObject = new JSONObject();
try {
jsonObject = new JSONObject(stringBuilder.toString());
} catch (JSONException e) {
e.printStackTrace();
}
return jsonObject;
}
public class NearByLocationObject {
String id = "", nameOfLocation, locationOfLatitude, LocationOfLongitude;
public NearByLocationObject() {
super();
// TODO Auto-generated constructor stub
}
public NearByLocationObject(String id, String nameOfLocation,
String locationOfLatitude, String locationOfLongitude) {
super();
this.id = id;
this.nameOfLocation = nameOfLocation;
this.locationOfLatitude = locationOfLatitude;
LocationOfLongitude = locationOfLongitude;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getNameOfLocation() {
return nameOfLocation;
}
public void setNameOfLocation(String nameOfLocation) {
this.nameOfLocation = nameOfLocation;
}
public String getLocationOfLatitude() {
return locationOfLatitude;
}
public void setLocationOfLatitude(String locationOfLatitude) {
this.locationOfLatitude = locationOfLatitude;
}
public String getLocationOfLongitude() {
return LocationOfLongitude;
}
public void setLocationOfLongitude(String locationOfLongitude) {
LocationOfLongitude = locationOfLongitude;
}
}