1

i am trying to make an app in android by watching an example from Android app development weather app. Now i am having this fatal exception and i have no idea why it is coming because i am using JSON and api first time.
my error log is following:

01-27 03:01:40.622: E/AndroidRuntime(514): FATAL EXCEPTION: AsyncTask #1
01-27 03:01:40.622: E/AndroidRuntime(514): java.lang.RuntimeException: An error occured      while executing doInBackground()
01-27 03:01:40.622: E/AndroidRuntime(514):  at android.os.AsyncTask$3.done(AsyncTask.java:200)
01-27 03:01:40.622: E/AndroidRuntime(514):  at java.util.concurrent.FutureTask$Sync.innerSetException(FutureTask.java:274)
01-27 03:01:40.622: E/AndroidRuntime(514):  at java.util.concurrent.FutureTask.setException(FutureTask.java:125)
01-27 03:01:40.622: E/AndroidRuntime(514):  at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:308)
01-27 03:01:40.622: E/AndroidRuntime(514):  at java.util.concurrent.FutureTask.run(FutureTask.java:138)
01-27 03:01:40.622: E/AndroidRuntime(514):  at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1088)
01-27 03:01:40.622: E/AndroidRuntime(514):  at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:581)
01-27 03:01:40.622: E/AndroidRuntime(514):  at java.lang.Thread.run(Thread.java:1019)
01-27 03:01:40.622: E/AndroidRuntime(514): Caused by: java.lang.NullPointerException
01-27 03:01:40.622: E/AndroidRuntime(514):  at org.json.JSONTokener.nextCleanInternal(JSONTokener.java:112)
01-27 03:01:40.622: E/AndroidRuntime(514):  at org.json.JSONTokener.nextValue(JSONTokener.java:90)
01-27 03:01:40.622: E/AndroidRuntime(514):  at org.json.JSONObject.<init>(JSONObject.java:154)
01-27 03:01:40.622: E/AndroidRuntime(514):  at org.json.JSONObject.<init>(JSONObject.java:171)
01-27 03:01:40.622: E/AndroidRuntime(514):  at com.example.secondtime.JSONWeatherParser.getWeather(JSONWeatherParser.java:24)
01-27 03:01:40.622: E/AndroidRuntime(514):  at com.example.secondtime.MainActivity$JSONWeatherTask.doInBackground(MainActivity.java:96)
01-27 03:01:40.622: E/AndroidRuntime(514):  at com.example.secondtime.MainActivity$JSONWeatherTask.doInBackground(MainActivity.java:1)
01-27 03:01:40.622: E/AndroidRuntime(514):  at android.os.AsyncTask$2.call(AsyncTask.java:185)
01-27 03:01:40.622: E/AndroidRuntime(514):  at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:306)
01-27 03:01:40.622: E/AndroidRuntime(514):  ... 4 more


This is my Main activity class:

package com.example.secondtime;

import com.survivingwithandroid.weatherapp.R;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;

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

import com.example.secondtime.DailyForecastPageAdapter;
import com.example.secondtime.Location;
import com.example.secondtime.Weather;
import com.example.secondtime.WeatherForecast;

import android.os.AsyncTask;
import android.os.Bundle;
import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.support.v4.app.FragmentActivity;
import android.support.v4.view.ViewPager;
import android.view.Menu;
import android.widget.ImageView;
import android.widget.TextView;

public class MainActivity extends FragmentActivity {


        private TextView cityText;
        private TextView condDescr;
        private TextView temp;
        private TextView press;
        private TextView windSpeed;
        private TextView windDeg;
        private TextView unitTemp;

        private TextView hum;
        private ImageView imgView;

        private static String forecastDaysNum = "3";
        private ViewPager pager;

