Obi
Obi

Reputation: 89

My application crashes when trying to read directly from URL

I am trying to design an app that reads jokes directly from a URL, but for some reason that I can't figure out it crashes when I press the button to initiate the process.

I am using two buttons, One to read one joke and another to read three jokes. When the first button is clicked,it will call an AsyncTask that Intiates the reading from the URL and shows a progress bar until the joke downloads. The second button does the same but downloads 3 jokes instead of one. Here is the mainActivity Class.

public class MainActivity extends AppCompatActivity {
    private Button oneJokeBtn, threeJokesBtn;
    private TextView mJokeTv;
    private final static String ERROR_TAG = "Download Error";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        // Capturing the TextView from our View
        mJokeTv = findViewById(R.id.tv_joke);
        // Capturing our buttons from the view
        oneJokeBtn = findViewById(R.id.joke_1);
        threeJokesBtn = findViewById(R.id.joke_3);
        // Register the onClick listener
        oneJokeBtn.setOnClickListener(buttonHandler);
        threeJokesBtn.setOnClickListener(buttonHandler);
        // Declaring the Spinner
        Spinner spinner = findViewById(R.id.spinner);
        // Create an ArrayAdapter using the string array and a default spinner layout
        ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(this,
            R.array.length_array, android.R.layout.simple_spinner_item);
    // Specify the layout to use when the list of choices appears
        adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
    // Apply the adapter to the spinner
    spinner.setAdapter(adapter);
    // Spinner onItemSelector implemented in the OnCreate Method
    spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
        @Override
        public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
            switch (position){
                case 0:
                    Toast.makeText(parent.getContext(), R.string.short_toast, Toast.LENGTH_SHORT).show();
                    break;
                case 1:
                    Toast.makeText(parent.getContext(), R.string.medium_toast, Toast.LENGTH_SHORT).show();
                    break;
                case 2:
                    Toast.makeText(parent.getContext(), R.string.long_toast, Toast.LENGTH_SHORT).show();
                    break;
            }
        }

        @Override
        public void onNothingSelected(AdapterView<?> parent) {

        }
    });
}
/** AsyncTask that reads one joke directly from the URL and adds it to the textView */
private class Download1JokeAsyncTask extends AsyncTask<Void, Void, String> {
    private ProgressDialog progressDialog;

    @Override
    protected void onPreExecute() {
        progressDialog = new ProgressDialog(getApplicationContext());
        progressDialog.setMessage(getString(R.string.progress_msg));
        progressDialog.setIndeterminate(true);
        progressDialog.show();
    }

    @Override
    protected String doInBackground(Void... voids) {
        try {
            URL url = new URL("http://www.oracle.com/");
            URLConnection conn = url.openConnection();
            // Obtain the input stream
            BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
            // The joke is a one liner, so just read one line.
            String joke;
            while ((joke = in.readLine()) != null) {
                System.out.println(joke);
            }
            // Close the connection
            in.close();
        } catch (MalformedURLException e) {
            e.printStackTrace();
            Log.e(ERROR_TAG, "Exception: ", e);
        } catch (IOException e) {
            e.printStackTrace();
            Log.e(ERROR_TAG, "Exception: ", e);
        }
        return null;
    }

    @Override
    protected void onPostExecute(String joke) {
        mJokeTv.setText(joke);
        if (progressDialog.isShowing()) {
            progressDialog.dismiss();
        }
    }

}

/** AsyncTask that reads three jokes directly from the URL and adds it to the textView */
private class Download3JokeAsyncTask extends AsyncTask<Void, Integer, String[]> {
    private ProgressDialog mProgressDialog;

    @Override
    protected void onPreExecute() {
        super.onPreExecute();
        mProgressDialog = new ProgressDialog(getApplicationContext());
        mProgressDialog.setProgress(0);
        mProgressDialog.setIndeterminate(false);
        mProgressDialog.show();
    }

    @Override
    protected String[] doInBackground(Void... voids) {
        int count = 2;
        for (int i = 0; i < 2; i++){
            try {
                URL url = new URL("http://www.oracle.com/");
                URLConnection conn = url.openConnection();
                // Obtain the input stream
                BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
                // The joke is a one liner, so just read one line.
                String joke;
                while ((joke = in.readLine()) != null) {
                    System.out.println(joke);
                }
                // Close the connection
                in.close();
            } catch (MalformedURLException e) {
                e.printStackTrace();
                Log.e(ERROR_TAG, "Exception: ", e);
            } catch (IOException e) {
                e.printStackTrace();
                Log.e(ERROR_TAG, "Exception: ", e);
            }
            publishProgress((int) ((i / (float) count) * 100));
        }
        return null;
    }

    @Override
    protected void onProgressUpdate(Integer... values) {
        super.onProgressUpdate(values);

    }

    @Override
    protected void onPostExecute(String[] strings) {
        super.onPostExecute(strings);
    }
}
/** onClickListener that gets the id of the button pressed and download jokes accordingly */
OnClickListener buttonHandler = new OnClickListener() {
    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.joke_1:
                new Download1JokeAsyncTask().execute();
                break;
            case R.id.joke_3:
                new Download3JokeAsyncTask().execute();
                break;
        }
    }
};

Here the log of the LogCat:

--------- beginning of crash

04-14 18:57:10.670 17411-17411/com.mad.exercise4 E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.mad.exercise4, PID: 17411
    android.view.WindowManager$BadTokenException: Unable to add window -- token null is not valid; is your activity running?
        at android.view.ViewRootImpl.setView(ViewRootImpl.java:765)
        at android.view.WindowManagerGlobal.addView(WindowManagerGlobal.java:356)
        at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:93)
        at android.app.Dialog.show(Dialog.java:330)
        at com.mad.exercise4.MainActivity$Download3JokeAsyncTask.onPreExecute(MainActivity.java:136)
        at android.os.AsyncTask.executeOnExecutor(AsyncTask.java:648)
        at android.os.AsyncTask.execute(AsyncTask.java:595)
        at com.mad.exercise4.MainActivity$2.onClick(MainActivity.java:187)
        at android.view.View.performClick(View.java:6294)
        at android.view.View$PerformClick.run(View.java:24770)
        at android.os.Handler.handleCallback(Handler.java:790)
        at android.os.Handler.dispatchMessage(Handler.java:99)
        at android.os.Looper.loop(Looper.java:164)
        at android.app.ActivityThread.main(ActivityThread.java:6494)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:807)
04-14 18:57:10.721 17411-17416/com.mad.exercise4 I/zygote: Do full code cache collection, code=92KB, data=56KB
    After code cache collection, code=90KB, data=44KB


----------

I haven't populated the second AsyncTask code because it also results in same error.

Please Help :).

Upvotes: 0

Views: 50

Answers (2)

Brainnovo
Brainnovo

Reputation: 1829

Try to use

progressDialog = new ProgressDialog(MainActivity.this); 

instead of

progressDialog = new ProgressDialog(getApplicationContext());

Upvotes: 1

theboringdeveloper
theboringdeveloper

Reputation: 1485

You need to replace

mProgressDialog = new ProgressDialog(getApplicationContext());

with

mProgressDialog = new ProgressDialog(this);

Reference:

Android 1.6: "android.view.WindowManager$BadTokenException: Unable to add window -- token null is not for an application"

Upvotes: 0

Related Questions