Je sais que parfois, le service principal de Google n'est peut-être pas disponible.
Par conséquent, une solution pourrait consister à boucler jusqu'à l'obtention des données.
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) {
}
}
Mais je ne parviens pas à obtenir l'emplacement du tout:
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
et bien sûr, j'ai ajouté toutes les autorisations nécessaires:
<uses-permission Android:name="Android.permission.INTERNET" />
J'essaie ceci sur Samsung Galaxy Note GT-N7000 (version 4.0.4)
Me manque-t-il des paramètres? lié à l'appareil ou à l'application? Ou cela arrive généralement? Si oui, une meilleure solution pour résoudre ce problème ??
Je vous remercie
La raison réelle pour laquelle Geocoder
ne fonctionnait pas est parce que NetworkLocator
a été tué au combat. Probablement à cause de moins de mémoire ou peut-être que vous avez utilisé le gestionnaire de tâches pour tuer tous les services?
Je ne suis pas sûr mais c'est une supposition. J'ai déjà vu ça auparavant. L'année dernière, j'ai écrit un mécanisme de reconnexion pour charger le fichier NetworkLocator.apk et se connecter à la variable GeocoderService
. Je pense que ce changement n'a pas fusionné dans JellyBean, donc ce problème persiste.
Il ne peut être résolu que par un redémarrage. (La NetworkLocationService
est chargée au démarrage)
Edit: vous ne verrez pas ce problème dans JBP ou KK, ce service est transféré dans l'application Playstore.
Solution de contournement utilisant l'accès direct à 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;
}
Redémarrez l'appareil et cela résoudra le problème.
La meilleure solution à ce problème consiste à utiliser la même chose que la classe Google Geocoder si le géocodeur d'origine échoue
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;
}
}
L'API lève une "exception Service non disponible" si ce service n'est pas disponible sur le périphérique. Utilisez la méthode isPresent()
pour vérifier l'existence du service.
Voir aussi: http://developer.Android.com/reference/Android/location/Geocoder.html
utilisez cette astuce.
éditez simplement le fichier project.properties
# Project target
target=Google Inc.:Google APIs:16
La raison en est que la classe Geocoder est présente dans le cadre principal d'Android, mais dépend du code fourni par les API de Google pour fonctionner correctement. Même si votre AVD inclut les API Google, votre projet doit toujours être construit en fonction de cette cible de construction spécifique.
Service non disponible - Geocoder Android lorsque j'obtiens cette erreur dans certaines roms cuites, j’ai écrit cette bibliothèque, j’espère pouvoir être utile. https://github.com/dnocode/gapis
J'utilise le code en vigueur (accès direct à Google Maps) "fusionné" avec le code Geocoder, comme indiqué ci-dessous (Faites particulièrement attention à "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;
}
Cela a fonctionné très bien pour moi, car lorsque Geocoder ne fonctionne pas, j'utilise un accès direct à Google Maps.
À votre santé!
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;
});
Certains appareils n’ayant pas suport pour Geocoder, vous devez donc créer votre propre géocodeur.
En gros, vous devez créer une tâche asynchrone pour demander à Google l'adresse et traiter la réponse JSON.
En utilisant aquery, je fais quelque chose comme ça:
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();
}
}
});
}
J'ai aussi eu des problèmes avec cette erreur. C'est arrivé lorsque j'ai mis à jour mon appareil vers Marshmallow récemment.
Si je redémarre, cela fonctionne une fois, mais échouera et ne fonctionnera plus du tout par la suite.
J'ai créé une AsyncTask comme d'autres personnes, qui ne retourne que l'adresse du premier résultat de la réponse JSON.
Pour utiliser le code ci-dessous, appelez-le construit avec votre clé api et utilisez un objet Location comme entrée pour exécuter AsyncTask. Vous pouvez importer Location avec les éléments suivants. import Android.location.Location;
Vous devrez obtenir l'emplacement actuel avec le LocationManager, en demandant une mise à jour.
new ReverseGeoCodeTask(GOOGLE_API_KEY).execute(location);
Assurez-vous de remplacer la clé api par la vôtre et de l'activer dans la console google cloud. C'est là que vous gérez tous les apis de Google pour votre projet particulier.
Copiez cette classe en tant que classe interne dans l'activité pour laquelle vous avez besoin de l'adresse géocodée inverse.
/**
* 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");
}
}
}
J'ai eu la même erreur de géocodeur, mais aucune des mesures ci-dessus n'a été appliquée. Il ne fonctionnerait pas l'un de mes appareils Android. Puis je me suis souvenu que j'avais accidentellement tué un service en cours d'exécution. La solution consistait à retirer la batterie pendant quelques secondes et à la réinstaller ..__et cela fonctionnait sans changer le code
Pour la ligne suivante
Geocoder gCoder = new Geocoder(context, Locale.getDefault());
Utilisez
Context
de votre activité et n'utilisez pasgetApplicationContext()