        @Override
        protected void onCreate(Bundle savedInstanceState) {
                super.onCreate(savedInstanceState);
                setContentView(R.layout.activity_main);
                String city = "London, UK";
                String lang = "en";

                cityText = (TextView) findViewById(R.id.cityText);
                temp = (TextView) findViewById(R.id.temp);
                unitTemp = (TextView) findViewById(R.id.unittemp);
                unitTemp.setText("°C");
                condDescr = (TextView) findViewById(R.id.skydesc);

                pager = (ViewPager) findViewById(R.id.pager);
                imgView = (ImageView) findViewById(R.id.condIcon);




                JSONWeatherTask task = new JSONWeatherTask();
                task.execute(new String[]{city,lang});

                JSONForecastWeatherTask task1 = new JSONForecastWeatherTask();
                task1.execute(new String[]{city,lang, forecastDaysNum});
        }

        @Override
        public boolean onCreateOptionsMenu(Menu menu) {
                // Inflate the menu; this adds items to the action bar if it is present.
                getMenuInflater().inflate(R.menu.main, menu);
                return true;
        }


        private class JSONWeatherTask extends AsyncTask<String, Void, Weather> {

                @Override
                protected Weather doInBackground(String... params) {
                        Weather weather = new Weather();
                        String data = ( (new WeatherHttpClient()).getWeatherData(params[0], params[1]));

                        try {
                                weather = JSONWeatherParser.getWeather(data);
                                System.out.println("Weather ["+weather+"]");

                                weather.iconData = ( (new WeatherHttpClient()).getImage(weather.currentCondition.getIcon()));

                        } catch (JSONException e) {                                
                                e.printStackTrace();
                        }
                        return weather;

        }


        @Override
        protected void onPostExecute(Weather weather) {                        
                        super.onPostExecute(weather);

                        if (weather.iconData != null && weather.iconData.length > 0) {
                                Bitmap img = BitmapFactory.decodeByteArray(weather.iconData, 0, weather.iconData.length); 
                                imgView.setImageBitmap(img);
                        }


                        cityText.setText(weather.location.getCity() + "," + weather.location.getCountry());
                        temp.setText("" + Math.round((weather.temperature.getTemp() - 275.15)));
                        condDescr.setText(weather.currentCondition.getCondition() + "(" + weather.currentCondition.getDescr() + ")");


                }



  }


        private class JSONForecastWeatherTask extends AsyncTask<String, Void, WeatherForecast> {

                @Override
                protected WeatherForecast doInBackground(String... params) {

                        String data = ( (new WeatherHttpClient()).getForecastWeatherData(params[0], params[1], params[2]));
                        WeatherForecast forecast = new WeatherForecast();
                        try {
                                forecast = JSONWeatherParser.getForecastWeather(data);
                                System.out.println("Weather ["+forecast+"]");


                        } catch (JSONException e) {                                
                                e.printStackTrace();
                        }
                        return forecast;

        }




        @Override
                protected void onPostExecute(WeatherForecast forecastWeather) {                        
                        super.onPostExecute(forecastWeather);

                        DailyForecastPageAdapter adapter = new DailyForecastPageAdapter(Integer.parseInt(forecastDaysNum), getSupportFragmentManager(), forecastWeather);

                        pager.setAdapter(adapter);
                }



  }
}


One more this this is my main activity xml file:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context=".MainActivity"
    android:orientation="vertical" >

    <RelativeLayout
        android:layout_width="290dp"
        android:layout_height="wrap_content"
        android:paddingBottom="@dimen/activity_vertical_margin"
        android:paddingLeft="@dimen/activity_horizontal_margin"
        android:paddingRight="@dimen/activity_horizontal_margin"
        android:paddingTop="@dimen/activity_vertical_margin"
        tools:context=".MainActivity" >

    <TextView
        android:id="@+id/cityText"
        style="?android:attr/textAppearanceMedium"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true">        
    </TextView>

    <TextView
        android:id="@+id/temp"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@id/cityText"
        android:layout_centerHorizontal="true">        
    </TextView>
    <TextView
        android:id="@+id/unittemp"        
        android:layout_width="wrap_content"
        style="?android:attr/textAppearanceMedium"
        android:layout_height="wrap_content"
        android:layout_below="@id/cityText"
        android:layout_toRightOf="@id/temp"
        android:layout_alignBaseline="@id/temp">        
    </TextView>
    <TextView
        android:id="@+id/skydesc"        
        android:layout_width="wrap_content"
        style="?android:attr/textAppearanceMedium"
        android:layout_height="wrap_content"
        android:layout_below="@id/temp"        
        android:layout_alignStart="@id/temp"
        android:layout_toRightOf="@id/temp">
    </TextView>

    <!--  Image weather condition -->
    <ImageView android:id="@+id/condIcon"
                android:layout_height="wrap_content"
                android:layout_width="wrap_content"
                android:layout_alignTop="@id/temp"
                android:layout_toRightOf="@id/temp"/>

