arpit
arpit

Reputation: 555

Service not available in geoCoder

I am able to get longitude and latitude but getting address i got an error.

public boolean onTouchEvent(MotionEvent event, MapView mapView)

{

  if(event.getAction()==0)

   {

GeoPoint p = mapView.getProjection().fromPixels(

  (int) event.getX(),

  (int) event.getY());


Geocoder geoCoder=new Geocoder(getBaseContext(),Locale.getDefault());

 try

   {

   List<Address> address = geoCoder.getFromLocation( p.getLatitudeE6() / 1E6,
                            p.getLongitudeE6() / 1E6, 1);

    String add="";

       if(address.size()>0)

          {

              for (int i=0; i<address.get(0).getMaxAddressLineIndex();i++)

        add += address.get(0).getAddressLine(i) + "\n";

          }

    Toast.makeText(getBaseContext(), add, Toast.LENGTH_SHORT).show();

            } catch (IOException e) 

            {   

                e.printStackTrace();

            }

            return true;    

        }

        return false;

}

My Logcat -->

02-14 12:27:35.717: WARN/System.err(452): java.io.IOException: Service not Available
02-14 12:27:35.727: WARN/System.err(452):     at android.location.Geocoder.getFromLocation(Geocoder.java:117)
02-14 12:27:35.727: WARN/System.err(452):     at com.parkhya.SecondGps.MainActivity$MapOverlay.onTouchEvent(MainActivity.java:47)
02-14 12:27:35.745: WARN/System.err(452):     at com.google.android.maps.OverlayBundle.onTouchEvent(OverlayBundle.java:63)
02-14 12:27:35.745: WARN/System.err(452):     at com.google.android.maps.MapView.onTouchEvent(MapView.java:643)
02-14 12:27:35.757: WARN/System.err(452):     at android.view.View.dispatchTouchEvent(View.java:3766)
02-14 12:27:35.757: WARN/System.err(452):     at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:897)
02-14 12:27:35.757: WARN/System.err(452):     at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:863)
02-14 12:27:35.767: WARN/System.err(452):     at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:863)
02-14 12:27:35.767: WARN/System.err(452):     at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:863)
02-14 12:27:35.777: WARN/System.err(452):     at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:863)
02-14 12:27:35.777: WARN/System.err(452):     at com.android.internal.policy.impl.PhoneWindow$DecorView.superDispatchTouchEvent(PhoneWindow.java:1671)
02-14 12:27:35.777: WARN/System.err(452):     at com.android.internal.policy.impl.PhoneWindow.superDispatchTouchEvent(PhoneWindow.java:1107)
02-14 12:27:35.777: WARN/System.err(452):     at android.app.Activity.dispatchTouchEvent(Activity.java:2086)
02-14 12:27:35.786: WARN/System.err(452):     at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchTouchEvent(PhoneWindow.java:1655)
02-14 12:27:35.786: WARN/System.err(452):     at android.view.ViewRoot.handleMessage(ViewRoot.java:1785)
02-14 12:27:35.796: WARN/System.err(452):     at android.os.Handler.dispatchMessage(Handler.java:99)
02-14 12:27:35.796: WARN/System.err(452):     at android.os.Looper.loop(Looper.java:123)
02-14 12:27:35.796: WARN/System.err(452):     at android.app.ActivityThread.main(ActivityThread.java:4627)
02-14 12:27:35.806: WARN/System.err(452):     at java.lang.reflect.Method.invokeNative(Native Method)
02-14 12:27:35.816: WARN/System.err(452):     at java.lang.reflect.Method.invoke(Method.java:521)
02-14 12:27:35.816: WARN/System.err(452):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868)
02-14 12:27:35.825: WARN/System.err(452):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626)
02-14 12:27:35.837: WARN/System.err(452):     at dalvik.system.NativeStart.main(Native Method)

Upvotes: 11

Views: 14193

Answers (3)

Ahmed Salem
Ahmed Salem

Reputation: 1757

The problem is that NetworkLocationService may be no longer running.

It can be only solved by a reboot. (The NetworkLocationService is loaded at boot)

Upvotes: 2

Pascal
Pascal

Reputation: 16631

Here is my way to get the address even if Geocoder failed... but first let me explain my own experience with Geocoder:

For some unknown reason, Geocoder works fine then, suddenly break!.

What I observed is that, after a while (can be days), Geocoder start to throw "Service not available" exception.

EDIT-> As mentioned by Christian, the exception is thrown even is isPresent() returns true.<-EDIT END

Really weird since it was working fine before and no configuration changed occurred:

  • same device
  • same Android version
  • same app
  • same manifest
  • WIFI up and running, Device location feature enabled in settings

Of course, something changed, but, for the time being, we don't know exactly what. There is a bug opened about that: Issue 38009: 4.1.1 Geocoder throwing exception: IOException: Service not Available

Last post on this thread (ATTOW) "Probably it's periodically reproducible in android 4.0.x + target API x"

As a workaround, you can use Google Map

Here is my GeocoderHelper class that provides a 'Google Map' B Plan in case Geocoder start to fails. In my case, I am just interested in CityName, but you can basically get any data availalbe in google map JSON output

Usage:

