I have an activity which has a button. Clicking on the button will start an asynctask and shows a progress loader on the activity.
This asynctask has some things to do but before that it has to make sure all the IntentServices of the app are finished handling intents from their queue.
I approached this problem by creating a lock object as below.
public class Lock{
private boolean isLocked = false;
public synchronized void lock()
throws InterruptedException{
while(isLocked){
wait();
}
isLocked = true;
}
public synchronized void unlock(){
isLocked = false;
notify();
}
}
An intent Service which is doing something will create an instance of Lock. It holds the lock in a public static field so that others can access it. It will call lock on the object above in onCreate() and will call unlock in onDestroy(). The asynctask will call lock on the same Lock object.
The expectation here is that my asynctask will wait till unlock() is called on the Lock object in onDestroy() of the service.
But the problem I am facing is that onDestroy() is never called on the IntentService. Android throws anr as ANR in <pkg> Reason: Executing service.
Can someone point out the problem in my understanding and implementation?
Related
I want to stop my thread when my app closes. Does any one know how can I do this?
public class ControlApplication extends Application
{
private static final String TAG=ControlApplication.class.getName();
private Waiter waiter; //Thread which controls idle time
private MySharedPrefrences prefs;
// only lazy initializations here!
#Override
public void onCreate()
{
super.onCreate();
Log.d(TAG, "Starting application" + this.toString());
Context ctx=getApplicationContext();
waiter=new Waiter(1*60*1000,ctx);//(1*60*1000); //1 mins
prefs=new MySharedPrefrences(this);
// start();
}
#Override
public void onTerminate() {
super.onTerminate();
Log.d(TAG,"App terminated");
prefs.SetLastVisitedActivity("");
waiter.stopThread();
waiter.loginUpdate(false);
}
}
I want to call some methods when app terminates but I can't seem to get it working. Any suggestion please?
Try calling super.onTerminate(); after stopping the thread, i.e.,
#Override
public void onTerminate() {
Log.d(TAG,"App terminated");
prefs.SetLastVisitedActivity("");
waiter.stopThread();
waiter.loginUpdate(false);
super.onTerminate();
}
Update: onTerminate will never work on a device. http://developer.android.com/reference/android/app/Application.html#onTerminate%28%29
This method is for use in emulated process environments. It will never be called on a >production Android device, where processes are removed by simply killing them; no user code >(including this callback) is executed when doing so.
So your best bet is to create a base activity and let all other activities extend it. You can use onPause() of an Activity but if the app is terminated then there is no guarantee unless you call finish().
Update: As Nasir said in one of the comments, using onPause is not a good idea.
If your application has only one entry point then in your home/first activity override onDestroy() method, and from that method stop the thread.
How to close an activity correctly with all cords?
I have an activity that uses multiple synchronous and asynchronous threads and end with and ended with "finish ()". But still open because some listeners (eg call) are listening.
A simple example is the following code:
...
test=new Timer();
test.schedule(new TimerTask(){
// #Override
public void run(){
countTime++;
System.out.println("time es -> " + countTime);
}
},1,1000);
...
I make a MainScreen.this.finish() and does not appear visually, but the meter still running.
How I can end the activity at all?
Call cancel() on your Timer in onDestroy() of the activity. Or, call cancel() on your Timer sooner than that (e.g., onPause()). Your use of your Timer needs to be intelligently tied to the activity lifecycle.
You have to stop the thread in the onStop() (or onPause()) method of your activity by using mThread.join().
This could look like this:
Thread mThread;
boolean isRunning;
#Override
public void onStop(){
isRunning = false;
try {
mThread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
If you have a lot of threads to stop, you could store them in some kind of a list and iterate through this list and join() each thread.
I have a Service like this (this is not the actual Service, it's just for describing my problem).
public class UploadService {
private BlockingQueue<UploadData> queue = null;
private UploadInfoReceiver receiver = null;
public void onStart(...) {
queue = new LinkedBlockingQueue<UploadData>();
(new Processor()).start();
// creating and reigtering receiver
}
public void onDestroy() {
queue.add(new ServiceDestroyedData());
// unregistering the receiver
}
private class Processor extends Thread() {
public void run() {
while (true) {
UploadData data = queue.take();
if (data instanceof ServiceDestroyedData) {
return;
}
// processing data
}
}
}
private class UploadInfoReceiver extends BroadcastReceiver {
public void onReceive(Context context, Intent intent) {
queue.add(new UploadData(/* getting data from intent */));
}
}
}
And my problem is that if I do something like this in my App:
if (!isUploadServiceRunning()) {
// start the Service
}
Then it starts the Service, but when I move my App to the background and open task manager (android 4.2.2), and kill the app, Android restart my Service, and I can see that it creates a whole new instance of it, and I can see that onDestroy never gets called for the previous Service instance. And I also can see that the instance of the previous Processor Thread is no longer running. How can this be? If onDestroy never gets called how does Android know that it should stop my Thread?
Thanks for your answers.
Android will kill off anything that it finds that is attached to your apps classloader when you select force stop from the menu. Think kill -9 on Linux. There will be no nice callbacks to any onDestroy methods, the system will just end everything.
Now for your service:
while(true) should really NEVER be used. It will instantly kill the battery and will not do any work 99% of the time anyway.
You area already using a receiver, you can just put your while logic into there and once the upload is done call the next upload and so on. There is absolutely no need for the loop.
I just need to stop a thread which was created in previous run time of the same application. This is the scenario. I'm retrieving data from database for the notification using thread in background, But when I start that application again, number of threads are increasing. I need to stop this. I think its better to stop the background running thread in onCreate() method of the application's main class. But noway to do it. Please help me on this thing as soon as possible.
Thanks and Best Regards,
Shehan.
Keep a static reference to the running Thread in your activity class. Inside your thread you need to have a boolean variable you can set or a method you can call that will cause your thread to complete. In onCreate() you can check if you have a running thread, and if so, tell it to stop. Here's a code example:
In your activity:
private static Thread myThread;
In your activity, when you create the thread:
if (myThread != null) {
if (myThread.isAlive()) {
myThread.running = false; // Tell the thread to stop running now
}
}
myThread = new Thread(...);
myThread.start();
In your thread:
public boolean running = true; // Initator of this thread should set this to false to make the thread complete
public void run() {
while (running) {
// do whatever your thread does in a loop
}
}
You can stop the ruuning threads onDestroy() of activity.
please find the below eg:
static boolean stopThread=false;
public myThread implements Ruunable{
public void run(){
while(true){
//your logic
if(stopThread)
break;
}
}
#Override
protected void onDestroy()
{
stopThread=true;
}
I created a Thread inside an Activity. At first, i thought that when onDestroy() is called on the Activity, then the thread will be killed also. But i was wrong. The Thread still continued running.
So i decided to cancel the thread inside the onDestroy() method. Everything works fine.
But there's 1 problem : onDestroy() is not guaranteed to be called. For example : the Activity is killed abruptly by the OS.
So what's the best thing to do in this case ? Thanks.
You should do everything related to cleanup in onPause(). You're correct that onDestroy() won't always be called, but onPause() is always called when activity moves to background or gets killed. But be careful to make your code in this method really lightweight, because an activity can't go to the background until this method returns.
I would propose to place Thread killing in Application onTerminate method
public class MyApplication extends Application
{
MyThread myThread;
#Override
public void onCreate()
{
super.onCreate();
myThread=new MyThread();
myThread.start();
}
#Override
public void onTerminate ()
{
super.onTerminate();
myThread.interrupt();
}
}
Be sure to declare MyApplication in AndroidManifest.xml