无法在 AsyncTask 中获取经纬度
Can't get latitude and longitude in AsyncTask
我正在与 Weather Underground
API 合作,我可以通过两种方式获取某个地方的天气信息:
- 直接写城市和国家的名字(例如:
http://api.wunderground.com/api/*MyKey*/conditions/q/It/Venice.json
)
- 获取每个地方的天气有latitude/longitude(例子:
http://api.wunderground.com/api/*MyKey*/conditions/q/45.43972222,12.33194444.json
)
我对第二种方式很感兴趣,所以我想找到我的位置(在 Activity 中有效)。
FirstActivity.java
:(位置显示没有问题)
public class FirstActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.first_activity);
GPSTracker gpsTracker = new GPSTracker(this);
if (gpsTracker.canGetLocation())
{
String stringLatitude = String.valueOf(gpsTracker.latitude);
TextView textview1 = (TextView)findViewById(R.id.fieldLatitude);
textview1.setText(stringLatitude);
String stringLongitude = String.valueOf(gpsTracker.longitude);
TextView textview2 = (TextView)findViewById(R.id.fieldLongitude);
textview2.setText(stringLongitude);
}
else
{
// can't get location
// GPS or Network is not enabled
// Ask user to enable GPS/network in settings
gpsTracker.showSettingsAlert();
}
}
AsyncTask
:
public class Conditions extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.weather_conditions);
new WeatherConditions(this).execute();
}
private class WeatherConditions extends AsyncTask<String, String, String> {
private Context mContext;
public WeatherConditions (Context context){
mContext = context;
}
@Override
protected String doInBackground(String... uri) {
GPSTracker gpsTracker = new GPSTracker(mContext);
String latitudine = null;
String longitudine = null;
if (gpsTracker.canGetLocation())
{
latitudine = String.valueOf(gpsTracker.latitude);
longitudine = String.valueOf(gpsTracker.longitude);
}
else
{
// can't get location
// GPS or Network is not enabled
// Ask user to enable GPS/network in settings
gpsTracker.showSettingsAlert();
}
String responseString = null;
try {
HttpClient client = new DefaultHttpClient();
URI apiCall = new URI("api.wunderground.com/api/51cda8abeca78e10/conditions/q/"
+ latitudine
+","
+ longitudine
+".json");
HttpGet request = new HttpGet();
request.setURI(apiCall);
HttpResponse response = client.execute(request);
responseString = EntityUtils.toString(response.getEntity());
} catch (Exception e) {
Log.e("TAG", "some sort of problem encountered", e);
}
return responseString;
}
@Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
...
}
}
}
我在 LogCat 中收到此消息的位置:无法在未调用 Looper.prepare()[=19= 的线程内创建处理程序]
这里是GPSTracker.java
:
public class GPSTracker extends Service implements LocationListener{
private final Context mContext;
boolean isGPSEnabled = false;
boolean isNetworkEnabled = false;
boolean canGetLocation = false;
Location location;
double latitude;
double longitude;
private static final long MIN_DISTANCE_CHANGE_FOR_UPDATES = 10; //10 metters
private static final long MIN_TIME_BW_UPDATES = 1000 * 60 * 1; // 1 minute
protected LocationManager locationManager;
public GPSTracker(Context context)
{
this.mContext = context;
getLocation();
}
public Location getLocation()
{
try
{
locationManager = (LocationManager) mContext.getSystemService(LOCATION_SERVICE);
isGPSEnabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
isNetworkEnabled = locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
if (!isGPSEnabled && !isNetworkEnabled)
{
}
else
{
this.canGetLocation = true;
if (isNetworkEnabled)
{
locationManager.requestLocationUpdates(
LocationManager.NETWORK_PROVIDER,
MIN_TIME_BW_UPDATES,
MIN_DISTANCE_CHANGE_FOR_UPDATES, this);
Log.d("Network", "Network");
if (locationManager != null)
{
location = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
updateGPSCoordinates();
}
}
if (isGPSEnabled)
{
if (location == null)
{
locationManager.requestLocationUpdates(
LocationManager.GPS_PROVIDER,
MIN_TIME_BW_UPDATES,
MIN_DISTANCE_CHANGE_FOR_UPDATES, this);
Log.d("GPS Enabled", "GPS Enabled");
if (locationManager != null)
{
location = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
updateGPSCoordinates();
}
}
}
}
}
catch (Exception e)
{
//e.printStackTrace();
Log.e("Error : Location", "Impossible to connect to LocationManager", e);
}
return location;
}
public void updateGPSCoordinates()
{
if (location != null)
{
latitude = location.getLatitude();
longitude = location.getLongitude();
}
}
public void stopUsingGPS()
{
if (locationManager != null)
{
locationManager.removeUpdates(GPSTracker.this);
}
}
public double getLatitude()
{
if (location != null)
{
latitude = location.getLatitude();
}
return latitude;
}
public double getLongitude()
{
if (location != null)
{
longitude = location.getLongitude();
}
return longitude;
}
public boolean canGetLocation()
{
return this.canGetLocation;
}
public void showSettingsAlert()
{
AlertDialog.Builder alertDialog = new AlertDialog.Builder(mContext);
alertDialog.setTitle("Attenzione!");
alertDialog.setMessage("Abilita il GPS");
alertDialog.setPositiveButton("OK", new DialogInterface.OnClickListener()
{
@Override
public void onClick(DialogInterface dialog, int which)
{
Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
mContext.startActivity(intent);
}
});
alertDialog.setNegativeButton("CLOSE", new DialogInterface.OnClickListener()
{
@Override
public void onClick(DialogInterface dialog, int which)
{
dialog.cancel();
}
});
alertDialog.show();
}
public List<Address> getGeocoderAddress(Context context)
{
if (location != null)
{
Geocoder geocoder = new Geocoder(context, Locale.ENGLISH);
try
{
return geocoder.getFromLocation(latitude, longitude, 1);
}
catch (IOException e)
{
//e.printStackTrace();
Log.e("Error : Geocoder", "Impossible to connect to Geocoder", e);
}
}
return null;
}
public String getAddressLine(Context context)
{
List<Address> addresses = getGeocoderAddress(context);
if (addresses != null && addresses.size() > 0)
{
Address address = addresses.get(0);
return address.getAddressLine(0);
}
else
{
return null;
}
}
public String getLocality(Context context)
{
List<Address> addresses = getGeocoderAddress(context);
if (addresses != null && addresses.size() > 0)
{
Address address = addresses.get(0);
return address.getLocality();
}
else
{
return null;
}
}
public String getSubLocality(Context context)
{
List<Address> addresses = getGeocoderAddress(context);
if (addresses != null && addresses.size() > 0)
{
Address address = addresses.get(0);
return address.getSubLocality();
}
else
{
return null;
}
}
public String getPostalCode(Context context)
{
List<Address> addresses = getGeocoderAddress(context);
if (addresses != null && addresses.size() > 0)
{
Address address = addresses.get(0);
return address.getPostalCode();
}
else
{
return null;
}
}
public String getCountryName(Context context)
{
List<Address> addresses = getGeocoderAddress(context);
if (addresses != null && addresses.size() > 0)
{
Address address = addresses.get(0);
return address.getCountryName();
}
else
{
return null;
}
}
@Override
public void onLocationChanged(Location location)
{
}
@Override
public void onProviderDisabled(String provider)
{
}
@Override
public void onProviderEnabled(String provider)
{
}
@Override
public void onStatusChanged(String provider, int status, Bundle extras)
{
}
@Override
public IBinder onBind(Intent intent)
{
return null;
}
在 GPSTracker.java
中,因为 getLocation()
附加了异步任务的上下文并且没有附加循环程序。
解决此问题的快速解决方法是添加 Looper.getMainLooper()
和 requestLocationUpdates
,这将在请求中附加主循环线程回调。
locationManager.requestLocationUpdates(
LocationManager.NETWORK_PROVIDER,
MIN_TIME_BW_UPDATES,
MIN_DISTANCE_CHANGE_FOR_UPDATES, this, Looper.getMainLooper()
);
我正在与 Weather Underground
API 合作,我可以通过两种方式获取某个地方的天气信息:
- 直接写城市和国家的名字(例如:
http://api.wunderground.com/api/*MyKey*/conditions/q/It/Venice.json
) - 获取每个地方的天气有latitude/longitude(例子:
http://api.wunderground.com/api/*MyKey*/conditions/q/45.43972222,12.33194444.json
)
我对第二种方式很感兴趣,所以我想找到我的位置(在 Activity 中有效)。
FirstActivity.java
:(位置显示没有问题)
public class FirstActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.first_activity);
GPSTracker gpsTracker = new GPSTracker(this);
if (gpsTracker.canGetLocation())
{
String stringLatitude = String.valueOf(gpsTracker.latitude);
TextView textview1 = (TextView)findViewById(R.id.fieldLatitude);
textview1.setText(stringLatitude);
String stringLongitude = String.valueOf(gpsTracker.longitude);
TextView textview2 = (TextView)findViewById(R.id.fieldLongitude);
textview2.setText(stringLongitude);
}
else
{
// can't get location
// GPS or Network is not enabled
// Ask user to enable GPS/network in settings
gpsTracker.showSettingsAlert();
}
}
AsyncTask
:
public class Conditions extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.weather_conditions);
new WeatherConditions(this).execute();
}
private class WeatherConditions extends AsyncTask<String, String, String> {
private Context mContext;
public WeatherConditions (Context context){
mContext = context;
}
@Override
protected String doInBackground(String... uri) {
GPSTracker gpsTracker = new GPSTracker(mContext);
String latitudine = null;
String longitudine = null;
if (gpsTracker.canGetLocation())
{
latitudine = String.valueOf(gpsTracker.latitude);
longitudine = String.valueOf(gpsTracker.longitude);
}
else
{
// can't get location
// GPS or Network is not enabled
// Ask user to enable GPS/network in settings
gpsTracker.showSettingsAlert();
}
String responseString = null;
try {
HttpClient client = new DefaultHttpClient();
URI apiCall = new URI("api.wunderground.com/api/51cda8abeca78e10/conditions/q/"
+ latitudine
+","
+ longitudine
+".json");
HttpGet request = new HttpGet();
request.setURI(apiCall);
HttpResponse response = client.execute(request);
responseString = EntityUtils.toString(response.getEntity());
} catch (Exception e) {
Log.e("TAG", "some sort of problem encountered", e);
}
return responseString;
}
@Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
...
}
}
}
我在 LogCat 中收到此消息的位置:无法在未调用 Looper.prepare()[=19= 的线程内创建处理程序]
这里是GPSTracker.java
:
public class GPSTracker extends Service implements LocationListener{
private final Context mContext;
boolean isGPSEnabled = false;
boolean isNetworkEnabled = false;
boolean canGetLocation = false;
Location location;
double latitude;
double longitude;
private static final long MIN_DISTANCE_CHANGE_FOR_UPDATES = 10; //10 metters
private static final long MIN_TIME_BW_UPDATES = 1000 * 60 * 1; // 1 minute
protected LocationManager locationManager;
public GPSTracker(Context context)
{
this.mContext = context;
getLocation();
}
public Location getLocation()
{
try
{
locationManager = (LocationManager) mContext.getSystemService(LOCATION_SERVICE);
isGPSEnabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
isNetworkEnabled = locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
if (!isGPSEnabled && !isNetworkEnabled)
{
}
else
{
this.canGetLocation = true;
if (isNetworkEnabled)
{
locationManager.requestLocationUpdates(
LocationManager.NETWORK_PROVIDER,
MIN_TIME_BW_UPDATES,
MIN_DISTANCE_CHANGE_FOR_UPDATES, this);
Log.d("Network", "Network");
if (locationManager != null)
{
location = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
updateGPSCoordinates();
}
}
if (isGPSEnabled)
{
if (location == null)
{
locationManager.requestLocationUpdates(
LocationManager.GPS_PROVIDER,
MIN_TIME_BW_UPDATES,
MIN_DISTANCE_CHANGE_FOR_UPDATES, this);
Log.d("GPS Enabled", "GPS Enabled");
if (locationManager != null)
{
location = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
updateGPSCoordinates();
}
}
}
}
}
catch (Exception e)
{
//e.printStackTrace();
Log.e("Error : Location", "Impossible to connect to LocationManager", e);
}
return location;
}
public void updateGPSCoordinates()
{
if (location != null)
{
latitude = location.getLatitude();
longitude = location.getLongitude();
}
}
public void stopUsingGPS()
{
if (locationManager != null)
{
locationManager.removeUpdates(GPSTracker.this);
}
}
public double getLatitude()
{
if (location != null)
{
latitude = location.getLatitude();
}
return latitude;
}
public double getLongitude()
{
if (location != null)
{
longitude = location.getLongitude();
}
return longitude;
}
public boolean canGetLocation()
{
return this.canGetLocation;
}
public void showSettingsAlert()
{
AlertDialog.Builder alertDialog = new AlertDialog.Builder(mContext);
alertDialog.setTitle("Attenzione!");
alertDialog.setMessage("Abilita il GPS");
alertDialog.setPositiveButton("OK", new DialogInterface.OnClickListener()
{
@Override
public void onClick(DialogInterface dialog, int which)
{
Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
mContext.startActivity(intent);
}
});
alertDialog.setNegativeButton("CLOSE", new DialogInterface.OnClickListener()
{
@Override
public void onClick(DialogInterface dialog, int which)
{
dialog.cancel();
}
});
alertDialog.show();
}
public List<Address> getGeocoderAddress(Context context)
{
if (location != null)
{
Geocoder geocoder = new Geocoder(context, Locale.ENGLISH);
try
{
return geocoder.getFromLocation(latitude, longitude, 1);
}
catch (IOException e)
{
//e.printStackTrace();
Log.e("Error : Geocoder", "Impossible to connect to Geocoder", e);
}
}
return null;
}
public String getAddressLine(Context context)
{
List<Address> addresses = getGeocoderAddress(context);
if (addresses != null && addresses.size() > 0)
{
Address address = addresses.get(0);
return address.getAddressLine(0);
}
else
{
return null;
}
}
public String getLocality(Context context)
{
List<Address> addresses = getGeocoderAddress(context);
if (addresses != null && addresses.size() > 0)
{
Address address = addresses.get(0);
return address.getLocality();
}
else
{
return null;
}
}
public String getSubLocality(Context context)
{
List<Address> addresses = getGeocoderAddress(context);
if (addresses != null && addresses.size() > 0)
{
Address address = addresses.get(0);
return address.getSubLocality();
}
else
{
return null;
}
}
public String getPostalCode(Context context)
{
List<Address> addresses = getGeocoderAddress(context);
if (addresses != null && addresses.size() > 0)
{
Address address = addresses.get(0);
return address.getPostalCode();
}
else
{
return null;
}
}
public String getCountryName(Context context)
{
List<Address> addresses = getGeocoderAddress(context);
if (addresses != null && addresses.size() > 0)
{
Address address = addresses.get(0);
return address.getCountryName();
}
else
{
return null;
}
}
@Override
public void onLocationChanged(Location location)
{
}
@Override
public void onProviderDisabled(String provider)
{
}
@Override
public void onProviderEnabled(String provider)
{
}
@Override
public void onStatusChanged(String provider, int status, Bundle extras)
{
}
@Override
public IBinder onBind(Intent intent)
{
return null;
}
在 GPSTracker.java
中,因为 getLocation()
附加了异步任务的上下文并且没有附加循环程序。
解决此问题的快速解决方法是添加 Looper.getMainLooper()
和 requestLocationUpdates
,这将在请求中附加主循环线程回调。
locationManager.requestLocationUpdates(
LocationManager.NETWORK_PROVIDER,
MIN_TIME_BW_UPDATES,
MIN_DISTANCE_CHANGE_FOR_UPDATES, this, Looper.getMainLooper()
);