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

Jaewoo Byun
4,961 Pointsweather app help URGENT!!
I think I followed the android course almost identically step by step, and I'm on <Hooking Up the Model to the View> stage right now, and when I try to run the code with the geny motion emulator, it stops after 2 seconds and says "Unfortunately stormy has stopped".
this is my logcat
09-21 21:10:06.098 10805-10805/com.example.jaewoobyun.stormy D/MainActivity﹕ Main UI code is running! 09-21 21:10:07.666 10805-10834/com.example.jaewoobyun.stormy V/MainActivity﹕ {"latitude":37.8267,"longitude":-122.423,"timezone":"America/Los_Angeles","offset":-7,"currently":{"time":1442884206,"summary":"Clear","icon":"clear-day","nearestStormDistance":2,"nearestStormBearing":241,"precipIntensity":0,"precipProbability":0,"temperature":72.44,"apparentTemperature":72.44,"dewPoint":55.03,"humidity":0.54,"windSpeed":10.18,"windBearing":269,"visibility":9.81,"cloudCover":0.24,"pressure":1006.93,"ozone":281.02},"minutely":{"summary":"Clear for the hour.","icon":"clear-day","data":[{"time":1442884200,"precipIntensity":0,"precipProbability":0},{"time":1442884260,"precipIntensity":0,"precipProbability":0},{"time":1442884320,"precipIntensity":0,"precipProbability":0},{"time":1442884380,"precipIntensity":0,"precipProbability":0},{"time":1442884440,"precipIntensity":0,"precipProbability":0},{"time":1442884500,"precipIntensity":0,"precipProbability":0},{"time":1442884560,"precipIntensity":0,"precipProbability":0},{"time":1442884620,"precipIntensity":0,"precipProbability":0},{"time":1442884680,"precipIntensity":0,"precipProbability":0},{"time":1442884740,"precipIntensity":0,"precipProbability":0},{"time":1442884800,"precipIntensity":0,"precipProbability":0},{"time":1442884860,"precipIntensity":0,"precipProbability":0},{"time":1442884920,"precipIntensity":0,"precipProbability":0},{"time":1442884980,"precipIntensity":0,"precipProbability":0},{"time":1442885040,"precipIntensity":0,"precipProbability":0},{"time":1442885100,"precipIntensity":0,"precipProbability":0},{"time":1442885160,"precipIntensity":0,"precipProbability":0},{"time":1442885220,"precipIntensity":0,"precipProbability":0},{"time":1442885280,"precipIntensity":0,"precipProbability":0},{"time":1442885340,"precipIntensity":0,"precipProbability":0},{"time":1442885400,"precipIntensity":0,"precipProbability":0},{"time":1442885460,"precipIntensity":0,"precipProbability":0},{"time":1442885520,"precipIntensity":0,"precipProbability":0},{"time":1442885580,"precipIntensity":0,"precipProbability":0},{"time":1442885640,"precipIntensity":0,"precipProbability":0},{"time":1442885700,"precipIntensity":0,"precipProbability":0},{"time":1442885760,"precipIntensity":0,"precipProbability":0},{"time":1442885820,"precipIntensity":0,"precipProbability":0},{"time":1442885880,"precipIntensity":0,"precipProbability":0},{"time":1442885940,"precipIntensity":0,"precipProbability":0},{"time":1442886000,"precipIntensity":0,"precipProbability":0},{"time":1442886060,"precipIntensity":0,"precipProbability":0},{"time":1442886120,"precipIntensity":0,"precipProbability":0},{"time":1442886180,"precipIntensity":0,"precipProbability":0},{"time":1442886240,"precipIntensity":0,"precipProbability":0},{"time":1442886300,"precipIntensity":0,"precipProbability":0},{"time":1442886360,"precipIntensity":0,"precipProbability":0},{"time":1442886420,"precipIntensity":0,"precipProbability":0},{"time":1442886480,"precipIntensity":0,"precipProbability":0},{"time":1442886540,"precipIntensity":0,"precipProbability":0},{"time":1442886600,"precipIntensity":0,"precipProbability":0},{"time":1442886660,"precipIntensity":0,"precipProbability":0},{"time":1442886720,"precipIntensity":0,"precipProbability":0},{"time":1442886780,"precipIntensity":0,"precipProbability":0},{"time":1442886840,"precipIntensity":0,"precipProbability":0},{"time":1442886900,"precipIntensity":0,"precipProbability":0},{"time":1442886960,"precipIntensity":0,"precipProbability":0},{"time":1442887020,"precipIntensity":0,"precipProbability":0},{"time":1442887080,"precipIntensity":0,"precipProbability":0},{"time":1442887140,"precipIntensity":0,"precipProbability":0},{"time":1442887200,"precipIntensity":0,"precipProbability":0},{"time":1442887260,"precipIntensity":0,"precipProbability":0},{"time":1442887320,"precipIntensity":0,"precipProbability":0},{"time":1442887380,"precipIntensity":0,"precipProbability":0},{"time":1442887440,"precipIntensity":0,"precipProbability":0},{"time":1442887500,"precipIntensity":0,"precipProbability":0},{"time":1442887560,"precipIntensity":0,"precipProbability":0},{"time":1442887620,"p 09-21 21:10:07.738 10805-10834/com.example.jaewoobyun.stormy I/MainActivity﹕ From JSON: America/Los_Angeles 09-21 21:10:07.738 10805-10834/com.example.jaewoobyun.stormy D/MainActivity﹕ 6:10 PM 09-21 21:10:07.742 10805-10805/com.example.jaewoobyun.stormy E/AndroidRuntime﹕ FATAL EXCEPTION: main Process: com.example.jaewoobyun.stormy, PID: 10805 java.lang.NullPointerException: id == null at java.util.TimeZone.getTimeZone(TimeZone.java:328) at com.example.jaewoobyun.stormy.weather.Current.getFormattedTime(Current.java:81) at com.example.jaewoobyun.stormy.ui.MainActivity.updateDisplay(MainActivity.java:147) at com.example.jaewoobyun.stormy.ui.MainActivity.access$500(MainActivity.java:32) at com.example.jaewoobyun.stormy.ui.MainActivity$2$3.run(MainActivity.java:115) at android.os.Handler.handleCallback(Handler.java:733) at android.os.Handler.dispatchMessage(Handler.java:95) at android.os.Looper.loop(Looper.java:136) at android.app.ActivityThread.main(ActivityThread.java:5001) at java.lang.reflect.Method.invokeNative(Native Method) at java.lang.reflect.Method.invoke(Method.java:515) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:785) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:601) at dalvik.system.NativeStart.main(Native Method)

Jaewoo Byun
4,961 Pointspackage com.example.jaewoobyun.stormy.weather;
import com.example.jaewoobyun.stormy.R;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.TimeZone;
/**
* Created by JaewooByun on 15. 9. 19..
*/
public class Current {
private String mIcon;
private long mTime;
private double mTemperature;
private double mHumidity;
private double mPrecipChance;
private String mSummary;
private String mTimezone;
public String getTimezone() {
return mTimezone;
}
public void setTimezone(String timezone) {
mTimezone = timezone;
}
public String getIcon() {
return mIcon;
}
public void setIcon(String icon) {
mIcon = icon;
}
public int getIconId() {
//clear-day, clear-night, rain, snow, sleet, wind, fog, cloudy, partly-cloudy-day, or partly-cloudy-night
int iconId = R.drawable.clear_day;
if (mIcon.equals("clear-day")) {
iconId = R.drawable.clear_day;
}
else if (mIcon.equals("clear-night")) {
iconId = R.drawable.clear_night;
}
else if (mIcon.equals("rain")) {
iconId = R.drawable.rain;
}
else if (mIcon.equals("snow")) {
iconId = R.drawable.snow;
}
else if (mIcon.equals("sleet")) {
iconId = R.drawable.sleet;
}
else if (mIcon.equals("wind")) {
iconId = R.drawable.wind;
}
else if (mIcon.equals("fog")) {
iconId = R.drawable.fog;
}
else if (mIcon.equals("cloudy")) {
iconId = R.drawable.cloudy;
}
else if (mIcon.equals("partly-cloudy-day")) {
iconId = R.drawable.partly_cloudy;
}
else if (mIcon.equals("partly-cloudy-night")) {
iconId = R.drawable.cloudy_night;
}
return iconId;
}
public long getTime() {
return mTime;
}
public String getFormattedTime() {
SimpleDateFormat formatter = new SimpleDateFormat("h:mm a");
formatter.setTimeZone(TimeZone.getTimeZone(getTimezone()));
Date dateTime = new Date(getTime() * 1000);
String timeString = formatter.format(dateTime);
return timeString;
}
public void setTime(long time) {
mTime = time;
}
public int getTemperature() {
return (int)Math.round(mTemperature);
}
public void setTemperature(double temperature) {
mTemperature = temperature;
}
public double getHumidity() {
return mHumidity;
}
public void setHumidity(double humidity) {
mHumidity = humidity;
}
public int getPrecipChance() {
double precipPercentage = mPrecipChance * 100;
return (int) Math.round(precipPercentage);
}
public void setPrecipChance(double precipChance) {
mPrecipChance = precipChance;
}
public String getSummary() {
return mSummary;
}
public void setSummary(String summary) {
mSummary = summary;
}
}

Jaewoo Byun
4,961 PointsHow did you know right away that there is a problem at line 79? could you teach me how to look at the logcat and figure out what went wrong?

Ben Deitch
Treehouse TeacherHmm not sure where I got line 79 as it looks like line 81 now. Anywho, at the bottom of your logcat Android logged an error:
... 10805/com.example.jaewoobyun.stormy E/AndroidRuntime﹕ FATAL EXCEPTION: main Process: com.example.jaewoobyun.stormy, PID: 10805 java.lang.NullPointerException: id == null at java.util.TimeZone.getTimeZone(TimeZone.java:328) at com.example.jaewoobyun.stormy.weather.Current.getFormattedTime(Current.java:81) at com.example.jaewoobyun.stormy.ui.MainActivity.updateDisplay(MainActivity.java:147) at ...
This tells us there was a NullPointerException in TimeZone.java on line 328 in the getTimeZone function. Since this class is from the java.util package we can be reasonably sure that's not where the error is. Moving up the call stack from there we get to Current.java line 81 inside the getFormattedTime function. Since this is a class we made it's a good place to start looking for the error. Line 81 inside Current.java is:
formatter.setTimeZone(TimeZone.getTimeZone(getTimezone()));
We know that calling TimeZone.getTimeZone gives us a NullPointerException. This means that getTimezone is probably returning null, and this can only happen if setTimezone was never called. I'm guessing in the getCurrentDetails method in MainActivity.java you're either missing a call to setTimeZone() or you're returning a new CurrentWeather object.
Does you're getCurrentDetails look like the one in the project files:
private CurrentWeather getCurrentDetails(String jsonData) throws JSONException {
JSONObject forecast = new JSONObject(jsonData);
String timezone = forecast.getString("timezone");
Log.i(TAG, "From JSON: " + timezone);
JSONObject currently = forecast.getJSONObject("currently");
CurrentWeather currentWeather = new CurrentWeather();
currentWeather.setHumidity(currently.getDouble("humidity"));
currentWeather.setTime(currently.getLong("time"));
currentWeather.setIcon(currently.getString("icon"));
currentWeather.setPrecipChance(currently.getDouble("precipProbability"));
currentWeather.setSummary(currently.getString("summary"));
currentWeather.setTemperature(currently.getDouble("temperature"));
currentWeather.setTimeZone(timezone);
Log.d(TAG, currentWeather.getFormattedTime());
return currentWeather;
}
4 Answers

Ben Deitch
Treehouse TeacherYou're never assigning a value to mCurrent. When you call mCurrent.getFormattedTime() (in updateDisplay) mCurrent is null which means its' Timezone is also null (i.e. getTimezone() returns null). And java's TimeZone.getTimeZone throws an error if we give it a null timezone.

Jaewoo Byun
4,961 Pointsthank you so much. I really really appreciate it :)

Jaewoo Byun
4,961 Pointsyes it looks exactly the same except CurrentWeather is current now.. it still isn't working..
formatter.setTimeZone(TimeZone.getTimeZone(getTimezone()));
is this line causing the problem?

Ben Deitch
Treehouse TeacherYep, but it's only causing the problem because it (getTimeZone) is getting bad input.
Could you post your MainActivity.java too?

Jaewoo Byun
4,961 Pointspackage com.example.jaewoobyun.stormy.ui;
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
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.example.jaewoobyun.stormy.R;
import com.example.jaewoobyun.stormy.weather.Current;
import com.example.jaewoobyun.stormy.weather.Day;
import com.example.jaewoobyun.stormy.weather.Forecast;
import com.example.jaewoobyun.stormy.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 MainActivity extends AppCompatActivity {
public static final String TAG = MainActivity.class.getSimpleName();
private Current mCurrent;
private Forecast mForecast;
@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;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ButterKnife.inject(this);
mProgressBar.setVisibility(View.INVISIBLE);
final double latitude = 37.8267;
final double longitude = -122.423;
mRefreshImageView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
getForecast(latitude, longitude);
}
});
getForecast(latitude, longitude);
Log.d(TAG, "Main UI code is running!");
}
private void getForecast(double latitude, double longitude) {
String apiKey = "71a21e692c60ce454016f7f77df6411a";
String forecastUrl = "https://api.forecast.io/forecast/" + apiKey + "/" + latitude + "," + longitude + "";
if (isNetworkAvailable()) {
toggleRefresh();
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url(forecastUrl)
.build();
Call call = client.newCall(request);
call.enqueue(new Callback() {
@Override
public void onFailure(Request request, IOException e) {
runOnUiThread(new Runnable() {
@Override
public void run() {
toggleRefresh();
}
});
alertUserAboutError();
}
@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 = parseForecastDetails(jsonData);
runOnUiThread(new Runnable() {
@Override
public void run() {
updateDisplay();
}
});
} else {
alertUserAboutError();
}
} catch (IOException e) {
Log.e(TAG, "Exception caught: ", e);
} catch (JSONException e) {
Log.e(TAG, "Exception caught: ", e);
}
}
});
} else {
Toast.makeText(this, R.string.network_unavailable_message, Toast.LENGTH_LONG).show();
}
}
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);
}
}
private void updateDisplay() {
Current current = mForecast.getCurrent();
mTemperatureLabel.setText(mCurrent.getTemperature() + "");
mTimeLabel.setText("At " + mCurrent.getFormattedTime() + " it will be");
mHumidityValue.setText(mCurrent.getHumidity() + "");
mPrecipValue.setText(mCurrent.getPrecipChance() + "%");
mSummaryLabel.setText(mCurrent.getSummary());
Drawable drawable = getResources().getDrawable(mCurrent.getIconId());
mIconImageView.setImageDrawable(drawable);
}
private Forecast parseForecastDetails(String jsonData) throws JSONException {
Forecast forecast = new Forecast();
forecast.setCurrent(getCurrentDetails(jsonData));
forecast.setHourlyForecast(getHourlyForecat(jsonData));
forecast.setDailyForecast(getDailyForecast(jsonData));
return forecast;
}
private Day[] getDailyForecast(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.setSummary(jsonDay.getString("summary"));
day.setIcon(jsonDay.getString("icon"));
day.setTemperatureMax(jsonDay.getDouble("temperatureMax"));
day.setTime(jsonDay.getLong("time"));
day.setTimezone(timezone);
days[i] = day;
}
return days;
}
private Hour[] getHourlyForecat(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.setSummary(jsonHour.getString("summary"));
hour.setTemperature(jsonHour.getDouble("temperature"));
hour.setTime(jsonHour.getLong("time"));
hour.setTimezone(timezone);
hours[i] = hour;
}
return hours;
}
private Current getCurrentDetails(String jsonData) throws JSONException{
JSONObject forecast = new JSONObject(jsonData);
String timezone = forecast.getString("timezone");
Log.i(TAG, "From JSON: " + timezone);
JSONObject currently = forecast.getJSONObject("currently");
Current current = new Current();
current.setHumidity(currently.getDouble("humidity"));
current.setTime(currently.getLong("time"));
current.setIcon(currently.getString("icon"));
current.setPrecipChance(currently.getDouble("precipProbability"));
current.setSummary(currently.getString("summary"));
current.setTemperature(currently.getDouble("temperature"));
current.setTimezone(timezone);
Log.d(TAG, current.getFormattedTime());
return current;
}
private boolean isNetworkAvailable() {
ConnectivityManager manager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo networkInfo = manager.getActiveNetworkInfo();
boolean isAvailable = false;
if (networkInfo != null && networkInfo.isConnected()) {
isAvailable = true;
}
return isAvailable;
}
private void alertUserAboutError() {
AlertDialogFragment dialog = new AlertDialogFragment();
dialog.show(getFragmentManager(), "error_dialog");
}
}
Ben Deitch
Treehouse TeacherBen Deitch
Treehouse TeacherLooks like a Null Pointer Exception at line 79 of CurrentWeather.java. Could you post your CurrentWeather.java to help us figure out what's going on?