Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

Android Build a Weather App (2015) Hooking Up the Model to the View Wrapping Up

Christopher Ahn
Christopher Ahn
3,105 Points

Adding location awareness to weather app, but progress bar does not stop spinning!

I have been trying to implement location awareness to the stormy app through the guide listed in the teachers note http://blog.teamtreehouse.com/beginners-guide-location-android .

I followed the guide and checked out the example on github and started implementing location awareness that way.

I get the lat/long and I am able to successfully gather the data, but the progressbar does not stop spinning and I cannot figure out why.

package com.chrisahn.weatherapp.ui;

import android.content.Context; import android.graphics.drawable.Drawable; import android.location.Location; import android.location.LocationManager; import android.os.Bundle; import android.support.v7.app.ActionBarActivity; import android.util.Log; import android.view.View; import android.widget.ImageView; import android.widget.ProgressBar; import android.widget.TextView; import android.widget.Toast;

import com.chrisahn.weatherapp.R; import com.chrisahn.weatherapp.locations.LocationProvider; import com.chrisahn.weatherapp.weather.Current; import com.chrisahn.weatherapp.weather.Day; import com.chrisahn.weatherapp.weather.Forecast; import com.chrisahn.weatherapp.weather.Hour; import com.squareup.okhttp.Call; import com.squareup.okhttp.Callback; import com.squareup.okhttp.OkHttpClient; import com.squareup.okhttp.Request; import com.squareup.okhttp.Response;

import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject;

import java.io.IOException;

import butterknife.ButterKnife; import butterknife.InjectView;

public class CurrentLocationForecast extends ActionBarActivity implements LocationProvider.LocationCallback {

private static final String TAG = CurrentLocationForecast.class.getSimpleName();

@InjectView(R.id.timeLabel) TextView mTimeLabel;
@InjectView(R.id.temperatureLabel) TextView mTemperatureLabel;
@InjectView(R.id.humidityValue) TextView mHumidityValue;
@InjectView(R.id.precipValue) TextView mPrecipValue;
@InjectView(R.id.summaryLabel) TextView mSummaryLabel;
@InjectView(R.id.iconImageView) ImageView mIconImageView;
@InjectView(R.id.refreshImageView) ImageView mRefreshImageView;
@InjectView(R.id.progressBar) ProgressBar mProgressBar;

private double mLatitude;
private double mLongitude;

private Forecast mForecast;

private LocationProvider mLocationProvider;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_current_location_forecast);
    ButterKnife.inject(this);
    mLocationProvider = new LocationProvider(this, this);

    mProgressBar.setVisibility(View.INVISIBLE);

/* if (isGpsOn()) { Toast.makeText(this, mLatitude + " " + mLongitude, Toast.LENGTH_LONG).show(); getLocationForecast(mLatitude, mLongitude); } else { Toast.makeText(this, "GPS is disabled. Please enable GPS", Toast.LENGTH_LONG).show(); }

    mRefreshImageView.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            getLocationForecast(mLatitude, mLongitude);
        }
    }); */

}

@Override
protected void onResume() {
    super.onResume();
    mLocationProvider.connect();
}

// Stop the location updates when the activity is not in focus
@Override
protected void onPause() {
    super.onPause();
    mLocationProvider.disconnect();
}

public void handleNewLocation(Location location) {
    Log.d(TAG, location.toString());

    mLatitude  = location.getLatitude();
    mLongitude = location.getLongitude();

    if (isGpsOn()) {
        Toast.makeText(this, mLatitude + " " + mLongitude, Toast.LENGTH_LONG).show();
        getLocationForecast(mLatitude, mLongitude);
    }
    else {
        Toast.makeText(this, "GPS is disabled. Please enable GPS", Toast.LENGTH_LONG).show();
    }

    mRefreshImageView.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            getLocationForecast(mLatitude, mLongitude);
        }
    });
    //LatLng latLng = new LatLng(mLatitude, mLongitude);
}

