Geocoder.java revision 4193558f232c8961039b9ae6f875e3303b8e5d30
1/*
2 * Copyright (C) 2007 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package android.location;
18
19import android.content.Context;
20import android.location.Address;
21import android.os.RemoteException;
22import android.os.IBinder;
23import android.os.ServiceManager;
24import android.util.Log;
25
26import java.io.IOException;
27import java.util.Locale;
28import java.util.ArrayList;
29import java.util.List;
30
31/**
32 * A class for handling geocoding and reverse geocoding.  Geocoding is
33 * the process of transforming a street address or other description
34 * of a location into a (latitude, longitude) coordinate.  Reverse
35 * geocoding is the process of transforming a (latitude, longitude)
36 * coordinate into a (partial) address.  The amount of detail in a
37 * reverse geocoded location description may vary, for example one
38 * might contain the full street address of the closest building, while
39 * another might contain only a city name and postal code.
40 *
41 * The Geocoder class requires a backend service that is not included in
42 * the core android framework. The Geocoder query methods will return an
43 * empty list if there no backend service in the platform.
44 */
45public final class Geocoder {
46    private static final String TAG = "Geocoder";
47
48    private String mLanguage;
49    private String mCountry;
50    private String mVariant;
51    private String mAppName;
52    private ILocationManager mService;
53
54    /**
55     * Constructs a Geocoder whose responses will be localized for the
56     * given Locale.
57     *
58     * @param context the Context of the calling Activity
59     * @param locale the desired Locale for the query results
60     *
61     * @throws NullPointerException if Locale is null
62     */
63    public Geocoder(Context context, Locale locale) {
64        if (locale == null) {
65            throw new NullPointerException("locale == null");
66        }
67        mLanguage = locale.getLanguage();
68        mCountry = locale.getCountry();
69        mVariant = locale.getVariant();
70        mAppName = context.getPackageName();
71
72        IBinder b = ServiceManager.getService(Context.LOCATION_SERVICE);
73        mService = ILocationManager.Stub.asInterface(b);
74    }
75
76    /**
77     * Constructs a Geocoder whose responses will be localized for the
78     * default system Locale.
79     *
80     * @param context the Context of the calling Activity
81     */
82    public Geocoder(Context context) {
83        this(context, Locale.getDefault());
84    }
85
86    /**
87     * Returns an array of Addresses that are known to describe the
88     * area immediately surrounding the given latitude and longitude.
89     * The returned addresses will be localized for the locale
90     * provided to this class's constructor.
91     *
92     * <p> The returned values may be obtained by means of a network lookup.
93     * The results are a best guess and are not guaranteed to be meaningful or
94     * correct. It may be useful to call this method from a thread separate from your
95     * primary UI thread.
96     *
97     * @param latitude the latitude a point for the search
98     * @param longitude the longitude a point for the search
99     * @param maxResults max number of addresses to return. Smaller numbers (1 to 5) are recommended
100     *
101     * @return a list of Address objects. Returns null or empty list if no matches were
102     * found or there is no backend service available.
103     *
104     * @throws IllegalArgumentException if latitude is
105     * less than -90 or greater than 90
106     * @throws IllegalArgumentException if longitude is
107     * less than -180 or greater than 180
108     * @throws IOException if the network is unavailable or any other
109     * I/O problem occurs
110     */
111    public List<Address> getFromLocation(double latitude, double longitude, int maxResults)
112        throws IOException {
113        if (latitude < -90.0 || latitude > 90.0) {
114            throw new IllegalArgumentException("latitude == " + latitude);
115        }
116        if (longitude < -180.0 || longitude > 180.0) {
117            throw new IllegalArgumentException("longitude == " + longitude);
118        }
119        try {
120            List<Address> results = new ArrayList<Address>();
121            String ex =  mService.getFromLocation(latitude, longitude, maxResults,
122                mLanguage, mCountry, mVariant, mAppName, results);
123            if (ex != null) {
124                throw new IOException(ex);
125            } else {
126                return results;
127            }
128        } catch (RemoteException e) {
129            Log.e(TAG, "getFromLocation: got RemoteException", e);
130            return null;
131        }
132    }
133
134    /**
135     * Returns an array of Addresses that are known to describe the
136     * named location, which may be a place name such as "Dalvik,
137     * Iceland", an address such as "1600 Amphitheatre Parkway,
138     * Mountain View, CA", an airport code such as "SFO", etc..  The
139     * returned addresses will be localized for the locale provided to
140     * this class's constructor.
141     *
142     * <p> The query will block and returned values will be obtained by means of a network lookup.
143     * The results are a best guess and are not guaranteed to be meaningful or
144     * correct. It may be useful to call this method from a thread separate from your
145     * primary UI thread.
146     *
147     * @param locationName a user-supplied description of a location
148     * @param maxResults max number of results to return. Smaller numbers (1 to 5) are recommended
149     *
150     * @return a list of Address objects. Returns null or empty list if no matches were
151     * found or there is no backend service available.
152     *
153     * @throws IllegalArgumentException if locationName is null
154     * @throws IOException if the network is unavailable or any other
155     * I/O problem occurs
156     */
157    public List<Address> getFromLocationName(String locationName, int maxResults) throws IOException {
158        if (locationName == null) {
159            throw new IllegalArgumentException("locationName == null");
160        }
161        try {
162            List<Address> results = new ArrayList<Address>();
163            String ex = mService.getFromLocationName(locationName,
164                0, 0, 0, 0, maxResults, mLanguage, mCountry, mVariant, mAppName, results);
165            if (ex != null) {
166                throw new IOException(ex);
167            } else {
168                return results;
169            }
170        } catch (RemoteException e) {
171            Log.e(TAG, "getFromLocationName: got RemoteException", e);
172            return null;
173        }
174    }
175
176    /**
177     * Returns an array of Addresses that are known to describe the
178     * named location, which may be a place name such as "Dalvik,
179     * Iceland", an address such as "1600 Amphitheatre Parkway,
180     * Mountain View, CA", an airport code such as "SFO", etc..  The
181     * returned addresses will be localized for the locale provided to
182     * this class's constructor.
183     *
184     * <p> You may specify a bounding box for the search results by including
185     * the Latitude and Longitude of the Lower Left point and Upper Right
186     * point of the box.
187     *
188     * <p> The query will block and returned values will be obtained by means of a network lookup.
189     * The results are a best guess and are not guaranteed to be meaningful or
190     * correct. It may be useful to call this method from a thread separate from your
191     * primary UI thread.
192     *
193     * @param locationName a user-supplied description of a location
194     * @param maxResults max number of addresses to return. Smaller numbers (1 to 5) are recommended
195     * @param lowerLeftLatitude the latitude of the lower left corner of the bounding box
196     * @param lowerLeftLongitude the longitude of the lower left corner of the bounding box
197     * @param upperRightLatitude the latitude of the upper right corner of the bounding box
198     * @param upperRightLongitude the longitude of the upper right corner of the bounding box
199     *
200     * @return a list of Address objects. Returns null or empty list if no matches were
201     * found or there is no backend service available.
202     *
203     * @throws IllegalArgumentException if locationName is null
204     * @throws IllegalArgumentException if any latitude is
205     * less than -90 or greater than 90
206     * @throws IllegalArgumentException if any longitude is
207     * less than -180 or greater than 180
208     * @throws IOException if the network is unavailable or any other
209     * I/O problem occurs
210     */
211    public List<Address> getFromLocationName(String locationName, int maxResults,
212        double lowerLeftLatitude, double lowerLeftLongitude,
213        double upperRightLatitude, double upperRightLongitude) throws IOException {
214        if (locationName == null) {
215            throw new IllegalArgumentException("locationName == null");
216        }
217        if (lowerLeftLatitude < -90.0 || lowerLeftLatitude > 90.0) {
218            throw new IllegalArgumentException("lowerLeftLatitude == "
219                + lowerLeftLatitude);
220        }
221        if (lowerLeftLongitude < -180.0 || lowerLeftLongitude > 180.0) {
222            throw new IllegalArgumentException("lowerLeftLongitude == "
223                + lowerLeftLongitude);
224        }
225        if (upperRightLatitude < -90.0 || upperRightLatitude > 90.0) {
226            throw new IllegalArgumentException("upperRightLatitude == "
227                + upperRightLatitude);
228        }
229        if (upperRightLongitude < -180.0 || upperRightLongitude > 180.0) {
230            throw new IllegalArgumentException("upperRightLongitude == "
231                + upperRightLongitude);
232        }
233        try {
234            ArrayList<Address> result = new ArrayList<Address>();
235            String ex =  mService.getFromLocationName(locationName,
236                lowerLeftLatitude, lowerLeftLongitude, upperRightLatitude, upperRightLongitude,
237                maxResults, mLanguage, mCountry, mVariant, mAppName, result);
238            if (ex != null) {
239                throw new IOException(ex);
240            } else {
241                return result;
242            }
243        } catch (RemoteException e) {
244            Log.e(TAG, "getFromLocationName: got RemoteException", e);
245            return null;
246        }
247    }
248}
249