Reputation: 89
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
Reputation: 1829
Try to use
progressDialog = new ProgressDialog(MainActivity.this);
instead of
progressDialog = new ProgressDialog(getApplicationContext());
Upvotes: 1
Reputation: 1485
You need to replace
mProgressDialog = new ProgressDialog(getApplicationContext());
with
mProgressDialog = new ProgressDialog(this);
Reference:
Upvotes: 0