Сервис недоступен при вызове geoCoder.getFromLocation()
Я знаю, что иногда может быть недоступна служба back-end google.
Следовательно, решение может выполняться до тех пор, пока я не получу данные.
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) {
}
}
Но я не могу получить местоположение вообще:
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
и, конечно же, я добавил все необходимые разрешения:
<uses-permission android:name="android.permission.INTERNET" />
Я пытаюсь это сделать на Samsung Galaxy Note GT-N7000 (версия 4.0.4)
У меня отсутствуют какие-либо настройки? связанные с устройством или приложением? Или это обычно происходит? Если да, то какое-нибудь лучшее решение для решения этой проблемы?
Спасибо
Ответы
Ответ 1
Фактическая причина, по которой Geocoder
не работает, заключается в том, что NetworkLocator
был убит в действии. Вероятно, из-за меньшей памяти или, возможно, вы использовали диспетчер задач, чтобы убить все службы?
Я не уверен, но это предположение. Я видел это раньше. В прошлом году я написал механизм повторного подключения для загрузки NetworkLocator.apk и привязки к GeocoderService
. Я думаю, что это изменение не слилось с JellyBean, так что эта проблема сохраняется.
Это можно решить только при перезагрузке. (NetworkLocationService
загружается при загрузке)
Изменить: вы не увидите эту проблему в JBP или KK, эта служба перемещается в приложение playstore.
Ответ 2
Обходной путь с использованием прямого доступа к картам google:
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;
}
Ответ 3
Перезагрузите устройство, и оно устранит проблему.
Ответ 4
API будет вызывать "Служебное недопустимое исключение", если такая услуга недоступна на устройстве. Используйте метод isPresent()
, чтобы проверить наличие службы.
Смотрите также: http://developer.android.com/reference/android/location/Geocoder.html
Ответ 5
Лучшим решением этой проблемы является использование того же типа, что и класс Google Geocoder, если исходный Geocoder не работает
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;
}
}
Ответ 6
используйте этот трюк.
просто отредактируйте project.properties
# Project target
target=Google Inc.:Google APIs:16
Причина в том, что класс Geocoder присутствует в основной платформе Android, но зависит от кода, внесенного API Google для правильной работы. Даже если ваш AVD включает API Google, ваш проект по-прежнему должен быть создан против этой конкретной цели сборки.
Ответ 7
Сервис не доступен - Geocoder Android, когда я получаю эту ошибку в некоторых приготовленных ромах, я написал эту библиотеку, надеюсь, может быть полезен. https://github.com/dnocode/gapis
Ответ 8
Я использую код, который работает (прямой доступ к Картам Google), "слитый" с кодом Geocoder, как показано ниже (обратите особое внимание на "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;
}
Это отлично работает для меня, потому что, когда Geocoder не работает, я использую прямой доступ к Картам Google.
Ура!
Ответ 9
У меня была такая же ошибка геокодера, но не из вышеприведенного. Он не будет запускать одно из моих Android-устройств. Затем я вспомнил, что я случайно убил какое-то бегство.
Решение заключалось в том, чтобы вынуть батарею на несколько секунд и переустановить ее.
И он работал без изменения кода:))
Ответ 10
Некоторые устройства не имеют поддержки для Geocoder, поэтому вам нужно создать собственный геокодер.
В принципе, вам нужно создать асинхронную задачу для запроса google для адреса и обработать ответ json.
Используя aquery, я делаю что-то вроде этого:
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();
}
}
});
}
Ответ 11
Для следующей строки
Geocoder gCoder = new Geocoder(context, Locale.getDefault());
Используйте Context
своей деятельности и не используйте getApplicationContext()
Ответ 12
У меня также были проблемы с этой ошибкой. Это случилось, когда я недавно обновил свое устройство до Marshmallow.
Если я перезагружу, он будет работать один раз, но потом будет не работать, и после этого он не будет работать.
Я создал AsyncTask, как и другие люди, который возвращает только адрес из первого результата ответа json.
Чтобы использовать приведенный ниже код, вызовите его с помощью вашего ключа api, и вы используете объект Location в качестве входа для выполнения AsyncTask. Вы можете импортировать местоположение со следующим. import android.location.Location;
Вам нужно будет получить текущее местоположение с помощью LocationManager, запросив обновление для него.
new ReverseGeoCodeTask(GOOGLE_API_KEY).execute(location);
Убедитесь, что вы заменили ключ api своим, а также убедитесь, что вы включили его в облачной консоли Google. Именно здесь вы управляете всей авикой google для своего конкретного проекта.
Скопируйте этот класс как Внутренний класс в Управлении, в котором вам нужен обратный геокодированный адрес.
/**
* 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 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");
}
}
}
Ответ 13
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;
});
Ответ 14
Была такая же проблема на Android 6. Проблема была в разрешениях приложения. Даже если карты работают правильно, вы должны разрешить разрешение "Получить позицию" в разрешениях приложения.
Лучше всего всегда проверять это разрешение, если вы ожидаете получить место в результате.
Ответ 15
У меня была такая же ошибка, добавьте ниже разрешения для ее устранения.
<uses-permission android:name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS" />
<uses-permission android:name="android.permission.INTERNET" />