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 Plugging in the Data

Stormy Timezone NullPointerException id = null ?

I am getting this area when trying to run my app and i'm not sure how to fix it:

03-01 21:31:14.186  25612-25612/watafuru.com.stormy E/AndroidRuntime﹕ FATAL EXCEPTION: main
    Process: watafuru.com.stormy, PID: 25612
    java.lang.NullPointerException: id == null
            at java.util.TimeZone.getTimeZone(TimeZone.java:328)
            at watafuru.com.stormy.CurrentWeather.getFormattedTime(CurrentWeather.java:83)
            at watafuru.com.stormy.MainActivity.updateDisplay(MainActivity.java:104)
            at watafuru.com.stormy.MainActivity.access$200(MainActivity.java:30)
            at watafuru.com.stormy.MainActivity$1$1.run(MainActivity.java:81)
            at android.os.Handler.handleCallback(Handler.java:733)
            at android.os.Handler.dispatchMessage(Handler.java:95)
            at android.os.Looper.loop(Looper.java:146)
            at android.app.ActivityThread.main(ActivityThread.java:5602)
            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:1283)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1099)
            at dalvik.system.NativeStart.main(Native Method)

Here is my code:

package watafuru.com.stormy;

import android.content.Context;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;

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.JSONException;
import org.json.JSONObject;

import java.io.IOException;

import butterknife.ButterKnife;
import butterknife.InjectView;


public class MainActivity extends ActionBarActivity {


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

    private CurrentWeather mCurrentWeather;

    @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.iconView) ImageView mIconImageView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        ButterKnife.inject(this);

        String apiKey = "7b9d2da8bda836a53c0d801645aeb6fb";
        double latitude = 37.8267;
        double longitude = -122.423;
        String forecastURL = "https://api.forecast.io/forecast/"
                + apiKey + "/" + latitude + "," + longitude;

        if(networkIsAvaliable()){
        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) {

            }

            @Override
            public void onResponse(Response response) throws IOException {
                try {

                    String jsonData = response.body().string();
                    Log.v(TAG, jsonData);
                    if (response.isSuccessful()) {
                        mCurrentWeather = getCurrentDetails(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,getString(R.string.No_Network),Toast.LENGTH_LONG).show();
        }
    }

    private void updateDisplay() {
        mTemperatureLabel.setText(mCurrentWeather.getTemperature() + "");
        mTimeLabel.setText("At " + mCurrentWeather.getFormattedTime() + " it will be");
        mHumidityValue.setText(mCurrentWeather.getHumidity() + "");
        mPrecipValue.setText(mCurrentWeather.getPercip() + "%");
        mSummaryLabel.setText(mCurrentWeather.getSummary());


    }


    private boolean networkIsAvaliable() {
        ConnectivityManager manager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo info = manager.getActiveNetworkInfo();
        boolean isAvaliable = false;
        if (info != null && info.isConnected()){
            isAvaliable = true;
        }
        return isAvaliable;
    }

    private CurrentWeather getCurrentDetails(String jsonData) throws JSONException {
        JSONObject forecast = new JSONObject(jsonData);
        String timezone = forecast.getString("timezone");
        Log.v(TAG,"From JSON: " + timezone);

        JSONObject currently = forecast.getJSONObject("currently");

        CurrentWeather currentWeather = new CurrentWeather();
        currentWeather.setHumidity(currently.getDouble("humidity"));
        currentWeather.setPercip(currently.getDouble("precipProbability"));
        currentWeather.setTime(currently.getLong("time"));
        currentWeather.setIcon(currently.getString("icon"));
        currentWeather.setSummary(currently.getString("summary"));
        currentWeather.setTemperature(currently.getDouble("temperature"));
        currentWeather.setTimezone(timezone);

        Log.d(TAG,currentWeather.getFormattedTime());


        return new CurrentWeather();


    }

    private void alertUserAboutError() {

        AlertDialogFragment dialog = new AlertDialogFragment();
        dialog.show(getFragmentManager(),"error_dialog");


    }

}
package watafuru.com.stormy;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.TimeZone;

