0

The project itself does not report any error, but when I run my project with the emulator, it popped up "Unfortunately project has stopped", can anyone look at my project and know what error is? I got following logcat error:

Process: edu.drexel.weatherundergroundapi, PID: 1800
java.lang.RuntimeException: Unable to start activity ComponentInfo{edu.drexel.weatherundergroundapi/edu.drexel.weatherundergroundapi.MainActivity}: java.lang.NullPointerException: storage == null
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2298)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2360)
at android.app.ActivityThread.access$800(ActivityThread.java:144)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1278)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5221)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:899)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:694)
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 android.widget.ArrayAdapter.<init>(ArrayAdapter.java:128)
at edu.drexel.weatherundergroundapi.CustomListAdapter.<init>(CustomListAdapter.java:35)
at edu.drexel.weatherundergroundapi.MainActivity.onCreate(MainActivity.java:25)
at android.app.Activity.performCreate(Activity.java:5933)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1105)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2251)
            at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2360)
            at android.app.ActivityThread.access$800(ActivityThread.java:144)
            at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1278)
            at android.os.Handler.dispatchMessage(Handler.java:102)
            at android.os.Looper.loop(Looper.java:135)
            at android.app.ActivityThread.main(ActivityThread.java:5221)
            at java.lang.reflect.Method.invoke(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:372)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:899)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:694)

There are three java classes and three xml files: 1. MainActivity.java 2. CustomListAdapter.java 3. MyBgTask.java 4. listView.xml 5. activity_main.xml

public class MainActivity extends Activity {


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

        MyBgTask asyncTask = new MyBgTask();

        CustomListAdapter adapter = new CustomListAdapter(this, asyncTask.getTimeArray(), asyncTask.getConditionArray(),
                                    asyncTask.getTempArray(), asyncTask.getHumidityArray(), asyncTask.getUrls());

        ListView list = (ListView) findViewById(R.id.listView);
        list.setAdapter(adapter);