new GeocoderHelper().fetchCityName(context, location); Then do somthing in onPostExecute() of example code (send broadcast, invoke listener method, set a textView text, whatever)

GeocoderHelper Class:

package com.<your_package>.location;

import java.util.List;
import java.util.Locale;

import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.BasicResponseHandler;
import org.json.JSONArray;
import org.json.JSONObject;

import android.content.Context;
import android.location.Address;
import android.location.Geocoder;
import android.location.Location;
import android.net.http.AndroidHttpClient;
import android.os.AsyncTask;
import android.util.Log;

public class GeocoderHelper
{
    private static final AndroidHttpClient ANDROID_HTTP_CLIENT = AndroidHttpClient.newInstance(GeocoderHelper.class.getName());

    private boolean running = false;

    public void fetchCityName(final Context contex, final Location location)
    {
        if (running)
            return;

        new AsyncTask<Void, Void, String>()
        {
            protected void onPreExecute()
            {
                running = true;
            };

            @Override
            protected String doInBackground(Void... params)
            {
                String cityName = null;

                if (Geocoder.isPresent())
                {
                    try
                    {
                        Geocoder geocoder = new Geocoder(contex, Locale.getDefault());
                        List<Address> addresses = geocoder.getFromLocation(location.getLatitude(), location.getLongitude(), 1);
                        if (addresses.size() > 0)
                        {
                            cityName = addresses.get(0).getLocality();
                        }
                    }
                    catch (Exception ignored)
                    {
                        // after a while, Geocoder start to trhow "Service not availalbe" exception. really weird since it was working before (same device, same Android version etc..
                    }
                }

                if (cityName != null) // i.e., Geocoder succeed
                {
                    return cityName;
                }
                else // i.e., Geocoder failed
                {
                    return fetchCityNameUsingGoogleMap();
                }
            }

            // Geocoder failed :-(
            // Our B Plan : Google Map
            private String fetchCityNameUsingGoogleMap()
            {
                String googleMapUrl = "http://maps.googleapis.com/maps/api/geocode/json?latlng=" + location.getLatitude() + ","
                        + location.getLongitude() + "&sensor=false&language=fr";

                try
                {
                    JSONObject googleMapResponse = new JSONObject(ANDROID_HTTP_CLIENT.execute(new HttpGet(googleMapUrl),
                            new BasicResponseHandler()));

                    // many nested loops.. not great -> use expression instead
                    // loop among all results
                    JSONArray results = (JSONArray) googleMapResponse.get("results");
                    for (int i = 0; i < results.length(); i++)
                    {
                        // loop among all addresses within this result
                        JSONObject result = results.getJSONObject(i);
                        if (result.has("address_components"))
                        {
                            JSONArray addressComponents = result.getJSONArray("address_components");
                            // loop among all address component to find a 'locality' or 'sublocality'
                            for (int j = 0; j < addressComponents.length(); j++)
                            {
                                JSONObject addressComponent = addressComponents.getJSONObject(j);
                                if (result.has("types"))
                                {
                                    JSONArray types = addressComponent.getJSONArray("types");

                                    // search for locality and sublocality
                                    String cityName = null;

                                    for (int k = 0; k < types.length(); k++)
                                    {
                                        if ("locality".equals(types.getString(k)) && cityName == null)
                                        {
                                            if (addressComponent.has("long_name"))
                                            {
                                                cityName = addressComponent.getString("long_name");
                                            }
                                            else if (addressComponent.has("short_name"))
                                            {
                                                cityName = addressComponent.getString("short_name");
                                            }
                                        }
                                        if ("sublocality".equals(types.getString(k)))
                                        {
                                            if (addressComponent.has("long_name"))
                                            {
                                                cityName = addressComponent.getString("long_name");
                                            }
                                            else if (addressComponent.has("short_name"))
                                            {
                                                cityName = addressComponent.getString("short_name");
                                            }
                                        }
                                    }
                                    if (cityName != null)
                                    {
                                        return cityName;
                                    }
                                }
                            }
                        }
                    }
                }
                catch (Exception ignored)
                {
                    ignored.printStackTrace();
                }
                return null;
            }

            protected void onPostExecute(String cityName)
            {
                running = false;
                if (cityName != null)
                {
                    // Do something with cityName
                    Log.i("GeocoderHelper", cityName);
                }
            };
        }.execute();
    }
}

Hope this will help.

Upvotes: 34

PravinCG
PravinCG

Reputation: 7708

GeoCoder service may/maynot be implemented as it is not part of core android framework. Check the documentation for GeoCoder here

You need to use google APIs and parse the address from the json response for it to work on all the devices.

A class for handling geocoding and reverse geocoding. Geocoding is the process of transforming a street address or other description of a location into a (latitude, longitude) coordinate. Reverse geocoding is the process of transforming a (latitude, longitude) coordinate into a (partial) address. The amount of detail in a reverse geocoded location description may vary, for example one might contain the full street address of the closest building, while another might contain only a city name and postal code. The Geocoder class requires a backend service that is not included in the core android framework. The Geocoder query methods will return an empty list if there no backend service in the platform. Use the isPresent() method to determine whether a Geocoder implementation exists.

Upvotes: 3

Related Questions