0

I am making an app that gets some XML and parses it, making an ArrayList of objects to be passed to another activity. This is all done in an AsyncTask. When I run the app, it crashes immediately, and I'm having trouble figuring out where the problem lies. Any help is greatly appreciated.

Main Activity

import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.ProtocolException;
import java.net.URL;
import java.util.ArrayList;
import org.xmlpull.v1.XmlPullParserException;
import android.os.AsyncTask;
import android.os.Bundle;
import android.app.Activity;
import android.app.ProgressDialog;
import android.util.Log;
import android.view.Menu;
import android.widget.TextView;

public class MainActivity extends Activity {

ProgressDialog progressDialog;

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

    new QuizWorker().execute("http://liisp.uncc.edu/~mshehab/api/trivia.xml");

}

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




// START QuizWorker Class
public class QuizWorker extends AsyncTask<String, Void, ArrayList<Question>> {

    @Override
    protected ArrayList<Question> doInBackground(String... params) {

        String urlString = params[0];

        try {
            URL url = new URL(urlString);
            HttpURLConnection con = (HttpURLConnection) url.openConnection();
            con.setRequestMethod("GET");
            con.connect();
            int statusCode = con.getResponseCode();

            if(statusCode == HttpURLConnection.HTTP_OK) {

                InputStream in = con.getInputStream();
                return QuestionUtil.parseQuestions(in);

            }

        }

        catch (MalformedURLException e) {
            e.printStackTrace();
        }
        catch (ProtocolException e) {
            e.printStackTrace();
        }
        catch (IOException e) {
            e.printStackTrace();
        }
        catch (XmlPullParserException e) {
            e.printStackTrace();
        }

        return null;

    }

    @Override
    protected void onPostExecute(ArrayList<Question> result) {
        super.onPostExecute(result);
        progressDialog.dismiss();
        TextView tv = (TextView) findViewById(R.id.ready_status);
        tv.setText("Trivia Ready");

        // testing purposes
        Log.d("demo", result.toString());
    }

    @Override
    protected void onPreExecute() {
        super.onPreExecute();
        progressDialog = new ProgressDialog(MainActivity.this);
        progressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
        progressDialog.setCancelable(false);
        progressDialog.setMessage("Loading Trivia");
        progressDialog.show();
    }




} // END Class

} // END Activity

As you can see, I have the MainActivity here with the AsyncTask. The AsyncTask calls another class called QuestionUtil

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlPullParserFactory;

public class QuestionUtil {

static ArrayList<Question> parseQuestions(InputStream xmlIn) throws XmlPullParserException, IOException {

    XmlPullParser parser = XmlPullParserFactory.newInstance().newPullParser();
    parser.setInput(xmlIn, "UTF-8");

    Question question = null;
    ArrayList<Question> questionList = new ArrayList<Question>();
    Choices choices = null;
    ArrayList<Choices> choiceList = new ArrayList<Choices>();

    int event = parser.getEventType();

    while (event != XmlPullParser.END_DOCUMENT) {

        switch (event) {
        case XmlPullParser.START_TAG:

            if(parser.getName().equals("question")) {

                question = new Question();

                try {
                    question.setId(parser.getAttributeValue(null, "id"));
                }
                catch (NumberFormatException ex) { }

            }

            else if (parser.getName().equals("text")) {
                question.setText(parser.nextText());
            }

            else if (parser.getName().equals("image")) {
                question.setImage(parser.nextText());
            }

            else if (parser.getName().equals("choices")) {

                boolean isCorrect;
                String answer;
                parser.next();

                while (parser.getName().equals("choice")) {

                    if (parser.getAttributeValue(null, "answer") != null) {
                        isCorrect = true;
                        answer = parser.nextText();
                        choices = new Choices(isCorrect, answer);
                    }
                    else {
                        isCorrect = false;
                        answer = parser.nextText();
                        choices = new Choices(isCorrect, answer);
                    }

                    choiceList.add(choices);
                    parser.next();

                }

                question.setChoices(choiceList);

            } // END Choices Parsing

            break;

        case XmlPullParser.END_TAG:

            if (parser.getName().equals("question")) {
                questionList.add(question);
                question = null;
            }

            break;

        default:
            break;

        } // END Switch

        event = parser.next();

    } // END While loop

    return questionList;

}

}

This class parses out the XML using PULL and makes an ArrayList of objects of my Question class:

import java.util.ArrayList;
import android.os.Parcel;
import android.os.Parcelable;

