Search code examples
javaandroidillegalstateexception

Error bringing up hourly weather forecast datar: java.lang.IllegalStateException: Could not execute method for android:onClick


I have a runtime issue with my Android studio project. It is a weather app that's trying to bring up hourly forecast data from an API. The intent to bring up the main activity keeps bringing up an IllegalStateException. It looks like there's no error with the code itself

This is the main activity file.

package com.teamtreehouse.stormy.ui;

import android.content.Context;
import android.content.Intent;
import android.databinding.DataBindingUtil;
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.text.method.LinkMovementMethod;
import android.util.Log;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;

import com.teamtreehouse.stormy.R;
import com.teamtreehouse.stormy.Weather.Current;
import com.teamtreehouse.stormy.Weather.Forecast;
import com.teamtreehouse.stormy.Weather.Hour;
import com.teamtreehouse.stormy.databinding.ActivityMainBinding;

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

import java.io.IOException;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;

public class MainActivity extends AppCompatActivity {

  public static final String TAG = MainActivity.class.getSimpleName();
  private Forecast forecast;
  private ImageView iconImageView;

  double latitude = 37.8267;
  double longitude = -122.4233;

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    getForecast(latitude, longitude);
    Log.d(TAG, "Main UI code is running, hooray!");
  }

  private void getForecast(double latitude, double longitude) {
    final ActivityMainBinding binding = DataBindingUtil
        .setContentView(MainActivity.this, R.layout.activity_main);

    iconImageView = findViewById(R.id.iconImageView);

    // Setup Dark Sky Link
    TextView darkSky = findViewById(R.id.darkSkyAttribution);
    darkSky.setMovementMethod(LinkMovementMethod.getInstance());

    String apiKey = "57eaf3aa961968bf65b0619680588073";


    String forecastURL = "https://api.darksky.net/forecast/" + apiKey +
        "/" + latitude + "," + longitude;

    if (isNetworkAvailable()) {
      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(Call call, IOException e) {

        }

        @Override
        public void onResponse(Call call, Response response) throws IOException {
          try {
            String jsonData = response.body().string();
            Log.v(TAG, jsonData);
            if (response.isSuccessful()) {

                forecast = parseForecastData(jsonData);

                Current current = forecast.getCurrent();

                final Current displayWeather = new Current(
                  current.getLocationLabel(),
                  current.getIcon(),
                  current.getTime(),
                  current.getTemperature(),
                  current.getHumidity(),
                  current.getPrecipChance(),
                  current.getSummary(),
                  current.getTimeZone()
              );

              binding.setWeather(displayWeather);

              runOnUiThread(new Runnable() {
                @Override
                public void run() {
                  Drawable drawable = getResources().getDrawable(displayWeather.getIconId());
                  iconImageView.setImageDrawable(drawable);
                }
              });

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

        }
      });
    }
    else {
      Toast.makeText(this, R.string.network_unavailable_message,
          Toast.LENGTH_LONG).show();
    }
  }

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

    forecast.setCurrent(getCurrentDetails(jsonData));

    return forecast;
  }

  private Hour[] getHourlyForecast(String jsonData) throws JSONException {
        JSONObject forecast = new JSONObject(jsonData);
        String timezone = forecast.getString("timezone");

       //get an array of JSON objects
        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.setIcon(jsonHour.getString("icon"));
            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();

    // Parse weather data from currently object
    current.setHumidity(currently.getDouble("humidity"));
    current.setTime(currently.getLong("time"));
    current.setIcon(currently.getString("icon"));
    current.setLocationLabel("Alcatraz Island, CA");
    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");
  }

  public void refreshOnClick(View view) {
    getForecast(latitude, longitude);
    Toast.makeText(this, "Refreshing data", Toast.LENGTH_LONG).show();
  }

  public void hourlyOnClick(View view) {

      List<Hour> hours = Arrays.asList(forecast.getHourlyForecast());
      Intent intent = new Intent(this, HourlyForecastActivity.class);

      intent.putExtra("HourlyList", (Serializable) hours);
      startActivity(intent);
  }

}

This is my stack trace

07-19 09:53:53.662 12590-12590/uk.co.jonniegrieve.stormy E/AndroidRuntime: FATAL EXCEPTION: main
    Process: uk.co.jonniegrieve.stormy, PID: 12590
    java.lang.IllegalStateException: Could not execute method for android:onClick
        at android.support.v7.app.AppCompatViewInflater$DeclaredOnClickListener.onClick(AppCompatViewInflater.java:389)
        at android.view.View.performClick(View.java:5198)
        at android.view.View$PerformClick.run(View.java:21147)
        at android.os.Handler.handleCallback(Handler.java:739)
        at android.os.Handler.dispatchMessage(Handler.java:95)
        at android.os.Looper.loop(Looper.java:148)
        at android.app.ActivityThread.main(ActivityThread.java:5417)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
     Caused by: java.lang.reflect.InvocationTargetException
        at java.lang.reflect.Method.invoke(Native Method)
        at android.support.v7.app.AppCompatViewInflater$DeclaredOnClickListener.onClick(AppCompatViewInflater.java:384)
        at android.view.View.performClick(View.java:5198) 
        at android.view.View$PerformClick.run(View.java:21147) 
        at android.os.Handler.handleCallback(Handler.java:739) 
        at android.os.Handler.dispatchMessage(Handler.java:95) 
        at android.os.Looper.loop(Looper.java:148) 
        at android.app.ActivityThread.main(ActivityThread.java:5417) 
        at java.lang.reflect.Method.invoke(Native Method) 
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726) 
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616) 
     Caused by: java.lang.NullPointerException: storage == null
        at java.util.Arrays$ArrayList.<init>(Arrays.java:38)
        at java.util.Arrays.asList(Arrays.java:155)
        at com.teamtreehouse.stormy.ui.MainActivity.hourlyOnClick(MainActivity.java:222)
        at java.lang.reflect.Method.invoke(Native Method) 
        at android.support.v7.app.AppCompatViewInflater$DeclaredOnClickListener.onClick(AppCompatViewInflater.java:384) 
        at android.view.View.performClick(View.java:5198) 
        at android.view.View$PerformClick.run(View.java:21147) 
        at android.os.Handler.handleCallback(Handler.java:739) 
        at android.os.Handler.dispatchMessage(Handler.java:95) 
        at android.os.Looper.loop(Looper.java:148) 
        at android.app.ActivityThread.main(ActivityThread.java:5417) 
        at java.lang.reflect.Method.invoke(Native Method) 
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726) 
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616) 
07-19 09:53:53.682 1228-1228/? E/EGL_emulation: tid 1228: eglCreateSyncKHR(1881): error 0x3004 (EGL_BAD_ATTRIBUTE

)


Solution

  • It looks that your method forecast.getHourlyForecast() inside hourlyOnClick returns null instead of array.