I have my asyncTask run when the activity first starts, then if network connectivity is not available then i have a refresh button that tries to run the asyncTask to try again. But i get a debug error saying this..
07-29 18:14:21.290: ERROR/AndroidRuntime(9080): FATAL EXCEPTION: main
07-29 18:14:21.290: ERROR/AndroidRuntime(9080): java.lang.IllegalStateException: Cannot execute task: the task has already been executed (a task can be executed only once)
07-29 18:14:21.290: ERROR/AndroidRuntime(9080): at android.os.AsyncTask.executeOnExecutor(AsyncTask.java:541)
07-29 18:14:21.290: ERROR/AndroidRuntime(9080): at android.os.AsyncTask.execute(AsyncTask.java:499)
07-29 18:14:21.290: ERROR/AndroidRuntime(9080): at com.fttech.gameIT.MainMenu$1.onClick(MainMenu.java:90)
Is there anyway to run this twice?
Just create another instance and execute it.
Just like threads, AsyncTasks can't be reused. You have to create a new instance every time you want to run one.
You can never execute a thread again, not in Java, not in any other language, once the thread is done with the run() method, you cannot restart it, which is why you are getting the IllegalStateException.
You can however still call the methods on that thread but they will run on the thread that is calling them NOT on a different thread. Therefore you will have to create a new one.
You cannot run same instance of an AsyncTask more than once.
Let's assume you have an AsyncTask named MyAsyncTaks and you intend to do something like this,
MyAsyncTask myAsyncTask = new MyAsyncTaks();
myAsyncTask.execute(); // Works as expected
.
.
.
.
myAsyncTask.execute(); // This will throw you exception
The reason for this is, a thread once finishes its 'run' method, cannot be assigned another task. Here, on the first invocation of execute(), your AsyncTask started running and
after doing its job, the thread comes out of run. Naturally, next invocation of execute() will throw you exception.
The simplest way to run this more than once is to create a new instance of MyAsyncTaks and call execute on that.
MyAsyncTask myAsyncTask = new MyAsyncTaks();
myAsyncTask.execute(); // Works as expected
.
.
.
MyAsyncTask myAsyncTask2 = new MyAsyncTaks();
myAsyncTask2.execute(); // Works as expected
Though its not needed to be mentioned here, one must be aware that post Android SDK version Honeycomb, if your run more than one AsyncTask at once, they actually run
sequentially. If you want to run them parallally, use executeOnExecutor instead.
Just make a new call like new asyncTask().execute(); You must create a new object to restart that task.
I just create the asynctask then create a runnable that creates new instances of the asynctask. Then you can submit your runnable over and over again to the handler.
class MyAsyncTask extends AsyncTask<String, Void, String>{ ...}
Runnable myRunner = new Runnable(){
public void run() {
new MyAsyncTask ().execute(...);
}};
myHandler.post(myRunner);
This solved my problem:
public class MainActivity extends AnimationActivity {
MyAsyncTasks asyncTasks = new MyAsyncTasks();
#BindView(R.id.refresh_btn)
Button refreshBtn;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
setUnbinder(ButterKnife.bind(this)); // ButterKnife usage
syncTasks(); // run asyncTasks on activity start
refreshBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
syncTasks(); // run asyncTasks on button click
}
});
}
private void syncTasks() {
try {
if (asyncTasks.getStatus() != AsyncTask.Status.RUNNING){ // check if asyncTasks is running
asyncTasks.cancel(true); // asyncTasks not running => cancel it
asyncTasks = new MyAsyncTasks(); // reset task
asyncTasks.execute(); // execute new task (the same task)
}
} catch (Exception e) {
e.printStackTrace();
Log.e("MainActivity_TSK", "Error: "+e.toString());
}
}
}
You can do it like this :
private MyAsyncTask createAsyncTask(){
if (myAsyncTask == null){
return myAsyncTask = new MyAsyncTask();
}
myAsyncTask.cancel(true);
return myAsyncTask = new MyAsyncTask();
}
and then you can use it :
createAsyncTask().execute();
this make a new instance of your background task everytime.
Async tsk only run once as the Exceptions says the task has already been executed..
So you just have to make a new instance of async and then call .execute();
in order to run it again .. thank you
I created an Arraylist of type ProgressUpdater(Name of class which extends AsyncTask) and added the instances into it(in the onClick of a button). So you can execute and cancel these task when needed.
public class MainActivity extends Activity {
ProgressBar progress;
ProgressUpdater task;
ArrayList<ProgressUpdater> pu = new ArrayList<MainActivity.ProgressUpdater>();
int count = 0;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
progress = (ProgressBar) findViewById(R.id.progress);
}
public void onClick(View v) {
switch (v.getId()) {
case R.id.btn:
task = new ProgressUpdater();
pu.add(task);
count++;
pu.get(count - 1).execute(0);
System.out.println("task" + task);
// task.execute(10);
break;
case R.id.btnCancel:
if (count >= 0) {
pu.get(count - 1).cancel(true);
pu.remove(count - 1);
count--;
}
// task.cancel(true);
break;
}
}
#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;
}
private class ProgressUpdater extends AsyncTask<Integer, Integer, Void> {
#Override
protected void onPreExecute() {
// TODO Auto-generated method stub
super.onPreExecute();
progress = (ProgressBar) findViewById(R.id.progress);
progress.setMax(100);
}
#Override
protected Void doInBackground(Integer... params) {
// TODO Auto-generated method stub
int start = params[0];
for (int i = start; i <= 100; i++) {
try {
boolean cancelled = isCancelled();
if (!cancelled) {
publishProgress(i);
SystemClock.sleep(100);
}
} catch (Exception e) {
e.printStackTrace();
}
}
return null;
}
#Override
protected void onPostExecute(Void result) {
// TODO Auto-generated method stub
super.onPostExecute(result);
Log.v("Progress", "Finished");
}
#Override
protected void onCancelled() {
// TODO Auto-generated method stub
super.onCancelled();
progress.setMax(0);
}
#Override
protected void onProgressUpdate(Integer... values) {
// TODO Auto-generated method stub
super.onProgressUpdate(values);
progress.setProgress(values[0]);
}
}
}
in your MainActivity you can put so this:
LeoAsyncTask leoAsyncTaskGeneric;
public void onClick_AsyncTask(View view) {
LeoAsyncTask leoAsyncTaskInner = new LeoAsyncTask();
leoAsyncTaskInner.execute();
leoAsyncTaskGeneric=leoAsyncTaskInner;
}
/**if you create a space in memory of your AsyncTask class as a generic, then you can create an instance of that same class within the onClick method, and there the equals, so every time you press onClick you will be using a new instance of the Class AsyncTask, it will not give you problems
*/
You could cancel your asyncTask when you press the button and then execute it again.
Inside OnClic method:
asyncTask.cancel();
AsyncTask asyncTask = new AsyncTask();
asyncTask.execute();
#coder_For_Life22 I think am late for the answer ,anyway you can do like
#Override
protected void onPostExecute(Void a) {
myAsyncTask=new MyAsyncTask();
}
in order to start a new AsyncTask after execution :)
Related
This was asked in one of the Android interviews. I was asked whether it's possible to start another async task (let it be Task2) from doInBackground() method of async task 1(let it be Task1). I had gone through the docs which say the following:
The task instance must be created on the UI thread.
execute(Params...) must be invoked on the UI thread.
As per these statements, I think that it shouldn't be possible to start a task from background method of another task. Also, async task has UI methods (which cannot be used on a background thread), so that strengthened my argument and I answered it as not possible.
On checking on a simple demo app, I saw that it's indeed possible to do so.
Some demo code:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mContext = this;
init();
Log.v ("gaurav", "Thread is : " + Thread.currentThread().getName());
Task1 task = new Task1();
task.execute();
}
class Task1 extends AsyncTask {
#Override
protected Object doInBackground(Object... params) {
// TODO Auto-generated method stub
Log.v ("gaurav", "Thread task 1 is : " + Thread.currentThread().getName());
Task2 task = new Task2();
task.execute();
return null;
}
}
class Task2 extends AsyncTask {
#Override
protected Object doInBackground(Object... params) {
// TODO Auto-generated method stub
Log.v ("gaurav", "Thread task 2 is : " + Thread.currentThread().getName());
Log.v ("gaurav", "Task 2 started");
return null;
}
}
I get following logs indicating successful execution :
> 08-07 09:46:25.564: V/gaurav(2100): Thread is : main 08-07
> 09:46:25.564: V/gaurav(2100): Thread task 1 is : AsyncTask #3 08-07
> 09:46:25.564: V/gaurav(2100): Thread task 2 is : AsyncTask #4 08-07
> 09:46:25.564: V/gaurav(2100): Task 2 started
I have checked this on ICS, KK and L device and it works fine for all.
One reason I could think of is that I'm not overriding any UI methods and doing any UI updation in my second task, hence it doesn't cause any problems, but I'm not sure. Even if that's the case, it violates the threading rules mentioned in the developer guide.
As a reference, I checked out this link too : Start AsyncTask from another AsyncTask doInBackground() but the answer states to start the second task using runOnUiThread() method inside doInBackground().
I'd like some help on what's going on here. Thanks.
Let's change your code to the following:
class Task1 extends AsyncTask {
#Override
protected Object doInBackground(Object... params) {
// TODO Auto-generated method stub
Log.v ("gaurav", "Thread task 1 is : " + Thread.currentThread().getName());
Task2 task = new Task2();
task.execute();
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
Log.v ("gaurav", "Log after sleeping");
return null;
}
}
class Task2 extends AsyncTask {
#Override
protected Object doInBackground(Object... params) {
// TODO Auto-generated method stub
Log.v ("gaurav", "Thread task 2 is : " + Thread.currentThread().getName());
Log.v ("gaurav", "Task 2 Started");
return null;
}
}
Now the LogCat returns:
08-07 06:13:44.208 3073-3073/testapplication V/gaurav﹕ Thread is : main
08-07 06:13:44.209 3073-3091/testapplication V/gaurav﹕ Thread task 1 is : AsyncTask #1
08-07 06:13:49.211 3073-3091/testapplication V/gaurav﹕ Log after sleeping
08-07 06:13:49.213 3073-3095/testapplication V/gaurav﹕ Thread task 2 is : AsyncTask #2
08-07 06:13:49.213 3073-3095/testapplication V/gaurav﹕ Task 2 Started
As you can see the Task 2 is executed after the end of the Task 1 execution (even after sleeping for 5 seconds). It means the second task would not be started until the first one is done.
Why?
The reason is behind the source code of AsyncTask. Please consider the execute() method:
public synchronized void execute(final Runnable r) {
mTasks.offer(new Runnable() {
public void run() {
try {
r.run();
} finally {
scheduleNext();
}
}
});
if (mActive == null) {
scheduleNext();
}
}
and scheduleNext() method:
protected synchronized void scheduleNext() {
if ((mActive = mTasks.poll()) != null) {
THREAD_POOL_EXECUTOR.execute(mActive);
}
}
The most important keyword in these methods is synchronized which ensures these methods would be run only in one thread at the same time. When you call the execute method, it offers a new Runnable to mTask which is an instance of ArrayDeque<Runnable> class which works as a serializer of the different requests at different threads [more info]. If there was no executed Runnable (i.e. if (mActive == null)), the scheduleNext() would be called, otherwise, the scheduleNext() in the finally block would be called after the (for any reason) end of current executed Runnable. All Runnables are executed on a separate thread by THREAD_POOL_EXECUTOR.
What's wrong with the execution of AsyncTask from other threads? Starting with Jelly Bean, an AsyncTask is class-loaded at application start on the UI thread, so that the callbacks are guaranteed to occur on the UI thread, however, prior to the Jelly Bean release, if another thread creates the AsyncTask the callbacks may not occur on the correct thread.
So, AsyncTask implementations should be called from the UI thread only on platforms prior to Jelly Bean (+ and +).
Clarification: please consider the following example which simply clarifies the differences between different platform releases of Android:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main2);
new Thread() {
#Override
public void run() {
Task1 task = new Task1();
task.execute();
}
}.start();
}
class Task1 extends AsyncTask {
#Override
protected Object doInBackground(Object... params) {
return null;
}
}
It works fine on Android 5.1, but crashes with the following exception on Android 2.3:
08-07 12:05:20.736 584-591/github.yaa110.testapplication E/AndroidRuntime﹕ FATAL EXCEPTION: Thread-8
java.lang.ExceptionInInitializerError
at github.yaa110.testapplication.Main2Activity$1.run(Main2Activity.java:21)
Caused by: java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
at android.os.Handler.<init>(Handler.java:121)
at android.os.AsyncTask$InternalHandler.<init>(AsyncTask.java:421)
at android.os.AsyncTask$InternalHandler.<init>(AsyncTask.java:421)
at android.os.AsyncTask.<clinit>(AsyncTask.java:152)
at github.yaa110.testapplication.Main2Activity$1.run(Main2Activity.java:21)
public class MainActivity extends Activity {
private final static String TAG = "ThreadingAsyncTask";
private ImageView mImageView;
private ProgressBar mProgressBar;
private int mDelay = 500;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mImageView = (ImageView) findViewById(R.id.imageView);;
mProgressBar = (ProgressBar) findViewById(R.id.progressBar);
final Button button = (Button) findViewById(R.id.loadButton);
button.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
new LoadIconTask().execute(R.drawable.cheetah);
}
});
final Button otherButton = (Button) findViewById(R.id.otherButton);
otherButton.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
Toast.makeText(MainActivity.this, "I'm Working",
Toast.LENGTH_SHORT).show();
}
});
}
class LoadIconTask extends AsyncTask<Integer, Integer, Bitmap> {
#Override
protected void onPreExecute() {
mProgressBar.setVisibility(ProgressBar.VISIBLE);
}
#Override
protected Bitmap doInBackground(Integer... resId) {
Bitmap tmp = BitmapFactory.decodeResource(getResources(), resId[0]);
// simulating long-running operation
for (int i = 1; i < 11; i++) {
sleep();
publishProgress(i * 10);
}
return tmp;
}
#Override
protected void onProgressUpdate(Integer... values) {
mProgressBar.setProgress(values[0]);
}
#Override
protected void onPostExecute(Bitmap result) {
mProgressBar.setVisibility(ProgressBar.INVISIBLE);
mImageView.setImageBitmap(result);
}
private void sleep() {
try {
Thread.sleep(mDelay);
} catch (InterruptedException e) {
Log.e(TAG, e.toString());
}
}
}
}
I have an AsyncTask inside a fragment, which is being executed every second using a Timer. The AsyncTask loads data into a ListView, and when the user clicks on a ListView item, it switches to another fragment.
The timer doesn't stop, so it keeps executing itself and finally, gives me an error when it tries to load the data into the ListView.
I already tried looking for answers, and have implemented those in my code-
class HttpGetAsyncTask extends AsyncTask<String, String, String> {
#Override
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected void onCancelled() {
Log.d("PORTS Cancelled","cancelled");
}
#Override
protected String doInBackground(String... q) {
String v = null, c = null;
for(int countervar=0;countervar<1;countervar++){
if(load.isCancelled())
break;
//All my code here
}
return c;
}
protected void onPostExecute(String result) {
if(isCancelled()||!isAdded()){
return;
}
else{
SimpleAdapter adapter = new SimpleAdapter(getActivity(),
ports, R.layout.playout, new String[] { "name",
"code", "type" }, new int[] { R.id.portn, R.id.portc,
R.id.portv });
adapter.notifyDataSetChanged();
lv.setAdapter(adapter);
}
}
}
#Override
public void onPause() {
super.onPause();
timer.cancel(); //timer is the name of the Timer
doAsynchronousTask.cancel(); //doAsynchronousTask is the TimerTask
if(load!=null) //load is the AsyncTask
if(!load.isCancelled())
load.cancel(true);
}
#Override
public void onDestroy() {
super.onDestroy();
timer.cancel();
doAsynchronousTask.cancel();
if(load!=null)
if(!load.isCancelled())
load.cancel(true);
}
The timer (Called in onCreateView)-
handler = new Handler();
doAsynchronousTask = new TimerTask() {
#Override
public void run() {
handler.post(new Runnable() {
public void run() {
try {
load = new HttpGetAsyncTask();
load.execute();
} catch (Exception e) {
// TODO Auto-generated catch block
}
}
});
}
};
timer.schedule(doAsynchronousTask, 0, 10000);
Please let me know where I'm going wrong and what I can do to fix this problem. Thanks.
When the doAsynchronousTask task is scheduled the load variable is replaced with a new HttpGetAsyncTask. So more than one AsyncTask can run a the same time, and when you stop the task, calling:
load.cancel(true);,
you are only cancelling the AsyncTask referenced by load variable, but others tasks can continue to work in backgroud (without any handle for stopping them).
A solution can be, to stop the AsyncTask before start another one.
What about adding a boolean flag in the loop as the condition controlling the loop?
Then you can set it to false to stop the task in onPause()
In my acivity, i need to run two background service.
main background service:
class loadingTask extends AsyncTask<Void, Void,Void> {
#Override
protected void onPreExecute() {
// TODO Auto-generated method stub
pd = ProgressDialog.show(context, "", "Chargement en cours..", true, false);
super.onPreExecute();
}
#Override
protected void onPostExecute(Void result) {
// TODO Auto-generated method stub
super.onPostExecute(result);
pd.dismiss();
}
...
#Override
protected Void doInBackground(Void... params) {
// TODO Auto-generated method stub
getxml = Util.CallWebService("");
return null;
}
}
Second background service.
class mloadingTask extends AsyncTask<String, Void, String> {
protected String doInBackground(String... urls) {
SAXHelper sh = null;
try {
sh = new SAXHelper(urls[0]);
} catch (MalformedURLException e) {
e.printStackTrace();
}
sh.parseContent("");
return "";
}
protected void onPostExecute(String s) {
pd.dismiss();
}
}
In my onCreate() method I want to call the first background and when it finished loading the second background service starts. Part of my background service is as follows.
AsyncTask<Void, Void,Void> loadTask = new loadingTask().execute();
if(loadTask.getStatus()==AsyncTask.Status.FINISHED){
new mloadingTask().execute(getxml);
System.out.println("getxml: "+getxml);
}
However the second background service doesn't seem to start. i am not getting the a print also. I think I miss a step or android doesn't allow more than one background service in the same activity. A help please.
AsyncTask<Void, Void,Void> loadTask = new loadingTask().execute();
if(loadTask.getStatus()==AsyncTask.Status.FINISHED){
new mloadingTask().execute(getxml);
System.out.println("getxml: "+getxml);
}
there is a 99% chance that the if() block will never pass.
You first execute the first asyncTask named loadTask and RIGHT after check if it finished.
Small chance that it actually finishes by then.
The easy approach:
Use only one async task. You want to finish asyncTask 1 and then fire asyncTask 2, its exactly the same as having only one asyncTask doing both operations.
class loadingTask extends AsyncTask<Void, Void,Void> {
#Override
protected void onPreExecute() {
// TODO Auto-generated method stub
pd = ProgressDialog.show(context, "", "Chargement en cours..", true, false);
super.onPreExecute();
}
#Override
protected void onPostExecute(Void result) {
// TODO Auto-generated method stub
super.onPostExecute(result);
pd.dismiss();
}
...
#Override
protected Void doInBackground(Void... params) {
// TODO Auto-generated method stub
getxml = Util.CallWebService("");
SAXHelper sh = null;
try {
sh = new SAXHelper(urls[0]);
} catch (MalformedURLException e) {
e.printStackTrace();
}
sh.parseContent("");
return null;
}
}
The difficult approach:
How I solve this kind of thing is(our situation is different, but it should do)
Create an interface, with one method. for example:
public interface OnDataChangedListner {
void dataChanged(Class listener);
}
Then somewhere (i use my repository classes)
write a method to add and remove entires to a list of OnDataChangedListener interfaces
private ArrayList<OnDataChangedListner> mOnDataChangedListners;
public void addOnDataChangedListner(OnDataChangedListner onDataChangedListner){
synchronized (mOnDataChangedListners){
mOnDataChangedListners.add(onDataChangedListner);
}
}
public void removeOnDataChangedListner(OnDataChangedListner onyDataChangedListner){
if (mOnDataChangedListners != null){
synchronized (mOnDataChangedListners){
for (Iterator<OnDataChangedListner> it = mOnDataChangedListners.iterator(); it.hasNext();) {
OnDataChangedListner listener = it.next();
if (listener .equals(onDataChangedListner))
it.remove();
}
}
}
}
This might be overkill. But this example should help you with updating the UI while your tasks are running. A free extra! :))
With the above code in place, create an onDataChanged() method in the same class where u defined the add and remove listener methods.
In that code call a handler
// Need handler for callbacks to the UI thread
final static Handler mHandler = new Handler();
// Create runnable for posting
final Runnable mNotifyDataChanged = new Runnable() {
public void run() {
if (mOnDataChangedListners != null){
synchronized (mOnDataChangedListners){
for (Iterator<OnDataChangedListner> it = mOnDataChangedListners.iterator(); it.hasNext();) {
OnDataChangedListner listener = it.next();
if (listener != null)
listener.dataChanged(this.getClass());
else
it.remove();
}
}
}
}
};
/**
* will notify registerred delegates on the main (UI) thread
*/
public void notifyDataChanged(){
mHandler.post(mNotifyDataChanged);
}
Ok, so I ended up giving out an entire sample.
Where you place this code is upto you. But when you call notifyDataChanged() it will fire the handler, which in turn will loop trough all current registered listeners for this class
then in turn it will call the listeners datachanged method.
To make this all work, all you have to do is have a class implement the interface
call addOnDataChangedListener(this);
and implement the method provided in the interface.
Note that this is deffinetly not the easiest way to do things.
I don't know what the easiest way to do what you want is. I never have been in that situation before.
but you can execute the second task in the implemented method. Should work..
AsyncTask is Asynchronous as its name suggest. You need to call your 2nd AsyncTask in onPostExecute of your 1st AsyncTask
OR
Loop and wait till AsyncTask is finished in your activity, but it may take more time and you can get Application Not Responding message.
As soon as you call execute() method, control comes to next statement which loadTask.getStatus(). As task is just started, loadTask.getStatus() will not return FINISH and your 2nd task is never getting executed.
I want to make a test app, that when called, execute a few lines of code, and then exit automatically. I want all these done within onCreate().
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
System.out.println("onCreate()");
try {
initSocket(); //connect to server
} catch (IOException e) {
e.printStackTrace();
}
new Thread(new AudioRecordThread()).start();
}
The problem is, how can I exit the app in onCreate()? I tried "this.finish()" but didn't work.
Any one can help?
EDIT
I agree that the problem may be caused by thread. Will post my answer when solved.
I think the Problem is your AudioRecordThread which shares the same Process with your App. You could definetly call this.finish() inside onCreate (done this often, never had problems), but that doesn't mean neccesarily that your AudioRecordThread gets killed the same time as your Activity. So without further Information about your Thread, and if it should stay alive on finish of your Activity I cannot give you any advise. If You want that Thread to be alive, after your Activity finishes, a Service is the way to go.
try
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
System.out.println("onCreate()");
try {
initSocket(); //connect to server
} catch (IOException e) {
e.printStackTrace();
}
new Thread(new AudioRecordThread()).start();
finish();
}
Perhaps what you are trying to do is a service?
Have a look here: http://developer.android.com/reference/android/app/Service.html
try this one
finish is working in onCreate() & onResume().. there is another problem in your code
#Override
protected void onResume()
{
super.onResume();
finish();
}
You can use an AsynTask in your activity, juste put this class in the Same file of your activity
=> In onPostExecute() methode you will test if your handling is finished to close your activity.
class MyAsynTask extends AsyncTask<Void, Integer, Boolean> {
#Override
protected void onPreExecute() {
// TODO Auto-generated method stub
super.onPreExecute();
// Init your variables, in my case it's my Progress Bar
myprogress = new ProgressDialog(mcontext);
myprogress.setTitle("Update");
myprogress.setMessage("Update running ....");
myprogress.show();
}
#Override
protected Boolean doInBackground(Void... params) {
// TODO Auto-generated method stub
boolean test = false;
int j = 0;
for (int i = 0; i < 50; i++) {
j = i + 10;
publishProgress(i);
// Your implemention code to connect to the server
if (i == 49)
test = true;
}
return test;
}
#Override
protected void onProgressUpdate(Integer... values) {
// TODO Auto-generated method stub
super.onProgressUpdate(values);
myprogress.setProgress(values[0]);
}
#Override
protected void onPostExecute(Boolean result) {
// TODO Auto-generated method stub
super.onPostExecute(result);
if (myprogress.isShowing())
myprogress.dismiss();
if (result){
Toast.makeText(mcontext, "I Finished",Toast.LENGTH_SHORT).show();
yourActivity.this.finish();
}
}
}
Ok this is a very weird problem I am having, and I'm pretty sure that I am messing up somewhere, but I can't quite figure out where.
What I am trying is -
Schedule a Timer to execute a TimerTask every five seconds
The TimerTask in turn executes an AsyncTask (which in this case simple sleeps for a second before returning the static count of the number of AsyncTasks).
Finally, the aforementioned count is updated in the UI.
And of course, the appropriate Handlers and Runnables have been used to post asynchronous messages from other threads to the UI.
This code executes only once. I expect it to fire every 5 seconds. Here's the code.
Note: I had no idea what to do with the Looper. I put it there after trial and error!
public class TimerAsyncMixActivity extends Activity {
public static final String TAG = "TimerAsyncMix";
static int executionCount = 0;
Handler mHandler = new Handler();
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
new Timer().schedule(new MyTimerTask(this), 0, 5000);
}
class MyAsyncTask extends AsyncTask<String, Void, Integer>{
#Override
protected Integer doInBackground(String... params) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return ++executionCount;
}
#Override
protected void onPostExecute(Integer result) {
mHandler.post(new UpdateUiThread(TimerAsyncMixActivity.this, result));
super.onPostExecute(result);
}
}
}
class MyTimerTask extends TimerTask{
private TimerAsyncMixActivity tma;
public MyTimerTask(TimerAsyncMixActivity tma) {
this.tma = tma;
}
#Override
public void run() {
Looper.prepare();
Log.d(TimerAsyncMixActivity.TAG, "Timer task fired");
tma.new MyAsyncTask().execute();
Looper.loop();
Looper.myLooper().quit();
}
}
class UpdateUiThread implements Runnable{
int displayCount;
TimerAsyncMixActivity tma;
public UpdateUiThread(TimerAsyncMixActivity tma, int i) {
this.displayCount = i;
this.tma = tma;
}
#Override
public void run() {
TextView tv = (TextView) tma.findViewById(R.id.tvDisplay);
tv.setText("Execution count is : "+displayCount);
}
Can anyone point me to what I'm doing wrong?
techie, this is how I implemented similar things. I'm won't claim that this is the best way, but it has worked for me and doesn't look too bad.
I have the following code in my activity. I create an async task when the activity starts and I stop it onPause. The AsyncTask does whatever it needs to do, and updates the UI on onProgressUpdate() (which is run on the UI thread, so there's no need to use a Handler).
private Task task;
#Override
protected void onPause() {
task.stop();
task = null;
}
#Override
protected void onResume() {
task = new Task();
task.execute();
}
private class Task extends AsyncTask<Void, String, Void> {
private boolean running = true;
#Override
protected Void doInBackground(Void... params) {
while( running ) {
//fetch data from server;
this.publishProgress("updated json");
Thread.sleep(5000); // removed try/catch for readability
}
return null;
}
#Override
protected void onProgressUpdate(String... values) {
if( ! running ) {
return;
}
String json = values[0];
//update views directly, as this is run on the UI thread.
//textView.setText(json);
}
public void stop() {
running = false;
}
}
Do not use a timer. If your phone goes to sleep, the timer is suspended too. Use AlarmManager.