public class Question implements Parcelable {


public String id;
public String text;
public String image;
public ArrayList<Choices> choices;


public Question() {
    // TODO Auto-generated constructor stub
}


// Constructs a Question from values
public Question (String id, String text, String image, ArrayList<Choices> choices) {
    this.id = id;
    this.text = text;
    this.image = image;
    this.choices = choices;
}


public String getId() {
    return id;
}
public void setId(String id) {
    this.id = id;
}


public String getText() {
    return text;
}
public void setText(String text) {
    this.text = text;
}


public String getImage() {
    return image;
}
public void setImage(String image) {
    this.image = image;
}


public ArrayList<Choices> getChoices() {
    return choices;
}
public void setChoices(ArrayList<Choices> choices) {
    this.choices = choices;
}

@Override
public String toString() {
    return "Question [id=" + id + ", text=" + text + ", image=" + image
            + "]";
}



/**
 * Constructs a Question from a Parcel
 * @param parcel Source Parcel
 */
public Question (Parcel parcel) {
    this.id = parcel.readString();
    this.text = parcel.readString();
    this.image = parcel.readString();
    this.choices = parcel.readArrayList(null);
}

@Override
public int describeContents() {
    return 0;
}

// Required method to write to Parcel
@Override
public void writeToParcel(Parcel dest, int flags) {
    dest.writeString(id);
    dest.writeString(text);
    dest.writeString(image);
    dest.writeList(choices);
}

// Method to recreate a Question from a Parcel
public static Creator<Question> CREATOR = new Creator<Question>() {

    @Override
    public Question createFromParcel(Parcel source) {
        return new Question(source);
    }

    @Override
    public Question[] newArray(int size) {
        return new Question[size];
    }

};


}

I also have a class called Choices where I put the answers, then I make an ArrayList that I add to each Question object.

When I run the code, the app doesn't even start, just immediately says that it stopped working. I think the log says it's in the doInBackground.

Log/Errors

03-17 15:52:51.509: D/dalvikvm(2032): GC_FOR_ALLOC freed 93K, 5% free 3020K/3168K, paused 2ms, total 4ms
03-17 15:52:51.509: I/dalvikvm-heap(2032): Grow heap (frag case) to 3.607MB for 635808-byte allocation
03-17 15:52:51.529: D/dalvikvm(2032): GC_FOR_ALLOC freed 5K, 5% free 3635K/3792K, paused 13ms, total 13ms
03-17 15:52:51.589: D/(2032): HostConnection::get() New Host Connection established 0xb8e93af0, tid 2032
03-17 15:52:51.629: W/EGL_emulation(2032): eglSurfaceAttrib not implemented
03-17 15:52:51.629: D/OpenGLRenderer(2032): Enabling debug mode 0
03-17 15:52:51.679: W/EGL_emulation(2032): eglSurfaceAttrib not implemented
03-17 15:52:51.799: W/dalvikvm(2032): threadid=11: thread exiting with uncaught exception (group=0xb2cbdb20)
03-17 15:52:51.799: E/AndroidRuntime(2032): FATAL EXCEPTION: AsyncTask #1
03-17 15:52:51.799: E/AndroidRuntime(2032): Process: com.example.midterm, PID: 2032
03-17 15:52:51.799: E/AndroidRuntime(2032): java.lang.RuntimeException: An error occured while executing doInBackground()
03-17 15:52:51.799: E/AndroidRuntime(2032):     at android.os.AsyncTask$3.done(AsyncTask.java:300)
03-17 15:52:51.799: E/AndroidRuntime(2032):     at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:355)
03-17 15:52:51.799: E/AndroidRuntime(2032):     at java.util.concurrent.FutureTask.setException(FutureTask.java:222)
03-17 15:52:51.799: E/AndroidRuntime(2032):     at java.util.concurrent.FutureTask.run(FutureTask.java:242)
03-17 15:52:51.799: E/AndroidRuntime(2032):     at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:231)
03-17 15:52:51.799: E/AndroidRuntime(2032):     at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
03-17 15:52:51.799: E/AndroidRuntime(2032):     at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
03-17 15:52:51.799: E/AndroidRuntime(2032):     at java.lang.Thread.run(Thread.java:841)
03-17 15:52:51.799: E/AndroidRuntime(2032): Caused by: java.lang.NullPointerException
03-17 15:52:51.799: E/AndroidRuntime(2032):     at com.example.midterm.QuestionUtil.parseQuestions(QuestionUtil.java:54)
03-17 15:52:51.799: E/AndroidRuntime(2032):     at com.example.midterm.MainActivity$QuizWorker.doInBackground(MainActivity.java:60)
03-17 15:52:51.799: E/AndroidRuntime(2032):     at com.example.midterm.MainActivity$QuizWorker.doInBackground(MainActivity.java:1)
03-17 15:52:51.799: E/AndroidRuntime(2032):     at android.os.AsyncTask$2.call(AsyncTask.java:288)
03-17 15:52:51.799: E/AndroidRuntime(2032):     at java.util.concurrent.FutureTask.run(FutureTask.java:237)
03-17 15:52:51.799: E/AndroidRuntime(2032):     ... 4 more
03-17 15:52:52.169: E/WindowManager(2032): android.view.WindowLeaked: Activity com.example.midterm.MainActivity has leaked window com.android.internal.policy.impl.PhoneWindow$DecorView{b2faf408 V.E..... R......D 0,0-456,144} that was originally added here
03-17 15:52:52.169: E/WindowManager(2032):  at android.view.ViewRootImpl.<init>(ViewRootImpl.java:348)
03-17 15:52:52.169: E/WindowManager(2032):  at android.view.WindowManagerGlobal.addView(WindowManagerGlobal.java:248)
03-17 15:52:52.169: E/WindowManager(2032):  at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:69)
03-17 15:52:52.169: E/WindowManager(2032):  at android.app.Dialog.show(Dialog.java:286)
03-17 15:52:52.169: E/WindowManager(2032):  at com.example.midterm.MainActivity$QuizWorker.onPreExecute(MainActivity.java:101)
03-17 15:52:52.169: E/WindowManager(2032):  at android.os.AsyncTask.executeOnExecutor(AsyncTask.java:587)
03-17 15:52:52.169: E/WindowManager(2032):  at android.os.AsyncTask.execute(AsyncTask.java:535)
03-17 15:52:52.169: E/WindowManager(2032):  at com.example.midterm.MainActivity.onCreate(MainActivity.java:28)
03-17 15:52:52.169: E/WindowManager(2032):  at android.app.Activity.performCreate(Activity.java:5231)
03-17 15:52:52.169: E/WindowManager(2032):  at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1087)
03-17 15:52:52.169: E/WindowManager(2032):  at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2159)
03-17 15:52:52.169: E/WindowManager(2032):  at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2245)
03-17 15:52:52.169: E/WindowManager(2032):  at android.app.ActivityThread.access$800(ActivityThread.java:135)
03-17 15:52:52.169: E/WindowManager(2032):  at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1196)
03-17 15:52:52.169: E/WindowManager(2032):  at android.os.Handler.dispatchMessage(Handler.java:102)
03-17 15:52:52.169: E/WindowManager(2032):  at android.os.Looper.loop(Looper.java:136)
03-17 15:52:52.169: E/WindowManager(2032):  at android.app.ActivityThread.main(ActivityThread.java:5017)
03-17 15:52:52.169: E/WindowManager(2032):  at java.lang.reflect.Method.invokeNative(Native Method)
03-17 15:52:52.169: E/WindowManager(2032):  at java.lang.reflect.Method.invoke(Method.java:515)
03-17 15:52:52.169: E/WindowManager(2032):  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:779)
03-17 15:52:52.169: E/WindowManager(2032):  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:595)
03-17 15:52:52.169: E/WindowManager(2032):  at dalvik.system.NativeStart.main(Native Method)

