I have an android app connected to a servlet. If the servlet is down (happened to me yesterday) the app crashes. I need to pop up a message to the user informing about some connection issues and then terminate the application.
on onCreate() method, i call an AsyncTask class, in which is done the first connection to the server. I have a try/catch(UnknownHostException e) block, which is activated if the sevlet is down.
The problem is that i cant create a pop up message there. I tried toast and AllertDialogs, but both return an exception
Java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
Is there some other way i can do this? Thanks in advance, ilias
You could set a boolean and read it after the function call, at which point you should be able to show a toast/dialog. But that's hard to say without the rest of the code.
Your AsyncTask is running in a background thread. Calls to show a Toast or a Dialog must be made on the main (UI) thread. To do this from within an AsyncTask you can do this:
You'll need an activity context in your AsyncTask, so have your activity create your AsyncTask like this:
MyAsyncTask task = new MyAsyncTask(this, ...); // pass "this" so AsyncTask has an activity context
In your AsyncTask constructor, save the activity context so you can use it later:
private Activity activity;
// Constructor
MyAsyncTask(Activity activity, ...) {
this.activity = activity;
...
}
When you want to show a Dialog or a Toast, make sure the code runs on the main (UI) thread:
// Here we want to Toast
activity.runOnUiThread(new Runnable() {
#Override
public void run() {
// Do your Toast or Dialog stuff in here
...
}
});
Related
I have a created non activity java class for doing same calculation from different activities. This class has asynctask with progress Dialog in it. In most cases calculation is not the last operation of activity and everything goes fine, but when it is my Progress Dialog goes lost.
Example:
myJavaClass doCalculations= new myJavaClass (SomeActivity.this);
doCalculations.Do(); //<------ method Do has asysctask with Progress Dialog
finish();
result:
java.lang.IllegalArgumentException: View=com.android.internal.policy.impl.PhoneWindow$DecorView{2bbf820e V.E..... R......D 0,0-1026,483} not attached to window manager
How can I wait for asynctask to finish and then finish activity?
Additional question: Is using asynctask in non activity class is a bad practice ?
If you want to keep your activity active until the AsyncTask has finished its job, you can define a callback method in the activity that gets called when the task has finished and can react appropriately:
In the Activity:
private boolean finishAfterCurrentTask = false;
public void onTaskFinished() {
if (finishAfterCurrentTask) { // set this to true when running the last task
finish();
}
}
In the AsyncTask:
protected void onPostExecute(Object result) {
progressDialog.dismiss();
activity.onTaskFinished();
}
I'm assuming that you're keeping a reference to the activity in myJavaClass. In case that you're calling the AsyncTask from a non-UI thread, you should probably run the callback (and also all methods involving the dialog) via Activity.runOnUiThread().
As for the second question - if you use an AsyncTask in a class which methods can be called from a thread other than the UI thread, it's necessary to use runOnUiThread() to perform any operations on the UI, such as changing the contents of a view or showing/hiding a dialog, beause onPreExecute() and onPostExecute() are called from the same thread as execute().
On the other hand, if you start the task inside one of the UI callbacks, which are guaranteed to run on the UI thread, you don't need to worry about that.
The AsyncTask has a onPostExecute method you can finish the activity from there
protected void onPostExecute(Long result) {
progressDialog.dismiss();
finish(); // you'll probably have to call finish() with a callback function
}
The onPostExecute method is called when the doInBackground method is finished, on that method you can finish the activity and close the progressdialog
How to block UI thread from doing anything and just displaying a progress bar until certain condition is met.
For example I have a list initialized to null, Lets call it list. I start another thread in UI to initialize its value which is going to take around 10 seconds. How can I block UI thread displaying progress dialog until the list is initialized.
// Initially
List list = null;
// Display progress bar until certain condition is met
while(list == null){
// Display progress dialog
}
I think AsyncTask will work if we ask that AsyncTask to update the list etc, what about another thread doing it. I have tried to simplify the problem.
you need to create a public method in mainActivity, named for examble yourcallback()
instead of instantiating all the objects in the OnCreate mainActivity, you can instantiate all objects in addition to quell ic you need for the progressbar in the callback method
yourcallback()
your callback
now you need to create an extenction of AsyncTask where you declare a base method constructor
like this
privte Activity mainObj;
public TestAsyncTask(Context context, Activity mainact ) throws Exception {
mainObj=mainact
your code
}
when the task naturally terminate the class AsyncTask call onPostExecute method
protected void onPostExecute(Long result) {
mainObj.yourcallback();
}
hope this help!
I think I am not getting something about the android activity lifecycle.
So here's my situation - I have an AsyncTask that does the job of uploading an XML file to a server. It is called when the user presses a button after filling out the required data in the activity. After it is called, I don't really need the activity anymore, so I call finish(); immediately.
task = new ASSend(data);
task.execute();
finish();
However, I need to display error messages in case something goes wrong during the execution of the AsyncTask (so I need to use either an AlertDialog or a dialog-themed intent), and I also need to open files in doInBackground with
FileInputStream fis;
fis = context.openFileInput(filePath);
which requires a context. Is it possible to pass the context of the activity that started the AsyncTask to do all this, even though the activity that launched the AsyncTask no longer exists?
Maybe you shouldn't call finish() on the activity immediately. Try just adding a progress dialog in your async task to show a loading screen of sorts.
public class task extends AsyncTask<Object, Object, Object> {
ProgressDialog mDialog;
Context mContext;
public task (Context context) {
this.mContext = context;
}
#Override
protected void onPreExecute() {
super.onPreExecute();
mDialog = new ProgressDialog(mContext);
mDialog.setMessage("Preparing Route...");
mDialog.show();
}
#Override
protected void onPostExecute(Object obj) {
mDialog.dismiss();
// then call finish?
}
I don't think AsyncTask is the correct class to use here. I think you should use an IntentService instead, for a few reasons:
Services have a higher process priority, meaning processes that host active Services are less likely to be killed by the system. In other words, using an AsyncTask inside an Activity would be more risky because the system would be more likely to kill your application process in low-memory situations.
You don't need to worry about leaking an activity context (since the Service isn't tied directly to the Activity lifecycle).
It's immediate--you don't need to block the user interface with a Dialog and wait for the task to complete. You can just queue up a task to be performed using an IntentService and leave the Activity immediately, and the task will eventually be executed asynchronously.
In your activity, call this.getApplicationContext() to get a context that will live beyond the lifetime of the Activity.
I am a beginner to Android and I have some confusions regarding Android UI Thread. Now, I know that no thread apart from the one that created the UI can modify it.
Great.
Here is the Activity from my first Android app which slightly confuses me.
public class NasaDailyImage extends Activity{
public ProgressDialog modalDialog = null;
//------------------------------------------------------------------------------
#Override
protected void onCreate(Bundle savedInstanceState){
//Instantiate progress dialog, skipping details.
Button b = //get reference to button
b.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
modalDialog.show(); // show modal
Toast.makeText(getApplicationContext(), "Getting feeds", 500).show();
new AsyncRetriever().execute(new IotdHandler()); // Get the feeds !!
}
});
}
//------------------------------------------------------------------------------
public synchronized void resetDisplay(boolean parseErrorOccured,
boolean imageErrorOccured,
IotdHandler newFeeds){
if(parseErrorOccured || imageErrorOccured){
// make a Toast
// do not update display
}else{
// make a Toast
// update display
// based on new feed
}
}
//------------------------------------------------------------------------------
class AsyncRetriever extends AsyncTask<IotdHandler,Void,IotdHandler>{
#Override
protected IotdHandler doInBackground(IotdHandler... arg0) {
IotdHandler handler = arg0[0];
handler.processFeed(); // get the RSS feed data !
return handler;
}
//------------------------------------------------------------------------------
#Override
protected void onPostExecute(IotdHandler fromInBackground){
resetDisplay( // call to update the display
fromInBackground.errorOccured,
fromInBackground.imageError,
fromInBackground);
}
//------------------------------------------------------------------------------
}
1. onCreate is on the UI thread so I can do whatever I want but onClick is not. Why can I make a ProgressDialog and a Toast in that method? Why no error there?
2. The AsyncTask is subclass of the the NasaDailyImage. This means it can access all the methods of NasaDailyImage including resetDisplay() which updates the display. resetDisplay() is called in the onPostExecute which runs on a different thread from UI. So, why can I update the display there and yet get no errors ?
onClick() is indeed on the UI thread. Most of what happens in an Activity happens on the UI thread.
onPostExecte() (and its counterpart onPreExecute()) runs on the UI thread as well. The AsyncTask.onPostExecte() documentation clearly states this. AsyncTask was deliberately designed such that developers could update the UI before and after they do background work.
In general, your code will be running on the UI thread unless you explicitly tell it otherwise. Once you create AsyncTasks, Runnables, or Threads, you need to ensure you understand where your code is executing. In an Activity, it is typically safe to assume you are on the UI thread.
You are extending AsyncTask class , where async task class is calling its sequential method automatically. First onPreExecute then doBackground and finally onPost. If you want to change any ui change you can use onProgressUpdate method.
To use your activity class simple call activityclass.this.resetDisplay(). Because inner class scope sometimes failed to integrate except global varible.
Thanks
I am popping up a dialog from an Application context by calling an intent which has a transparent theme.(Similar to what is mentioned here.)
The pop is a read only.The issue is that when the pop up is shown there is a current activity going on in the background. I need to be able to access the background activity too while the popup is dispalyed. I have added the following two lines but it still is not possible for me to control the underlying activity:
getWindow().addFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL);
What am I doing wrong?
you must open the dialog in a thread, you haven't explained much about what you want to do in background ,but for making a thread do this:
create a new class with name:thread1 then write down these there:
public class thread1 extends Thread {
MainActivity activity;
public thread1(MainActivity m){
activity=m;
ProgressDialog pd;
//other code maybe for specification
pd=ProgressDialog.show(activity,"", "wait for background activity");
}
#Override
public void run(){
//you code working in background here like:
activity.sucess=0;
while (activity.sucess==0){
android.os.SystemClock.sleep(300);
}
pd.dismiss();
}
}
whenever you want to open this pb you should write this,
thread1 t1=new thread1(this);
t1.start();
and when ever your work is done and you want to close the pb, you must set sucess=1 then the thread will be killed.