I'm currently have an Android application with 3 activities.
Main activity:
Constantly polling a Xml file using AsyncTask and update UI using onPostExecute.
The AsyncTask is loop by:
Handler.postDelayed(runnableCode, Poll_internval);
Second Activity:
Does the same thing, pulling Xml using another AsyncTask and update UI using onPostExecute.
loop by :
Handler.postDelayed(runnableCode, Poll_internval);
How should i kill the AsyncTask as it is constantly looping?
Would like to kill it when ending this activity with finish();
There is no way to cancel the AsyncTask, even with cancel method.
You need to implement your logic for canceling the task manually, see this link :
How to completly kill/remove/delete/stop an AsyncTask in Android
You can use like:
Asyn mAsyn = new Asyn();
mAsyn.execute();
if(mAsyn.isCancelled()){
mAsyn.cancel(true);
}
There is provision,
you can remove async task in call back in handler, there is method
handler.removeCallbacks(runnable);
In Asynctask there is status, you have to develop logic and check status code.
AsyncTask statuc
In my project, i have same condition and i developed this kind of logic, it work in my code.
please check it.
Have a look at the androidannotations framework, that has support for running async tasks and also cancelling them. You can checkout the details here:
https://github.com/excilys/androidannotations/wiki/WorkingWithThreads#background]
Basically, all you need to do is annotate the method that needs to run in another thread with
#Background(id="cancellable_task")
void someCancellableBackground(String aParam, long anotherParam) {
[...]
}
where "id" is the id of the new thread. Then, to cancel it you just call
BackgroundExecutor.cancelAll("id");
Related
I have created an App which requires to run a operation in background for quite some time suppose 10 - 15 mins.
I am running this operation in An AsyncTask. So during this time the user is minimizing the Screen and using his other apps in his phone as usual.
When this operation is started I am creating a Progress Dialog box and then keep updating it regularly.
But this is the error which I am receiving sometimes very rarely once the operation is over
Fatal Exception: java.lang.IllegalArgumentException
View=DecorView#1234567[ABC:] not attached to window manager PackageName
And this is the detailed stack log
Fatal Exception: java.lang.IllegalArgumentException
View=DecorView#1234567[ABC:] not attached to window manager PackageName
at android.view.WindowManagerGlobal.findViewLocked(WindowManagerGlobal.java:508)
at android.view.WindowManagerGlobal.removeView(WindowManagerGlobal.java:417)
at android.view.WindowManagerImpl.removeViewImmediate(WindowManagerImpl.java:136)
at android.app.Dialog.dismissDialog(Dialog.java:446)
at android.app.Dialog.dismiss(Dialog.java:429)
at android.app.Dialog.cancel(Dialog.java:1353)
at PACKAGENAME
at android.app.Activity.runOnUiThread(Activity.java:6078)
at PACKAGENAME
at PACKAGENAME
at android.os.AsyncTask.finish(AsyncTask.java:667)
at android.os.AsyncTask.-wrap1(AsyncTask.java)
at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:684)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6823)
at java.lang.reflect.Method.invoke(Method.java)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1557)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1445)
To my knowledge this error is because the Android OS wanted to release some memory hence my App was closed since this was not visible to the user. But is there any way to tackle this thing?
Any help would be really appreciated.
EDIT: This is the code which I am using
public class load extends AsyncTask<Void, Void, Void> {
#Override
public Void doInBackground(Void... voids) {
for(int i=0;i<number;i++){
PerformSomeOperation();
UpdateTheProgress();
}
return null;
}
#Override
protected void onPostExecute(Void n) {
runOnUiThread(new Runnable() {
#Override
public void run() {
mProgressDialog.cancel();
CreateAnotherDialog();//This dialog is created to show the user completion of the progress.
}
});
}
You're having this crash because you're trying to update the UI when it's in the background so your Activity could be destroyed at that point. By the way, onPostExecute runs your code on the main thread already but as you're sending a separate message to the main looper you're postponing your logic a bit which can also cause a problem. Moreover, But the main question - why to update the UI if it's not visible to the user anyways?
Also, because you're using the AsyncTask as an inner class you may leak (though temporarily) your Activity object as it's referenced implicitly by the task.
From Android Documentation:
AsyncTasks should ideally be used for short operations (a few seconds
at the most.) If you need to keep threads running for long periods of
time, it is highly recommended you use the various APIs provided by
the java.util.concurrent package such as Executor, ThreadPoolExecutor
and FutureTask.
So, don't use AsyncTasks for long-running operations. A better approach would be to use:
IntentService together with BroadcastReceiver to communicate with your Activity / Fragment (in API >= 26 you should use JobIntentService as IntentService may misbehave due to new restrictions on background services).
RxAndroid (or just ExecutorService/Thread) together with Architecture-Components (more specifically with LiveData) - this way a result of your task can be cached or it can survive the config change.
My personal favourite is option 2.
There are few things to say: (1) the "onPostExecuted()" method is already executed on the UiThread/MainThread, so "runOnUiThread()" is not required. (2) if the Activity is minimized/destroyed when the Asynctask reach the final pass you get an Exception. So you have to check if the View is attached using "View. IsAttachedToWindow()" before execute some GUI methods like "mProgressDialog.cancel()". (3) you have to create a Thread or a Service to do a task that should run/work more than few seconds, or the System could kill it at anytime.
I am running a 20 second timer in the background of my app using a service. I want the service to call my GameOver class when it is done with it's timer. By the way, the user is constantly switching activities while the timer is running, but when it finishes, the user has to be taken to the game over screen no matter what. I have put a toast in the service, but that doesn't show up.
Here is my service:
Here is my Main Menu where I call the service:
Here is the manifest where I show the service:
Please let me know as to why the service or the timer aren't running. Thank you so much for all of your help, I really appreciate it! If you need any more code, just let me know and I will show you. Thanks!
:-)
Your toast is not showing because a Service can't directly manipulate the UI, such as showing toasts.
To do this from a service, you need to run the Toast code on the main thread. This can be done as such:
Handler handler = new Handler(Looper.getMainLooper());
handler.post(new Runnable() {
#Override
public void run() {
Toast.makeText(TwentySeconds.this.getApplicationContext(), "Started!", Toast.LENGTH_SHORT).show();
}
});
Your CountDownTimer isn't working because you never start it. Very simple.
You create the CountDownTimer, but never call .start() on the object.
cdt.start();
After a few hours on this issue, I figured out my pathetic error:
I had the service declaration OUTSIDE of the '< application>' end tag.
facepalm
ALWAYS keep service declarations inside of tag
I'm looking for a way to close an android app after some time while the app has not been in focus. For example if the user open up an other app instead, the app should exit after 5 mins. I have tried using runnable and creating a thread. But those method don't seems to work while the app is in the background (maybe they are pause I'm not sure). So how do I close the app when it is not in focus?
For those who are wonder the reason I want to do this is that the app contains some sensitives data about the user so I want to be sure it is all cleared when they aren't using it.
Something like this might work:
A field inside activity class:
private Thread t = null;
Inside onResume():
if(t!=null) {
if(t.isAlive()) {
t.interrupt();
t.join();
}
t=null;
}
Inside onPause():
t = new Thread() {
public void run() {
try {
sleep(5*60*1000);
// Wipe your valuable data here
System.exit(0);
} catch (InterruptedException e) {
return;
}
}.start();
}
I recommend calling finish() in the onPause() or onStop() callbacks. A TimerTask will not survive onPause() and a Service does not appear, on face value, to give you options. Maybe you can start a service, sleep the thread the service runs on, then kill the processes your app has after the sleep timer expires.
Alternatively, you can just implement some security libraries to help secure the data from other apps.
Here is the Google Services link.
Get the process ID of your application, and kill that process onDestroy() method
#Override
public void onDestroy()
{
super.onDestroy();
int id= android.os.Process.myPid();
android.os.Process.killProcess(id);
}
Refer- how to close/stop running application on background android
Edit- Use this with AlarmManager
The fundamental problem with what you're trying to do is that your Activity may not exist in memory at all when it's "running" in the background. The Android framework may have destroyed the activity instance and even the process it was running in. All that exists may be the persistent state you saved in onSaveInstanceState(...) and a screenshot for the recent apps list. There may be nothing for you to get a reference to and kill.
Frank Brenyah's suggestion to call finish() in onPause() will prevent your activity from running in the background at all, but this is the closest you can get to what you want. You probably only want to do this when isChangingConfigurations() is false. But even when all your app's activities are finished, Android may keep the process and Application instance around to avoid recreating them later. So you may also want to use Bhush_techidiot's suggestion of killing the process. Do this in onPause() because the activity may be destroyed without a call to onDestroy().
I want to use AsyncTask for update my db4o with a server. In the doInBackground method , I connect to the server, update the db4o, and schedule a pendingintents. Not modify UI or show any toast.
Initially, I had the following error:
Can't create handler inside thread that has not called Looper.prepare()
After adding the Looper.prepare(), works fine, but only for five updates (AsyncTask). I've read this topic: AsyncTask threads never die (Android) , and I don't now that fails. When I throw the sixth update, the app crashes:
FATAL EXCEPTION: AsyncTask #1
java.lang.RuntimeException: An error occured while executing doInBackground()
at android.os.AsyncTask$3.done(AsyncTask.java:200)
at java.util.concurrent.FutureTask$Sync.innerSetException(FutureTask.java:274)
at java.util.concurrent.FutureTask.setException(FutureTask.java:125)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:308)
at java.util.concurrent.FutureTask.run(FutureTask.java:138)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1088)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:581)
at java.lang.Thread.run(Thread.java:1019)
Caused by: java.lang.RuntimeException: Only one Looper may be created per thread
at android.os.Looper.prepare(Looper.java:74)
(...)
I've read in the documentation that I need the Looper.loop(), but whith this, the app crashes..
Example:
protected Integer doInBackground(Void... params) {
Looper.prepare();
update = new Update();
update.checknewObjects();
update.deleteOldObjects();
update.updateObjects();
Looper.loop();
}
Why do I need Looper?
Why the app crashes after five updates?
Where can I schedule Looper.loop()?
Thanks in advance!
If you want to use AsyncTask so use it, you shouldn't mix it with Lopper...
protected Integer doInBackground(Void... params) {}
already working on background thread and there is no reason to call Lopper, for what?
If your application need to do some kind of long computation so AsyncTask is very good tool for it because offers methods which working on UI Thread and allow to update UI with some progress of work because every User that will use your application should know that application "doing something" (when it takes more than 2-5 seconds).
Also it's generic and that provide some benefits.
If you do not need to update UI just use for example Handler.
If you want to schedule tasks you should use Timer & TimerTask, from what I understand I think they should fit better to your needs.
http://developer.android.com/reference/java/util/Timer.html
in asynck Task you can't use looping in background function .it giving error
My application has one service which runs until user pressed exit button. I know giving exit button in android is not good design but in my application it is desired.
In my application I also have a thread to send Http request, download a file and then parse it in background so that UI will not block. In my thread's run method there are sequential steps (like download a file, then parse it), there is no while or for loop in it.
When user presses exit button, is there any way to stop the background thread if it is running without kill process (using Process.kiil(pid) or System.exit(0)) ?
I have tried AsyncTask also. Whatever in run method of thread, i put it in doInBackground method. When user presses exit button i have canceled asynctask. Cancelling task not stop the background thread completely because after file download it will go in parser to parse the file (i.e. parsing is done in background thread but it at the time of parsing it is not in doInBackground or run method. It will in parsing method of parser class or in Default handler class for parsing.)
From googling I read many blogs and other stackoverflow questions about thread but still I cannot find any solution for it.
Please help....thanks in advance..
before each step you could add a line like
if(stillRunning){
//next step
}
and when you want it to stop, you just set stillRunning to false.
(1) use this to stop application instead of exit
finish();
Intent intent = new Intent(Intent.ACTION_MAIN);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
intent.addCategory(Intent.CATEGORY_HOME);
startActivity(intent);
(2) use new Thread instead of asynk task which you can stop by calling stop method
Thread myThread = new Thread ()
{
public void run()
{
Looper.prepare();
doMyWork();
}
}.start();
and call stop on myThread
Probably, your connection and parser use same InputStream. If you quit, try to close the stream and a connection. In that case, some kind of Exception will be thrown and background thread will finish job with error but very fast. If you are in the middle of file saving, you must check every write(buffer) if you are canceled or try to close FileOutputStream.
Stop thread at instance (when exit event occurred from UI) is not possible without using
Process.killProcess(Process.myPid());