        asyncTask.execute();
    }

    /*public void onListItemClick(ListView lv, View view, int position, int imgid) {
        String Slecteditem= (String)getListAdapter().getItem(position);
        Toast.makeText(this, Slecteditem, Toast.LENGTH_SHORT).show();
    }*/


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

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

        //noinspection SimplifiableIfStatement
        if (id == R.id.action_settings) {
            return true;
        }

        return super.onOptionsItemSelected(item);
    }
}
  1. CustomListAdapter.java:

    public class CustomListAdapter extends ArrayAdapter<String> {
    private final Activity context;
    private final String[] time;
    private final String[] condition;
    private final String[] temp;
    private final String[] humidity;
    private final String[] url;
    
    public CustomListAdapter(Activity context, String[] time, String[] condition, String[] temp, String[] humidity, String[] url)
    {
        super(context, R.layout.listview, time);
        this.context = context;
        this.time = time;
        this.condition = condition;
        this.temp = temp;
        this.humidity = humidity;
        this.url = url;
    }
    
    private Bitmap getImageBitmap(String url) {
        Bitmap bm = null;
        try {
            URL aURL = new URL(url);
            URLConnection conn = aURL.openConnection();
            conn.connect();
            InputStream is = conn.getInputStream();
            BufferedInputStream bis = new BufferedInputStream(is);
            bm = BitmapFactory.decodeStream(bis);
            bis.close();
            is.close();
        } catch (IOException e) {
            Log.e("Error getting bitmap", e.toString());
        }
        return bm;
    }
    
    public View getView(int position, View view, ViewGroup parent) {
        LayoutInflater inflater = context.getLayoutInflater();
        View rowView = inflater.inflate(R.layout.listview, null, true);
    
        TextView timeView = (TextView) rowView.findViewById(R.id.dateTime);
        TextView conditionView = (TextView) rowView.findViewById(R.id.condition);
        TextView tempView = (TextView) rowView.findViewById(R.id.temp);
        TextView humidityView = (TextView) rowView.findViewById(R.id.humidity);
        ImageView imageView = (ImageView) rowView.findViewById(R.id.icon);
    
        timeView.setText(time[position]);
        conditionView.setText(condition[position]);
        tempView.setText(temp[position]);
        humidityView.setText(humidity[position]);
        imageView.setImageBitmap(getImageBitmap(url[position]));
    
        return rowView;  
    }  
    

    }

  2. MyBgTask.java

    public class MyBgTask extends AsyncTask<Void, Void, Void> {
    
    String[] timeArray;
    String[] conditionArray;
    String[] tempArray;
    String[] humidityArray;
    String[] urls;
    
    public String[] getTimeArray() {
        return timeArray;
    }
    
    public String[] getConditionArray() {
        return conditionArray;
    }
    
    public String[] getTempArray() {
        return tempArray;
    }
    
    public String[] getHumidityArray() {
        return humidityArray;
    }
    
    public String[] getUrls() {
        return urls;
    }
    
    @Override
    protected Void doInBackground(Void... params) {
        try {
            // Get User Current Location
            String geoURL = "http://api.wunderground.com/api/56419d324b9bf190/geolookup/q/autoip.json";
            URL url = new URL(geoURL);
            HttpURLConnection request = (HttpURLConnection) url.openConnection();
            request.connect();
            request.getContent();
    
            JsonParser geo_jp = new JsonParser();
            JsonElement geo_root = geo_jp.parse(new InputStreamReader((InputStream) request.getContent()));
            JsonObject geo_rootobj = geo_root.getAsJsonObject();
    
            String city = geo_rootobj.get("location").getAsJsonObject().get("city").getAsString();
            String state = geo_rootobj.get("location").getAsJsonObject().get("state").getAsString();
            String zip = geo_rootobj.get("location").getAsJsonObject().get("zip").getAsString();
    
            // Invoke hourly weather forcast with user's current location
            String forecastURL = "http://api.wunderground.com/api/56419d324b9bf190/conditions/hourly/forecast/q/" + zip + ".json";
            URL furl = new URL(forecastURL);
            HttpURLConnection forecastRequest = (HttpURLConnection) furl.openConnection();
            forecastRequest.connect();
            forecastRequest.getContent();
    
            JsonParser forecast_jp = new JsonParser();
            JsonElement forecast_root = forecast_jp.parse(new InputStreamReader((InputStream) request.getContent()));
            JsonArray forecast_array = forecast_root.getAsJsonObject().get("hourly_forcast").getAsJsonArray();
    
            for (int hour = 0; hour < forecast_array.size(); hour++) {
                String month = forecast_array.get(hour).getAsJsonObject().
                        get("FCTTIME").getAsJsonObject().
                        get("mon_abbrev").getAsString();
    
                String monthDay = forecast_array.get(hour).getAsJsonObject().
                        get("FCTTIME").getAsJsonObject().
                        get("mday_padded").getAsString();
    
                String time = forecast_array.get(hour).getAsJsonObject().
                        get("FCTTIME").getAsJsonObject().
                        get("civil").getAsString();
    
                String dateAndtime = month + " " + monthDay + " " + time;
    
                String condition = forecast_array.get(hour).getAsJsonObject().
                        get("condition").getAsString();
    
                String temp = forecast_array.get(hour).getAsJsonObject().
                        get("temp").getAsJsonObject().
                        get("english").getAsString();
    
                String humidity = forecast_array.get(hour).getAsJsonObject().
                        get("humidity").getAsString();
    
                String icon_url = forecast_array.get(hour).getAsJsonObject().
                        get("icon_url").getAsString();
    
                timeArray[hour] = dateAndtime;
                conditionArray[hour] = condition;
                tempArray[hour] = temp;
                humidityArray[hour] = humidity;
                urls[hour] = icon_url;
            }
    
    
        } catch (IOException e) {
            Log.e("ERROR", e.toString());
        }
    
        return null;
    }
    
    protected void onPostExecute(Void... params) {
    
    }
    }
    
  3. listView.xml

    <ImageView
        android:id="@+id/icon"
        android:layout_width="60dp"
        android:layout_height="60dp"
        android:padding="5dp" />
    
    <LinearLayout android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="vertical">
    
        <TextView
            android:id="@+id/dateTime"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textAppearance="?android:attr/textAppearanceMedium"
            android:layout_marginLeft="10dp"
            android:layout_marginTop="5dp"
            android:padding="2dp"
            android:textColor="#33CC33"
            android:text="@string/dateTime" />
        <TextView
            android:id="@+id/condition"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/condition"
            android:layout_marginLeft="10dp"/>
    
        <TextView
            android:id="@+id/temp"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/temp"
            android:layout_marginLeft="10dp" />
    
        <TextView
            android:id="@+id/humidity"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/humidity"
            android:layout_marginLeft="10dp" />
    </LinearLayout>
    

  4. activity_main.xml

    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
    android:layout_height="match_parent" android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:paddingBottom="@dimen/activity_vertical_margin" tools:context=".main">
    
    <ListView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/listView"
        android:clickable="false"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true" >
    
    
    </ListView>
    