public void getLocationForecast(double latitude, double longitude) {
    String ApiKey = "f4a73f20558d9eba16d1a065c44a5b4d";
    String url = "https://api.forecast.io/forecast/" + ApiKey +"/" + latitude
            + "," + longitude;

    // Requesting url
    OkHttpClient client = new OkHttpClient();
    Request request = new Request.Builder()
            .url(url)
            .build();
    Call response = client.newCall(request);
    // Call in background
    response.enqueue(new Callback() {
        @Override
        public void onFailure(Request request, IOException e) {
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    toggleRefresh();
                }
            }); alertUserError();
        }

        @Override
        public void onResponse(Response response) throws IOException {
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    toggleRefresh();
                }
            });
            try {
                String jsonData = response.body().string();
                Log.v(TAG, jsonData);
                if (response.isSuccessful()) {
                    mForecast = parseForecastData(jsonData);
                    runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            updateDisplay();
                        }
                    });


                } else {
                    alertUserError();
                }
            }
            catch (IOException e) {
                Log.e(TAG, "Exception caught: ", e);
            }
            catch (JSONException e) {
                Log.e(TAG, "Exception caught: ", e);
            }

        }
    });

}

private void updateDisplay() {
    Current current = mForecast.getCurrent();
    mTemperatureLabel.setText(current.getTemperature() + "");
    mHumidityValue.setText(current.getHumidity() + "");
    mPrecipValue.setText(current.getPrecipChance() + "");
    mSummaryLabel.setText(current.getSummary());
    mTimeLabel.setText("At " + current.getFormattedTime() + " it will be");

    Drawable drawable = getResources().getDrawable(current.getIconId());
    mIconImageView.setImageDrawable(drawable);

}

private Forecast parseForecastData(String jsonData) throws JSONException {
    Forecast forecast = new Forecast();

    forecast.setCurrent(getCurrentDetails(jsonData));
    forecast.setDailyForecast(getDailyDetails(jsonData));
    forecast.setHourlyForecast(getHourDetails(jsonData));

    return forecast;
}

private Current getCurrentDetails(String jsonData) throws JSONException {
    JSONObject forecast = new JSONObject(jsonData);
    String timezone = forecast.getString("timezone");
    JSONObject currently = forecast.getJSONObject("currently");

    Current current = new Current();
    current.setHumidity(currently.getDouble("humidity"));
    current.setIcon(currently.getString("icon"));
    current.setPrecipChance(currently.getDouble("precipProbability"));
    current.setSummary(currently.getString("summary"));
    current.setTemperature(currently.getDouble("temperature"));
    current.setTime(currently.getLong("time"));
    current.setTimeZone(timezone);

    return current;
}

private Day[] getDailyDetails(String jsonData) throws JSONException {
    JSONObject forecast = new JSONObject(jsonData);
    String timezone = forecast.getString("timezone");
    JSONObject daily = forecast.getJSONObject("daily");
    JSONArray data = daily.getJSONArray("data");
    Day[] days = new Day[data.length()];

    for (int i = 0; i < data.length(); i++) {
        JSONObject jsonDay = data.getJSONObject(i);
        Day day = new Day();
        day.setTime(jsonDay.getLong("time"));
        day.setSummary(jsonDay.getString("summary"));
        day.setIcon(jsonDay.getString("icon"));
        day.setTemperatureMax(jsonDay.getDouble("temperatureMax"));
        day.setTimezone(timezone);

        days[i] = day;
    }

    return days;
}

private Hour[] getHourDetails(String jsonData) throws JSONException {
    JSONObject forecast = new JSONObject(jsonData);
    String timezone = forecast.getString("timezone");
    JSONObject hourly = forecast.getJSONObject("hourly");
    JSONArray data = hourly.getJSONArray("data");
    Hour[] hours = new Hour[data.length()];

    for (int i = 0; i < data.length(); i++) {
        JSONObject jsonHour = data.getJSONObject(i);
        Hour hour = new Hour();
        hour.setTimezone(timezone);
        hour.setTime(jsonHour.getLong("time"));
        hour.setIcon(jsonHour.getString("icon"));
        hour.setSummary(jsonHour.getString("summary"));
        hour.setTemperature(jsonHour.getDouble("temperature"));
        hours[i] = hour;
    }

    return hours;
}

// Check to see if GPS is enabled
public boolean isGpsOn() {
    boolean gpsAvail = false;
    LocationManager locationManager = (LocationManager)getSystemService(Context.LOCATION_SERVICE);
    boolean gpsStatus = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);

    if (gpsStatus) {
        gpsAvail = true;
    }
    return gpsAvail;
}

