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 version)
設定がありませんか?デバイスまたはアプリケーションに関連する?または、これは通常起こりますか?もしそうなら、これを解決するためのより良い解決策はありますか??
ありがとうございました
Geocoder
が機能しなかった実際の理由は、NetworkLocator
が実際に殺されたためです。おそらくメモリが少ないためか、タスクマネージャを使用してすべてのサービスを強制終了した可能性がありますか?
よくわかりませんが、これは推測です。これは前に見たことがあります。昨年、NetworkLocator.apkをロードしてGeocoderService
にバインドする再接続メカニズムを作成しました。この変更はJellyBeanにマージされていないので、この問題は解決しません。
再起動することによってのみ解決できます。 (NetworkLocationService
はブート時にロードされます)
編集:JBPまたはKKでこの問題は表示されません。このサービスはplaystoreアプリに移動されます。
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;
}
デバイスを再起動すると、問題が修正されます。
この問題の最善の解決策は、元のジオコーダーが失敗した場合、Googleジオコーダークラスと同じものを使用することです
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;
}
}
そのようなサービスがデバイスで利用できない場合、APIは「サービス利用不可例外」をスローします。メソッドisPresent()
を使用して、サービスの存在を確認します。
参照: http://developer.Android.com/reference/Android/location/Geocoder.html
このトリックを使用してください。
project.propertiesを編集するだけです
# Project target
target=Google Inc.:Google APIs:16
その理由は、GeocoderクラスがコアAndroidフレームワークに存在するが、Google APIによって提供されるコードに依存して適切に機能するためです。AVDにGoogle APIが含まれている場合でも、プロジェクトにはその特定のビルドターゲットに対してビルドされます。
サービスは利用できません-Geocoder Android調理済みのROMでこのエラーが発生した場合、このライブラリを作成したことをお勧めします。 https://github.com/dnocode/gapis
以下に示すように、Geocoderコードと「マージ」されたコード(Googleマップへの直接アクセス)を使用しています(「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マップへの直接アクセスを使用するため、これは私にとって非常に効果的でした。
乾杯!
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;
});
一部のデバイスにはジオコーダーがサポートされていないため、独自のジオコーダーを作成する必要があります。
基本的に、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();
}
}
});
}
私もこのエラーに問題がありました。最近、デバイスをMarshmallowにアップデートしたときに起こりました。
再起動すると、一度動作しますが、その後は失敗し、その後はまったく動作しません。
他の人と同じように、json応答の最初の結果からのみアドレスを返すAsyncTaskを作成しました。
以下のコードを使用するには、apiキーで構築されたコードを呼び出し、Locationオブジェクトを入力として使用してAsyncTaskを実行します。以下を使用してロケーションをインポートできます。 import Android.location.Location;
更新をリクエストして、LocationManagerで現在のロケーションを取得する必要があります。
new ReverseGeoCodeTask(GOOGLE_API_KEY).execute(location);
Apiキーを独自のキーに置き換えてください。また、Googleクラウドコンソールで有効にしてください。特定のプロジェクトのすべてのGoogle APIを管理する場所です。
逆ジオコーディングされた住所が必要なアクティビティで、このクラスを内部クラスとしてコピーします。
/**
* 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");
}
}
}
Android 6で同じ問題がありました。問題はアプリの権限にありました。マップが正常に機能する場合でも、アプリの許可で"Get position"許可を許可する必要があります。
最良のケースは、結果の場所を取得する予定のときに許可されているこの許可を常にチェックすることです。
このメソッドを使用して、場所から完全なアドレスを取得します。
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;
}
同じジオコーダーエラーが発生しましたが、上記のものは適用されませんでした。それは私のAndroidデバイスのいずれかを実行しませんでした。コードを変更せずに:))
次の行について
_Geocoder gCoder = new Geocoder(context, Locale.getDefault());
_
アクティビティの
Context
を使用し、getApplicationContext()
は使用しないでください