Joe
  • 1
  • 2
  • This is way too much code and too little explanation. You need to explain what you are doing when the app starts and, most important, post the logcat so we can see what the error is and where it happens. But, with a quick glance, I'm almost positive it's with the way you are trying to use your `AsyncTask`. You should also see [this post](http://stackoverflow.com/questions/23353173/unfortunately-myapp-has-stopped-how-can-i-solve-this) and read the docs on using `AsyncTask`. – codeMagic Mar 02 '15 at 02:25
  • @codeMagic I am trying to invoke wunderground api, obtain the hourly forecasts and output them in a scrolling list view. – Joe Mar 02 '15 at 02:41

1 Answers1

0

Based on what I can see, the program crashes because time is null at this line:

public CustomListAdapter(Activity context, String[] time, String[] condition, String[] temp, String[] humidity, String[] url){
    super(context, R.layout.listview, time);
    ...
}

This is because, as @codeMagic said in the comments, you are using the AsyncTask class incorrectly. The following code in your onCreate method

MyBgTask asyncTask = new MyBgTask();

CustomListAdapter adapter = new CustomListAdapter(this, asyncTask.getTimeArray(), asyncTask.getConditionArray(),
                                asyncTask.getTempArray(), asyncTask.getHumidityArray(), asyncTask.getUrls());

Creates an AsyncTask, but doesn't execute() it. When you call getTimeArray(), it returns the value of timeArray, which is a default-initialised null value.

Broadly, you need to

  • Execute the AsyncTask
  • Update the ArrayListAdapter when the task is done
Xiao
  • 1,552
  • 2
  • 22
  • 20
  • can you tell me how to pass the updated array as getArray to the main activity? – Joe Mar 05 '15 at 01:25
  • What do mean by pass to the main `Activity`? If you mean you want to run your code as is with `getArray()` blocking until the `AsyncTask` has finished, that would be a bad idea as `onCreate` is run on the UI thread, and blocking would prevent any UI updates until the task has finished. Is that what you meant? – Xiao Mar 05 '15 at 02:07
  • hi, Xiao, I just changed all the arrays String[] to ArrayLists, and these ArrayLists are all updated in the doInBackground. And I call them in the main CustomListAdapter adapter = new CustomListAdapter(this, asyncTask.getTimeList(), asyncTask.getConditionList(), asyncTask.getTempList(), asyncTask.getHumidityList(), asyncTask.getBitmapList()); But the lists are all null, the getLists() return null lists, do you know how I can get the updated lists from the asyncTask to main? – Joe Mar 05 '15 at 04:58
  • Hi Joe, an `AsyncTask` won't automatically execute once created. You need to execute it, then use the results when it is done. More information on `AsyncTask`, including an example, is on the Android Developers website: https://developer.android.com/reference/android/os/AsyncTask.html – Xiao Mar 12 '15 at 01:10