I’m new to android app development and am following a weather app made in a textbook, and the app opens in the emulator, but when I input a city to display the weather the app closes and gives me the following error:
" java.lang.NullPointerException: Attempt to invoke virtual method ‘org.json.JSONArray org.json.JSONObject.getJSONArray(java.lang.String)’ on a null object reference"
public class MainActivity extends AppCompatActivity {
private final List<Weather> weatherList = new ArrayList<>();
private WeatherArrayAdapter weatherArrayAdapter;
private ListView weatherListView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
findViewById(R.id.toolbar);
setSupportActionBar();
weatherListView = findViewById(R.id.weatherListView);
weatherArrayAdapter = new WeatherArrayAdapter(this,weatherList);
weatherListView.setAdapter(weatherArrayAdapter);
FloatingActionButton fab =
findViewById(R.id.fab);
fab.setOnClickListener((view) -> {
EditText locationEditText =
findViewById(R.id.locationEditText);
URL url = createURL(locationEditText.getText().toString());
if (url != null) {
dismissKeyboard(locationEditText);
GetWeatherTask getLocalWeatherTask = new GetWeatherTask();
getLocalWeatherTask.execute(url);
}
else {
Snackbar.make(findViewById(R.id.coordinatorLayout),
"Invalid URL", Snackbar.LENGTH_LONG).show();
}
});
}
private void setSupportActionBar() {
}
private void dismissKeyboard(View view) {
InputMethodManager imm = (InputMethodManager) getSystemService(
Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(view.getWindowToken(),0);
}
private URL createURL(String city) {
String apiKey = "()";
String baseURL = "http://api.openweathermap.org/data/2.5/forecast/daily?q=";
try {
String urlString = baseURL + URLEncoder.encode(city,"UTF-8") +
"()" + apiKey;
return new URL(urlString);
}
catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
*
*/
@SuppressWarnings("deprecation")
@SuppressLint("StaticFieldLeak")
private class GetWeatherTask
extends AsyncTask<URL, Void, JSONObject> {
@Override
protected JSONObject doInBackground(URL... params) {
HttpURLConnection connection = null;
try {
connection = (HttpURLConnection) params[0].openConnection();
int response = connection.getResponseCode();
if (response == HttpURLConnection.HTTP_OK) {
StringBuilder builder = new StringBuilder();
try (BufferedReader reader = new BufferedReader(
new InputStreamReader(connection.getInputStream()))) {
String line;
while ((line = reader.readLine()) != null) {
builder.append(line);
}
}
catch (IOException e) {
Snackbar.make(findViewById(R.id.coordinatorLayout),
"Unable to read weather data", Snackbar.LENGTH_LONG).show();
e.printStackTrace();
}
return new JSONObject(builder.toString());
}
else {
Snackbar.make(findViewById(R.id.coordinatorLayout),
"Unable to connect to OpenWeatherMap.org", Snackbar.LENGTH_LONG).show();
}
}
catch (Exception e) {
Snackbar.make(findViewById(R.id.coordinatorLayout),
"Unable to connect to OpenWeather.org", Snackbar.LENGTH_LONG).show();
e.printStackTrace();
}
finally {
assert connection != null;
connection.disconnect();
}
return null;
}
@Override
protected void onPostExecute(JSONObject weather) {
convertJSONtoArrayList(weather);
weatherArrayAdapter.notifyDataSetChanged();
weatherListView.smoothScrollToPosition(0);
}
}
private void convertJSONtoArrayList(JSONObject forecast) {
weatherList.clear();
try {
JSONArray list = forecast.getJSONArray("list");
for (int i = 0; i < list.length(); ++i) {
JSONObject day = list.getJSONObject(i);
JSONObject temperatures = day.getJSONObject("temp");
JSONObject weather =
day.getJSONArray("weather").getJSONObject(0);
weatherList.add(new Weather(
day.getLong("dt"),
temperatures.getDouble("min"),
temperatures.getDouble("max"),
day.getDouble("humidity"),
weather.getString("description"),
weather.getString("icon")));
}
}
catch (JSONException e) {
e.printStackTrace();
}
}
}
I tried some of the recommended fixes that appear as the yellow lines in the editor but it still doesn’t work. Any help is appreciated.
2
Answers
You are calling getJSONArray(java.lang.String) on a null object. It means that one of these two objects is null:
Can you double check them?
inside your convertJSONtoArrayList(JSONObject forecast) method, add a null check like this
this will immediately return null and prevent app from crashing.