我正在尝试通过android中的给定位置获取cityname和国家/地区名称,但我无法做到这一点。我需要在所有情况下获得它们,没有gps,互联网连接,或者所有这些都打开了。
我试过了GeoCoder
,但我收到了这个错误:
11-29 11:54:01.718: W/System.err(32200): at com.myapp.Main$4.gotLocation(Main.java:282)
11-29 11:54:01.718: W/System.err(32200): at com.myapp.services.MyLocation$GetLastLocation.run(MyLocation.java:124)
geoCoder位于我的MainActivity中的gotLocation内部
这是我的代码:
Log.v("--", "got location ="+location.getLatitude()+" | "+location.getLongitude());
try {
Geocoder gcd = new Geocoder(Main.this, Locale.getDefault());
List<Address> addresses;
//im getting an error in this line and checked location values are OK
addresses = gcd.getFromLocation(location.getLatitude(), location.getLongitude(), 1);
Log.v("--", addresses.size()+" got location address size");
if (addresses.size() > 0) {
city = addresses.get(0).getLocality();
country = addresses.get(0).getCountryName();
prefs.edit().putString(Constants.COUNTRY, country).commit();
prefs.edit().putString(Constants.CITY, city).commit();
} else {
city = a.getString(R.string.app_name);
country = "France";
}
Log.v("--", "got location"+city+" | "+country);
}catch(Exception e){
Log.v("--", "got location failed");
e.printStackTrace();
}
和MyLocation类代码:
public class MyLocation {
Timer timer1;
LocationManager lm;
LocationResult locationResult;
boolean gps_enabled = false;
boolean network_enabled = false;
private Context context;
public boolean getLocation(Context context, LocationResult result) {
// I use LocationResult callback class to pass location value from
// MyLocation to user code.
locationResult = result;
this.context = context;
if (lm == null)
lm = (LocationManager) context
.getSystemService(Context.LOCATION_SERVICE);
// exceptions will be thrown if provider is not permitted.
try {
gps_enabled = lm.isProviderEnabled(LocationManager.GPS_PROVIDER);
} catch (Exception ex) {
}
try {
network_enabled = lm
.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
} catch (Exception ex) {
}
// don't start listeners if no provider is enabled
if (!gps_enabled && !network_enabled)
return false;
if (gps_enabled)
lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0,
locationListenerGps);
if (network_enabled)
lm.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0,
locationListenerNetwork);
timer1 = new Timer();
timer1.schedule(new GetLastLocation(), 20000);
return true;
}
LocationListener locationListenerGps = new LocationListener() {
public void onLocationChanged(Location location) {
timer1.cancel();
locationResult.gotLocation(location);
lm.removeUpdates(this);
lm.removeUpdates(locationListenerNetwork);
}
public void onProviderDisabled(String provider) {
}
public void onProviderEnabled(String provider) {
}
public void onStatusChanged(String provider, int status, Bundle extras) {
}
};
LocationListener locationListenerNetwork = new LocationListener() {
public void onLocationChanged(Location location) {
timer1.cancel();
locationResult.gotLocation(location);
lm.removeUpdates(this);
lm.removeUpdates(locationListenerGps);
}
public void onProviderDisabled(String provider) {
}
public void onProviderEnabled(String provider) {
}
public void onStatusChanged(String provider, int status, Bundle extras) {
}
};
class GetLastLocation extends TimerTask {
private Handler mHandler = new Handler(Looper.getMainLooper());
Location net_loc,gps_loc;
@Override
public void run() {
mHandler.post(new Runnable() {
public void run() {
lm.removeUpdates(locationListenerGps);
lm.removeUpdates(locationListenerNetwork);
net_loc = null; gps_loc = null;
if (gps_enabled)
gps_loc = lm.getLastKnownLocation(LocationManager.GPS_PROVIDER);
if (network_enabled)
net_loc = lm
.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
// if there are both values use the latest one
if (gps_loc != null && net_loc != null) {
if (gps_loc.getTime() > net_loc.getTime())
locationResult.gotLocation(gps_loc);
else
locationResult.gotLocation(net_loc);
return;
}
if (gps_loc != null) {
locationResult.gotLocation(gps_loc);
timer1.notifyAll();
return;
}
if (net_loc != null) {
locationResult.gotLocation(net_loc);
return;
}
locationResult.gotLocation(null);
}
});
}
}
public void cancelTimer() {
timer1.cancel();
lm.removeUpdates(locationListenerGps);
lm.removeUpdates(locationListenerNetwork);
}
public static abstract class LocationResult {
public abstract void gotLocation(Location location);
}
}
那么有人可以帮我解决这个问题吗?
答案 0 :(得分:0)
您可以使用以下代码
public class GeocoderModel {
private String streetNumber;
private String rout;
private String subLocality;
private String political;
private String country;
// getter and setter
}
自定义geoCoder类:
import android.content.Context;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.location.Address;
import android.util.Log;
import org.json.JSONArray;
import org.json.JSONObject;
import java.io.IOException;
import java.net.URLEncoder;
import java.util.Locale;
/**
* 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.
* <p/>
* This is a replacement of built-in Geocoder which is not always available.
* This implementation parses just a formatted address and is guaranteed to
* work.
*/
public final class Geocoder {
private static final String PREFERENCES_GEOCODER = Geocoder.class.getName()
+ ".GEOCODER";
private static final String KEY_ALLOW = Geocoder.class.getName()
+ ".KEY_ALLOW";
/*
* Status codes which we handle
*/
/**
* Indicates that no errors occurred; the address was successfully parsed
* and at least one geocode was returned.
*/
private static final String STATUS_OK = "OK";
/**
* Indicates that you are over your quota.
*/
private static final String STATUS_OVER_QUERY_LIMIT = "OVER_QUERY_LIMIT";
private final Context context;
/**
* Constructs a Geocoder whose responses will be localized for the default
* system Locale.
*
* @param context the Context of the calling Activity
*/
public Geocoder(Context context) {
this.context = context;
}
/**
* Returns an array of Addresses that are known to describe the area
* immediately surrounding the given latitude and longitude. The returned
* addresses will be localized for the locale provided to this class's
* constructor.
* <p/>
* <p/>
* The returned values may be obtained by means of a network lookup. The
* results are a best guess and are not guaranteed to be meaningful or
* correct. It may be useful to call this method from a thread separate from
* your primary UI thread.
*
* @param latitude the latitude a point for the search
* @param longitude the longitude a point for the search
* @param maxResults max number of addresses to return. Smaller numbers (1 to 5)
* are recommended
* @return a list of Address objects. Returns null or empty list if no
* matches were found or there is no backend service available.
* @throws IllegalArgumentException if latitude is less than -90 or greater than 90
* @throws IllegalArgumentException if longitude is less than -180 or greater than 180
* @throws java.io.IOException if the network is unavailable or any other I/O problem occurs
*/
public GeocoderModel getFromLocation(double latitude, double longitude,
int maxResults) throws IOException, LimitExceededException {
if (latitude < -90.0 || latitude > 90.0) {
throw new IllegalArgumentException("latitude == " + latitude);
}
if (longitude < -180.0 || longitude > 180.0) {
throw new IllegalArgumentException("longitude == " + longitude);
}
if (isLimitExceeded(context)) {
throw new LimitExceededException();
}
final GeocoderModel results = new GeocoderModel();
final StringBuilder url = new StringBuilder(
"http://maps.googleapis.com/maps/api/geocode/json?sensor=true&latlng=");
url.append(latitude);
url.append(',');
url.append(longitude);
url.append("&language=");
url.append(Locale.ENGLISH);
final byte[] data = WebserviceClient.download(url.toString());
if (data != null) {
this.parseJson(results, maxResults, data);
}
return results;
}
/**
* Returns an array of Addresses that are known to describe the named
* location, which may be a place name such as "Dalvik,
* Iceland", an address such as "1600 Amphitheatre Parkway, Mountain View,
* CA", an airport code such as "SFO", etc.. The returned addresses will be
* localized for the locale provided to this class's constructor.
* <p/>
* <p/>
* The query will block and returned values will be obtained by means of a
* network lookup. The results are a best guess and are not guaranteed to be
* meaningful or correct. It may be useful to call this method from a thread
* separate from your primary UI thread.
*
* @param locationName a user-supplied description of a location
* @param maxResults max number of results to return. Smaller numbers (1 to 5) are
* recommended
* @return a list of Address objects. Returns null or empty list if no
* matches were found or there is no backend service available.
* @throws IllegalArgumentException if locationName is null
* @throws java.io.IOException if the network is unavailable or any other I/O problem occurs
*/
public GeocoderModel getFromLocationName(String locationName, int
maxResults)
throws IOException, LimitExceededException {
if (locationName == null) {
throw new IllegalArgumentException("locationName == null");
}
if (isLimitExceeded(context)) {
throw new LimitExceededException();
}
final GeocoderModel results = new GeocoderModel();
final StringBuilder request = new StringBuilder(
"http://maps.googleapis.com/maps/api/geocode/json?sensor=false");
request.append("&language=").append(Locale.getDefault().getLanguage());
request.append("&address=").append(
URLEncoder.encode(locationName, "UTF-8"));
byte[] data = WebserviceClient.download(request.toString());
if (data != null) {
try {
this.parseJson(results, maxResults, data);
} catch (LimitExceededException e) {
// LimitExceededException could be thrown if too many calls per
// second
// If after two seconds, it is thrown again - then it means
// there are too much calls per 24 hours
try {
Thread.sleep(2000);
} catch (InterruptedException e1) {
return results;
}
data = WebserviceClient.download(request.toString());
if (data != null) {
try {
this.parseJson(results, maxResults, data);
} catch (LimitExceededException lee) {
// available in 24 hours
setAllowedDate(context,
System.currentTimeMillis() + 86400000L);
throw lee;
}
}
}
}
return results;
}
private void parseJson(GeocoderModel geoCoderModel, int maxResults,
byte[] data) throws LimitExceededException {
try {
final String json = new String(data, "UTF-8");
final JSONObject o = new JSONObject(json);
final String status = o.getString("status");
if (status.equals(STATUS_OK)) {
final JSONArray a = o.getJSONArray("results");
// for (int i = 0; i < maxResults && i < a.length(); i++) {
final Address current = new Address(Locale.getDefault());
final JSONObject item = a.getJSONObject(0);
JSONArray addressComponnet = item
.getJSONArray("address_components");
for (int i = 0; i < addressComponnet.length(); i++) {
JSONObject temp = addressComponnet.getJSONObject(i);
Log.d("temp is", temp.toString());
JSONArray type = temp.getJSONArray("types");
if (type.toString().contains("street_number")) {
geoCoderModel.setStreetNumber(temp
.getString("long_name"));
} else if (type.toString().contains("rout")) {
geoCoderModel.setRout(temp.getString("long_name"));
} else if (type.toString().contains("country")) {
geoCoderModel.setCountry(temp.getString("long_name"));
} else if (type.toString().contains("political")) {
if ((geoCoderModel.getPolitical().length() - geoCoderModel
.getPolitical().replace("|", "").length()) < 3
|| type.toString().contains(
"administrative_area_level_1"))
geoCoderModel.setPolitical(temp
.getString("long_name"));
} else if (type.toString().contains("sublocality")) {
geoCoderModel.setRout(geoCoderModel.getRout() + " "
+ temp.getString("long_name"));
}
}
} else if (status.equals(STATUS_OVER_QUERY_LIMIT)) {
throw new LimitExceededException();
}
} catch (LimitExceededException e) {
throw e;
} catch (Throwable e) {
e.printStackTrace();
}
}
/**
* Returns true if limit is exceeded and next query is not allowed
*
* @param context Current context
* @return true if limit is exceeded and next query is not allowed; false
* otherwise
*/
private static boolean isLimitExceeded(Context context) {
return System.currentTimeMillis() <= getAllowedDate(context);
}
/**
* Sets date after which next geocoding query is allowed
*
* @param context Current context
* @param date the date after which next geocoding query is allowed
*/
private static void setAllowedDate(Context context, long date) {
final SharedPreferences p = context.getSharedPreferences(
PREFERENCES_GEOCODER, Context.MODE_PRIVATE);
final Editor e = p.edit();
e.putLong(KEY_ALLOW, date);
e.commit();
}
/**
* Returns date after which the next geocoding query is allowed
*
* @param context Current context
* @return date after which the next geocoding query is allowed
*/
private static long getAllowedDate(Context context) {
final SharedPreferences p = context.getSharedPreferences(
PREFERENCES_GEOCODER, Context.MODE_PRIVATE);
return p.getLong(KEY_ALLOW, 0);
}
/**
* Is thrown when the query was over limit before 24 hours
*/
public static final class LimitExceededException extends Exception {
private static final long serialVersionUID = -1243645207607944474L;
}
}
WebServiceClient此类:
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;
public class WebserviceClient {
public static byte[] download(String url) {
InputStream is = null;
ByteArrayOutputStream os = null;
try {
final URL u = new URL(url);
final URLConnection connection = u.openConnection();
connection.connect();
is = connection.getInputStream();
os = new ByteArrayOutputStream();
final byte[] buffer = new byte[5120];
int read;
while (true) {
read = is.read(buffer, 0, buffer.length);
if (read == -1)
break;
os.write(buffer, 0, read);
}
return os.toByteArray();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (is != null)
try {
is.close();
} catch (IOException ignored) {
}
if (os != null)
try {
os.close();
} catch (IOException ignored) {
}
}
return null;
}
}
您可以使用以下方法获取数据。
geocoderModel = geocoder.getFromLocation(latLng.latitude, latLng.longitude, 5);
您通过此代码获得了所有地址。我希望这能帮到你