无法在 AsyncTask 中获取经纬度

Can't get latitude and longitude in AsyncTask

我正在与 Weather Underground API 合作,我可以通过两种方式获取某个地方的天气信息:

  1. 直接写城市和国家的名字(例如:http://api.wunderground.com/api/*MyKey*/conditions/q/It/Venice.json
  2. 获取每个地方的天气有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()
);