In my app, i'm reading text files from web server using Async Tasking from a separate class because it is used in many activities, so i've made a dedicated class. I'm trying to show a spinning progress dialogue but it is giving me error when i put the code in Async Tasking class.
here is my cod for Async Task Class
public class Utilssss extends AsyncTask<String, String, String> {
private Context mContext;
private ProgressDialog pdia;
// constructor
public Utilssss(Context activityContext) {
mContext = activityContext;
}
protected void onPreExecute() {
super.onPreExecute();
pdia = new ProgressDialog(mContext);
pdia.setMessage("Loading...");
pdia.show();
}
protected String doInBackground(String... url) {
return GetLinkss(url[0]);
}
protected void onPostExecute(String result) {
// Toast.makeText(mContext, result, Toast.LENGTH_LONG).show();
super.onPostExecute(result);
pdia.dismiss();
}
private String GetLinkss(String url) {
// your stuff
String StringBuffer = "";
String stringText = "";
try {
URL link = new URL(url);
BufferedReader bufferReader = new BufferedReader(new InputStreamReader(link.openStream()));
while ((StringBuffer = bufferReader.readLine()) != null) {
stringText += StringBuffer;
}
bufferReader.close();
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return stringText;
}
}
Code how i'm accessing this class
public void urdu(View view) throws InterruptedException, ExecutionException {
String fileexist = null;
fileexist = new Utilssss(getBaseContext()).execute("http://192.168.1.2/eWorldLiterature/urdu/index.txt").get();
Toast.makeText(getBaseContext(), fileexist, Toast.LENGTH_SHORT).show();
// if (fileexist != 229) {
Intent i = new Intent(getBaseContext(), MainPage.class);
i.putExtra(LANGUAGE, "urdu");
startActivity(i);
Here is the LogCat results.
12-05 00:38:06.266: E/AndroidRuntime(28766): FATAL EXCEPTION: main
12-05 00:38:06.266: E/AndroidRuntime(28766): java.lang.IllegalStateException: Could not execute method of the activity
12-05 00:38:06.266: E/AndroidRuntime(28766): at android.view.View$1.onClick(View.java)
12-05 00:38:06.266: E/AndroidRuntime(28766): at android.view.View.performClick(View.java)
12-05 00:38:06.266: E/AndroidRuntime(28766): at android.view.View$PerformClick.run(View.java)
12-05 00:38:06.266: E/AndroidRuntime(28766): at android.os.Handler.handleCallback(Handler.java)
12-05 00:38:06.266: E/AndroidRuntime(28766): at android.os.Handler.dispatchMessage(Handler.java)
12-05 00:38:06.266: E/AndroidRuntime(28766): at android.os.Looper.loop(Looper.java)
12-05 00:38:06.266: E/AndroidRuntime(28766): at android.app.ActivityThread.main(ActivityThread.java)
12-05 00:38:06.266: E/AndroidRuntime(28766): at java.lang.reflect.Method.invokeNative(Native Method)
12-05 00:38:06.266: E/AndroidRuntime(28766): at java.lang.reflect.Method.invoke(Method.java)
12-05 00:38:06.266: E/AndroidRuntime(28766): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java)
12-05 00:38:06.266: E/AndroidRuntime(28766): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java)
12-05 00:38:06.266: E/AndroidRuntime(28766): at dalvik.system.NativeStart.main(Native Method)
12-05 00:38:06.266: E/AndroidRuntime(28766): Caused by: java.lang.reflect.InvocationTargetException
12-05 00:38:06.266: E/AndroidRuntime(28766): at java.lang.reflect.Method.invokeNative(Native Method)
12-05 00:38:06.266: E/AndroidRuntime(28766): at java.lang.reflect.Method.invoke(Method.java)
12-05 00:38:06.266: E/AndroidRuntime(28766): ... 12 more
12-05 00:38:06.266: E/AndroidRuntime(28766): Caused by: android.view.WindowManager$BadTokenException: Unable to add window -- token null is not for an application
12-05 00:38:06.266: E/AndroidRuntime(28766): at android.view.ViewRootImpl.setView(ViewRootImpl.java)
12-05 00:38:06.266: E/AndroidRuntime(28766): at android.view.WindowManagerImpl.addView(WindowManagerImpl.java)
12-05 00:38:06.266: E/AndroidRuntime(28766): at android.view.WindowManagerImpl.addView(WindowManagerImpl.java)
12-05 00:38:06.266: E/AndroidRuntime(28766): at android.view.WindowManagerImpl$CompatModeWrapper.addView(WindowManagerImpl.java)
12-05 00:38:06.266: E/AndroidRuntime(28766): at android.app.Dialog.show(Dialog.java)
12-05 00:38:06.266: E/AndroidRuntime(28766): at md.literature.imranseries.Utilssss.onPreExecute(Utilssss.java:35)
12-05 00:38:06.266: E/AndroidRuntime(28766): at android.os.AsyncTask.executeOnExecutor(AsyncTask.java)
12-05 00:38:06.266: E/AndroidRuntime(28766): at android.os.AsyncTask.execute(AsyncTask.java)
12-05 00:38:06.266: E/AndroidRuntime(28766): at md.literature.imranseries.Selection.urdu(Selection.java:65)
12-05 00:38:06.266: E/AndroidRuntime(28766): ... 14 more
Just one more thing i want to ask. Sorry to bother you guys again.. Here is the thing, one of my activity relies on the results of Asynctask and should no proceed unless the task is completed, but this is not happening, here is a sample piece of code which proves it.
final Context context = this;
new Utils(context, new Utils.UtilsCallback() {
@Override
public void onResult(String lstr) {
// lstr = string;
Toast.makeText(getBaseContext(), "Now Raeading" + Novelselected, Toast.LENGTH_LONG).show();
}
}).execute(ulti_link + "/" + Novelselected.replace(" ", "%20") + ".txt");
Toast.makeText(getBaseContext(), "Now Raeading", Toast.LENGTH_LONG).show();
in the above code, the following Toast appears before the Toast within the AsyncTAsk appears, The question is, how can i pause my main thread to wait for the AsyncTAsk to complete. Thanks a lot :)
I suggest you read this explanation about the different types of Context
Android
has. There are some instances of Context
that do not allow you to do certain things that other Context
instances do (ie Service
is a Context
that doesn't allow layout inflation).
In your case you are passing the Application
Context
to the AsyncTask
constructor, and subsequently to the Dialog
. You should use an Activity
Context
instead.
Since you are calling the AsyncTask
from an Activity
and Activity
extends from Context
you can use the keyword this
in the AsyncTask
instantiation like Cata said.
Besides using the correct Context
you must not use AsyncTask#get()
. Never. It blocks the Ui thread until the result is available and you can not show a progress dialog during that time then because you are already waiting for the result.
If you want to use an AsyncTask from a different class add a callback mechanism of your own.
public class Utilssss extends AsyncTask<String, String, String> {
/** Implement this somewhere to get the result */
public interface UtilssssCallback {
void onResult(String string);
}
private Context mContext;
private ProgressDialog pdia;
private UtilssssCallback mListener;
// constructor
public Utilssss(Context activityContext, UtilssssCallback listener) {
mContext = activityContext;
mListener = listener; // save callback
}
@Override
protected void onPostExecute(String result) {
pdia.dismiss();
mListener.onResult(result);
}
// rest omitted since unchanged
}
And inside your Activity
public void urdu(View view) {
final Context context = this;
new Utilssss(context, new Utilssss.UtilssssCallback() {
@Override
public void onResult(String string) {
Toast.makeText(context, string, Toast.LENGTH_LONG).show();
Intent i = new Intent(context, MainPage.class);
i.putExtra(LANGUAGE, "urdu");
context.startActivity(i);
}
}).execute("http://192.168.1.2/eWorldLiterature/urdu/index.txt");
}
Note that the code inside onResult
is executed way after the program flow has already left the urdu(View view)
method.
Alternatively to implementing the callback as an anonymous inner class ( new UtilssssCallback(){...}
) you could also let the Activity
implement the interface and make it a method. Doing it that way looks less confusing but is essentially the same.
public class TheActivity extends FragmentActivity implements UtilssssCallback {
public void urdu(View view) {
// those two are not necessary but help make it obvious what parameters we have
Context context = this;
UtilssssCallback callback = this; // the class implements that
new Utilssss(context, callback).execute("http://192.168.1.2/eWorldLiterature/urdu/index.txt");
}
@Override
public void onResult(String string) {
Toast.makeText(context, string, Toast.LENGTH_LONG).show();
}
....
I would suggest two things:
WeakReference
when passing a context to an AsyncTask
Activity
to start and stop your progress dialog Something like this:
public class ProgressAsyncTask extends AsyncTask<Void, Void, Void> {
private WeakReference<Activity> weakActivity;
public ProgressAsyncTask(Activity activity) {
weakActivity = new WeakReference<Activity>(activity);
}
@Override
protected void onPreExecute() {
super.onPreExecute();
Activity activity = weakActivity.get();
((MainActivity) activity).showProgressDialog(true);
}
@Override
protected void doInBackground(Void... params) {
// Do stuff
}
@Override
protected void onPostExecute(List<Color> result) {
super.onPostExecute(result);
Activity activity = weakActivity.get();
((MainActivity) activity).showProgressDialog(false);
}
In your MainActivity you implement the method showProgressDialog(boolean show)
.
And as Emmanuel pointed out you should most likely pass an Activity
's context.
Try this:
fileexist = new Utilssss(this).execute("http://192.168.1.2/eWorldLiterature/urdu/index.txt").get();
Where "this" should be the Activity and assumming that the parameter represents the mContext on the Utilssssclass side :).
And also pay attention to Emmanuel's answer too.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.