/**
 * Created by Watafuru on 3/1/2015.
 */
public class CurrentWeather {

    private String mIcon;
    private long mTime;
    private double mTemperature;
    private double mHumidity;
    private double mPercip;
    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 long getTime() {
        return mTime;
    }

    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 getPercip() {
        double percipPercent = mPercip *100;

        return (int) Math.round(percipPercent);
    }

    public void setPercip(double percip) {
        mPercip = percip;
    }

    public String getSummary() {
        return mSummary;
    }

    public void setSummary(String summary) {
        mSummary = summary;
    }


    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 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;
    }
}

4 Answers

Andre' Jones
Andre' Jones
26,671 Points

Im trying to figure out your problem. But I've spotted another problem in your code. in your getCurrentDetails method you are returning a new CurrentWeather(); object. what you want to do is return currentWeather; the object that you've been constructing in the method not a new blank instance. This might solve your problem if so let me know.

That worked, thanks!

Wow thank you! This was the reason I was having this same exact issue thank you!

Maximilian Bertram
Maximilian Bertram
9,486 Points

Thank you so much andre' !! I finally got my App working with your tipp!

Sang Tran
Sang Tran
6,918 Points

Thank you Andre!

alex gwartney
alex gwartney
8,849 Points

I know this has been answered already but just in case some one like i have run across this i had the same problem make sure to return the right weather data it was confusing me till ran across this.

Daniel Muchiri
Daniel Muchiri
15,407 Points

Thanks you very much it worked for me too!!

DAVID MUK1
PLUS
DAVID MUK1
Courses Plus Student 771 Points

It took me hours to find what the REAL problem was !

The cause of the problem is a bug in the JDK - which results in a NullpointerException in the case where the argument is null in the call to SimpleDateFormat::setTimeZone(arg).

Here is how I got round the problem:

public class MainActivity extends AppCompatActivity { . . . public void hourlyOnClick(View view) { //Get Hour data from network List<Hour> hours = Arrays.asList(forecast.getHourlyForecast());

    String timeZoneForHour = forecast.getCurrent().getTimeZone();

    Log.d(LOG_TAG, ": hourlyOnClick() ------> timeZoneForHour=" + timeZoneForHour);

    //ASSIGN A TimeZone TO THE HOUR OBJECT. Recall that TimeZone it is at a higher level in the JSON than hour data
    ////////////////////////////////////////////////
    for(Hour hour: hours)
    {
        hour.setTimeZone(timeZoneForHour );
    }
    ////////////////////////////////////////////////

    Intent intent = new Intent(this, HourlyForecastActivity.class);

    intent.putExtra(HourlyForecastActivity.HOURLY_LIST_INTENT_EXTRA_KEY, (Serializable) hours);



    startActivity(intent);

}

}//END CLASS MainActivity

public class Hour implements Serializable {

 public String getTime()
{
    String retVal="";

                                                           //HOUR AM/PM
    SimpleDateFormat formatter= new SimpleDateFormat("h a");

    Log.d(LOG_TAG, ":  getTime() ------> timeZone=" + timeZone);
    //formatter.setTimeZone(TimeZone.getTimeZone(timeZone));

    //NOTE: THIS IS A WORK AROUND FOR A JDK8 BUG   !!!!!!!!!
    /*
       The documentation for "getTimeZone(String ID)" can be updated to state that it
       throws a NullPointerException if the id is null.

     */
    ///////////////////////////////////////////////////////////////////
    if(timeZone != null)
    {
        formatter.setTimeZone(TimeZone.getTimeZone(timeZone) );
    }
    else
    {
        formatter.setTimeZone(TimeZone.getTimeZone("America/Los_Angeles") );
    }
    ///////////////////////////////////////////////////////////////////



    //Convert seconds to milliseconds - and pass into Date constructor
    Date date= new Date(1000 * time);

    retVal=formatter.format(date);


    return retVal;
}
 .
 . 
 .

}//END CLASS Hour