private void toggleRefresh() {
    if (mProgressBar.getVisibility() == View.INVISIBLE) {
        mProgressBar.setVisibility(View.VISIBLE);
        mRefreshImageView.setVisibility(View.INVISIBLE);
    }
    else {
        mProgressBar.setVisibility(View.INVISIBLE);
        mRefreshImageView.setVisibility(View.VISIBLE);
    }
}

public void alertUserError() {
    AlertDialogFragment dialog = new AlertDialogFragment();
    dialog.show(getFragmentManager(),"error_dialog");
}

}

This is the code I currently have. I only implemented the current details so far to check if everything worked, then I found this problem.

package com.chrisahn.weatherapp.locations;

import android.app.Activity; import android.content.Context; import android.content.IntentSender; import android.location.Location; import android.os.Bundle; import android.util.Log;

import com.google.android.gms.common.ConnectionResult; import com.google.android.gms.common.api.GoogleApiClient; import com.google.android.gms.location.LocationListener; import com.google.android.gms.location.LocationRequest; import com.google.android.gms.location.LocationServices;

public class LocationProvider implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, LocationListener {

public abstract interface LocationCallback {
    public void handleNewLocation(Location location);
}

public static final String TAG = LocationProvider.class.getSimpleName();


 /* Define a request code to send to Google Play services
 * This code is returned in Activity.onActivityResult
 */
private final static int CONNECTION_FAILURE_RESOLUTION_REQUEST = 9000;

private LocationCallback mLocationCallback;
private Context mContext;
private GoogleApiClient mGoogleApiClient;
private LocationRequest mLocationRequest;

public LocationProvider(Context context, LocationCallback callback) {

    mGoogleApiClient = new GoogleApiClient.Builder(context)
            .addConnectionCallbacks(this)
            .addOnConnectionFailedListener(this)
            .addApi(LocationServices.API)
            .build();

    mLocationCallback = callback;

    // Create the LocationRequest object
    // Used to request a quality of service for location updates
    mLocationRequest = LocationRequest.create()
            .setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY)
            .setInterval(10 * 1000)        // 10 seconds, in milliseconds
            .setFastestInterval(1 * 1000); // 1 second, in milliseconds

    mContext = context;
}

public void connect() {
    mGoogleApiClient.connect();
}

public void disconnect() {
    if (mGoogleApiClient.isConnected()) {
        LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, this);
        mGoogleApiClient.disconnect();
    }
}

// Callback when response is made
@Override
public void onConnected(Bundle bundle) {
    Log.i(TAG, "Location services connected.");

    Location location = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
    // Check to see if there was a previous location. null means first time Google Play
    // services is checking the location, might also be because of other reasons
    if (location == null) {
        LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);
    }
    else {
        mLocationCallback.handleNewLocation(location);
    }
}

@Override
public void onConnectionSuspended(int i) {

}

@Override
public void onConnectionFailed(ConnectionResult connectionResult) {
    /* Google Play services can resolve some errors it detects.
     *  If the error has a resolution, try sending an Intent to
     * start a Google Play services activity that can resolve
     * error.
     */
    if (connectionResult.hasResolution() && mContext instanceof Activity) {
        try {
            Activity activity = (Activity)mContext;
            // Start an Activity that tries to resolve the error
            connectionResult.startResolutionForResult(activity, CONNECTION_FAILURE_RESOLUTION_REQUEST);
        /*
         * Thrown if Google Play services canceled the original
         * PendingIntent
         */
        } catch (IntentSender.SendIntentException e) {
            // Log the error
            e.printStackTrace();
        }
    } else {

         // If no resolution is available, display a dialog to the
         // user with the error.
        Log.i(TAG, "Location services connection failed with code " + connectionResult.getErrorCode());
    }
}

@Override
public void onLocationChanged(Location location) {
    mLocationCallback.handleNewLocation(location);
}

}

Above is the code for the LocationProvider that gets my current location. The Forecast/Day/Hour classes are all the same as shown in the tutorial.

2 Answers

Christopher Ahn
Christopher Ahn
3,105 Points

Nvm! Please ignore all of that. I just misplaced a lot of things where they shouldn't have been.

Christopher Ahn
Christopher Ahn
3,105 Points

Oh my lord that came out so messy. Please forgive me =[