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.
Related
Checked the log for it.. onDestroy() method gets called instead of onHandleIntent()
i am using two intent services, and have written similar code for both... but one runs all the time but for the second intentService(code attached)...sometimes it runs and sometimes it doesn't without changing anything in the whole project.
can anyone please help?
public class GetDataService extends IntentService {
private static final String TAG="GetDataService";
public GetDataService(){
super("GetDataService");
}
#Override
protected void onHandleIntent(Intent intent) {
GetDataTask task= new GetDataTask();
Log.d(TAG,intent.getStringExtra(GetDataTask.INSTA_TOKEN_URL));
task.execute(this,intent);
ApplicaitonsData.GetDataServiceRunning=true;
Log.d(TAG,"data service running status = "+ ApplicaitonsData.GetDataServiceRunning);
}
#Override
public void onDestroy() {
super.onDestroy();
ApplicaitonsData.GetDataServiceRunning=false;
Log.d(TAG,"data service running status = "+ApplicaitonsData.GetDataServiceRunning);
}
}
the task.execute() method in code had a if loop in it and the condition was false. so there wasn't anything for the IntentService to do..therefore it was destroying itself.
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?
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.
is the order of a broadcast intent guaranteed? that is, if i do,
sendBroadcast(intent1);
sendBroadcast(intent2);
are the receivers guaranteed to get intent1 before intent2? i suspect the answer to this is no, but in that case, i'm not quite sure how to solve my problem.
i'm trying to create a "busy" indicator for my app that shows busy when the device is talking on the network, and then goes away when the network communication is done. all network communication happens in an intent service.
my attempt at this was to send a BUSY_START intent when i begin network communication in the service, and a BUSY_STOP when network communication ends. this seems to mostly work, but i'm finding occasionally that i get the stop and start messages out of order.
is there a better way to solve this problem?
i'm thinking of adding an ID to each busy intent, so they can be paired. that way if i receive a start for which i've already received a stop, i can ignore it. or, perhaps more simply, add an integer sequence number into each broadcast. if i ever receive a broadcast for which the sequence of the current intent is less than the sequence of the last received intent, ignore it.
Have you considered using a Handler object to communicate from the background thread in the IntentService? The advantage of a Handler over the BroadcastReciver approach is that the Handler uses a message queue to sequence the Message objects.
(I'm assuming your Service is in the same process as the app's main thread).
At least one viable alternative to intents is to execute messaging through the application class, i.e.,
create a listener interface
Manager a collection of listener objects in the application / provide methods to add / remove listener
Interested entities call the application methods to add / remove themselves as listeners
Add "notify" methods in the application, that call the appropriate listener interface method on each of the registered listeners
Services call the application's notification methods to
For example,
public class MyApplication extends Application {
public interface MyListener {
void onEvent();
}
private Set<MyListener> listeners = new HashSet<Listener>();
public void addListener(MyListener l) {
listeners.add(l);
}
public void removeListener(MyListener l) {
listeners.remove(l);
}
public void sendEvent() {
for (MyListener l: listeners) { l.onEvent(); }
}
}
Now, from your activity (or fragment),
public class MyActivity extends Activity implements MyListener {
...
...
...
#Override
public void onEvent() {
// do something
}
#Override
protected void onResume() {
super.onResume();
((MyApplication)getApplication()).addListener(this);
}
#Override
protected void onPause() {
super.onPause();
((MyApplication)getApplication()).removeListener(this);
}
}
And in your service,
((MyApplication)getApplication()).sendEvent();
This provides synchronous messaging without using intents or static variables.
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