I'm working with Weather Underground API where I can get weather of a place in 2 ways:
- Writing directly the name of the city and nation (example:
http://api.wunderground.com/api/*MyKey*/conditions/q/It/Venice.json) - Get the weather of every place have latitude/longitude (example:
http://api.wunderground.com/api/*MyKey*/conditions/q/45.43972222,12.33194444.json)
I'm interested in the second way so I'm trying to get my position (that works in an Activity).
FirstActivity.java: (the position is displayed with no problem)
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);
...
}
}
}
Where I get this message in the LogCat: Can't create handler inside thread that has not called Looper.prepare()
Here's 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;
}
In
GPSTracker.java, sincegetLocation()has context of async task attached to it and looper is not attached to it.A quick workaround to solve this problem is add
Looper.getMainLooper()withrequestLocationUpdates, this will attach main looper thread callback with request.