Any help would be greatly appreciated. I have no errors in my code and I just can't figure out what might be wrong, why it's not even starting.

Kenny
  • 2,124
  • 3
  • 33
  • 63

1 Answers1

1

Concerning this part of your logcat:

03-17 15:52:52.169: E/WindowManager(2032): android.view.WindowLeaked: Activity com.example.midterm.MainActivity has leaked window com.android.internal.policy.impl.PhoneWindow$DecorView{b2faf408 V.E..... R......D 0,0-456,144} that was originally added here
03-17 15:52:52.169: E/WindowManager(2032):  at android.view.ViewRootImpl.<init>(ViewRootImpl.java:348)
03-17 15:52:52.169: E/WindowManager(2032):  at android.view.WindowManagerGlobal.addView(WindowManagerGlobal.java:248)
03-17 15:52:52.169: E/WindowManager(2032):  at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:69)
03-17 15:52:52.169: E/WindowManager(2032):  at android.app.Dialog.show(Dialog.java:286)

I recommend you to have a look at this link. I think this one will work as soon as the other error doesn't occur anymore.

The following line says there is a NullPointerException. To determine what exactly is null, it's necessary to know which line QuestionUtil.java:54 is.

03-17 15:52:51.799: E/AndroidRuntime(2032):     at com.example.midterm.QuestionUtil.parseQuestions(QuestionUtil.java:54)
Community
  • 1
  • 1
Julisch
  • 308
  • 1
  • 16
  • I have the `Dialog.show()` in my `onPreExecute`, I thought it'd be during the activity. I look at the link you provided, someone suggested not having `Dialog.dismiss()` in the post execute, do you think if I fix these then my application will work? – Kenny Mar 17 '14 at 20:58
  • I don't think the dialog is what we should worry much about. That described NullPointerException is thrown, and as a result the finishing AsyncTask tries to remove its Dialog off the Activity which is already crashed, and thus doesn't exist anymore. As soon as we make your QuestionUtil work correctly, the dialog will be dismissed correctly. – Julisch Mar 17 '14 at 21:03
  • So then you're saying the real problem must be in the `QuestionUtil` class? – Kenny Mar 17 '14 at 21:04
  • Yes. Which line is `QuestionUtil.java:54` ? – Julisch Mar 17 '14 at 21:06
  • while (parser.getName().equals("choice")) { – Kenny Mar 17 '14 at 21:10
  • 1
    well then the `name`, that's read is `null`. Try doing it the other way round: `while("choice".equals(parser.getName()))` – Julisch Mar 17 '14 at 21:11
  • Oh my goodness, that worked! Thank you very much for the help! – Kenny Mar 17 '14 at 21:14