</RelativeLayout>

<android.support.v4.view.ViewPager

    android:id="@+id/pager"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_weight="6" >

    <android.support.v4.view.PagerTitleStrip
        android:id="@+id/pager_title_strip"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="top"
        android:background="#E6E6E6"
        android:paddingBottom="4dp"
        android:paddingTop="4dp"
        android:textColor="#fff" />

        </android.support.v4.view.ViewPager> 
</LinearLayout>


Any Help on this will be great. Thanks in advance and sorry for my bad English and grammer.

jazz b
  • 437
  • 1
  • 6
  • 15

1 Answers1

4

You should check the returned data for not being null..Try to add there a breakpoint and you will see..

if(data != null){
  //do the parsing stuff
}else{
  //something wrong happened during the download..

}

According to the stacktrace, you have a NullPointerException here :

JSONWeatherParser.getWeather(data)

When you look at the code of the method

public String getWeatherData(String location, String lang) {
            HttpURLConnection con = null ;
            InputStream is = null;

            try {
                    String url = BASE_URL + location;
                    if (lang != null)
                            url = url + "&lang=" + lang;

                    con = (HttpURLConnection) ( new URL(url)).openConnection();
                    con.setRequestMethod("GET");
                    con.setDoInput(true);
                    con.setDoOutput(true);
                    con.connect();

                    // Let's read the response
                    StringBuffer buffer = new StringBuffer();
                    is = con.getInputStream();
                    BufferedReader br = new BufferedReader(new InputStreamReader(is));
                    String line = null;
                    while (  (line = br.readLine()) != null )
                            buffer.append(line + "\r\n");

                    is.close();
                    con.disconnect();

                    return buffer.toString();
        }
            catch(Throwable t) {
                    t.printStackTrace();
            }
            finally {
                    try { is.close(); } catch(Throwable t) {}
                    try { con.disconnect(); } catch(Throwable t) {}
            }

            return null;

    }

you can see that at the last line it returns null. This happens when there is an error during the download..So you definitely need to check for the nullpointer there to make your code fail save.

simekadam
  • 7,334
  • 11
  • 56
  • 79
  • Well it's the issue. Data is null.Probably better to turn it to a comment instead..? – simekadam Jan 26 '14 at 22:24
  • 2
    Well, you are absolutely correct but I believe we can help the OP further ;-) I added an edit, hopefully, it'll make things a bit clearer on how to actually make this code work. – 2Dee Jan 26 '14 at 22:28
  • if i comment data what should i passed to get weather – jazz b Jan 26 '14 at 22:40
  • 2
    @jazzb when data is null, the download failed and therefore you shouldn't call the method getWeather() at all..instead you should try the download again, or just show an error message to the user.. – simekadam Jan 26 '14 at 22:43
  • Good explanation of the root of the issue, voted up ! – 2Dee Jan 26 '14 at 22:50
  • Sir as you can see `con = (HttpURLConnection) ( new URL(url)).openConnection();` this line i use break point and get to know that that con have null so it did nothing and just jump to the `Catch` bracket and after that goes to `finally` i want to know how it is null and how can i fix it and thank you for your help – jazz b Jan 26 '14 at 22:58
  • By the way, you should also check for availability of internet connection before trying any network access at all (and display an error message if not available). Have a look at this question for details : http://stackoverflow.com/questions/7404917/how-to-check-the-network-availability – 2Dee Jan 26 '14 at 23:00
  • internet is working on the emulator i check it by using same url in the browser – jazz b Jan 26 '14 at 23:01
  • But you cannot assume your users will always be connected to the internet with their device when using your app, so it is better to check ;) – 2Dee Jan 26 '14 at 23:07