I am running a foreground service which is doing some work in the background while the user is interacting with my application.The problem which occurs is that when the user comes out of the application and kills the application from the home screen the service is not destroyed.Is there any way to kill the service when my application dies.
With "kills the application from the home screen" I'm assuming you mean swiping away the app from the task manager? In that case, there is a convenient callback in the Service class that lets you handle this.
Simply override that method and call stopSelf().
You can do following to stop the service
call stopService method in onDestroy method of activity
hope this will solve your problem
why do you make the service foreground?
If it's only doing work while the user interacts with your application,
maybe you should not keep it foreground.
Just call stopService() for your service in onDestroy() method of your main Activity.
I solved it by calling stopService(intent); in my MainActivity where I call the service from another Class.
#Override
protected void onDestroy()
{
super.onDestroy();
stopService(intent);
}
But as For the yourservice.class needed to have the onDestroy method, it is crucial.
#Override
public void onDestroy()
{
super.onDestroy();
stopForeground(true);
stopSelf();
}
Related
I have big problems with stopping a service, which plays audio file. I want to stop the current service before I play another file.
Activity:
public void playTrack(View view){
Intent i=new Intent(this,playService.class);
i.setAction("com.c0dehunterstudios.relaxer.PLAY");
if(isPlaying){
stopService(i);
isPlaying=false;
Log.v("ACTIVITY", "Stopping..");
}
startService(i);
isPlaying=true;
}
Service:
#Override
public void OnDestroy(){
Log.v("SERVICE","Service killed");
player.stop();
super.onDestroy();
}
But sadly it doesn't work - actually it doesn't even come down to the "Service killed" inside OnDestroy().
What am I doing wrong?
First, it's onDestroy, not OnDestroy . Second, you must use the #Override annotation for compile-time checking, so your Service code should look somewhat like this:
#Override
public void onDestroy(){
Log.v("SERVICE","Service killed");
player.stop();
super.onDestroy();
}
First, you need to clarify how many types of services in Android. AFAIK, there are:
Foreground service.
Background service.
Bound service.
Intent service.
These services stop in different ways.
Foreground: only stop when you intentionally stop it by calling stopService() in activity or fragment where you start that service or call stopSelf() in its own service. And Please note only these methods trigger service's onDestroy().
Background: stopService() and stopSelf() do in the same way as foreground. Moreover, you should know this service is in the same thread with activity or fragment calling it, so if you destroy activity or fragment, this service will stop also, but without calling onDestroy(). It basically destroys underground. Thus, if you want to catch when this service stops you need to add android:stopWithTask="false" when declaring service in Manifest file like this:
<application>
//....
<service android:name=".services.catchingStopService"
android:stopWithTask="false" />
//....
</application>
And now in your service class, you can override this method which triggers whenever this service stops:
#Override
public void onTaskRemoved(Intent rootIntent) {
super.onTaskRemoved(rootIntent);
// Your job when the service stops.
}
Bound: you need to handle by your self by bindService() and unbindService(), you will find out it's totally the same as starService() and stopService()
Intent: this type of service stops by itself when it finishes its jobs. And you can use ResultReceiver to communicate between service and activity or fragment. It's similar to BroadcastReceiver. You can search for example on Google easily.
Summary: base on your purpose, pick the type of service satisfying you. And they all agree with:
Don't count on onDestroy() to know when service stops because it
sometimes gets called underground; more accurately, onDestroy calls
when stopService() or stopSelf() calls (BoundService works in the
same way, I think, but by a similar method, maybe unBind(), I did not
test yet).
Use attribute android:stopWithTask="false", instead to know when the
service really stops.
All types of service stop when the device shutdown or OS kills it if
device leaks of memory.
You also should have a look at flag return by onStartCommand() to
be able to deal with when services stop like restart service again or
something. Here are some keyword you can search:
START_STICKY
<action android:name="android.intent.action.BOOT_COMPLETED" />
<action android:name="android.intent.action.ACTION_SHUTDOWN" />
<actionandroid:name="android.intent.action.QUICKBOOT_POWEROFF" />
I had a similar problem even with onDestroy correctly set up - the answer for which could be useful for people coming to this page. For me, onDestroy was not called immediately during stopService, sometimes for a very long time - leaving the service doing work when it should have stopped.
The answer is that this is expected behaviour - I can guess but don't exactly know why. So my solution in this case was to create a public static method to stop the actions of the service manually, which happens at the time it's called, then stopService() will call onDestroy in it's own good time...
In the case for this example (which is probably long gone, I would probably decide to keep the service running until it's expected to quite the app, but provide ways to change audio file, while the service is still active.
In my case I was printing a log inside the onDestroy and It was not printing the log and I thought onDestroy not calling when I call stopService. but in Android studio many times does not print the log so you can once double check or verify with the debug or toast.
I want to perform some operation when my application gets killed.
Which method can be used for this? I am working on Android 5.0.
The key of this question is that:
you must understand your application whether can receive any
additional callbacks when your application being killed in any kinds of situation.
The following answer is answered by Devunwired in this question:
Android app doens't call "onDestroy()" when killed (ICS)
This will help you more to understand this.
Your application will not receive any additional callbacks if the process it terminated by external means (i.e. killed for memory reasons or the user Force Stops the application). You will have to make do with the callbacks you received when you app went into the background for your application cleanup.
finish() is only called by the system when the user presses the BACK button from your Activity, although it is often called directly by applications to leave an Activity and return to the previous one. This is not technically a lifecycle callback.
onDestroy() only gets called on an Activity as a result of a call to finish(), so mainly only when the user hits the BACK button. When the user hits the HOME button, the foreground Activity only goes through onPause() and onStop().
This means that Android doesn't provide much feedback to an Activity to differentiate a user going Home versus moving to another Activity (from your app or any other); the Activity itself simply knows it's no longer in the foreground. An Android application is more a loose collection of Activities than it is a tightly integrated singular concept (like you may be used to on other platforms) so there are no real system callbacks to know when your application as a whole has been brought forward or moved backward.
Ultimately, I would urge you to reconsider your application architecture if it relies on the knowledge of whether ANY Activity in your application is in the foreground, but depending on your needs, there may be other ways more friendly to the framework to accomplish this. One option is to implement a bound Service inside of your application that every Activity binds to while active (i.e. between onStart() and onStop()). What this provides you is the ability to leverage the fact that a bound Service only lives as long as clients are bound to it, so you can monitor the onCreate() and onDestroy() methods of the Service to know when the current foreground task is not part of your application.
You might also find this article written by Dianne Hackborn to be interesting covering in more detail the Android architecture and how Google thinks it ought to be used.
You have to use Service Class for it like -
public class Myservice extends Service { #Nullable #Override public IBinder onBind(Intent intent) { return null; }
#Override public int onStartCommand(Intent intent, int flags, int startId) { Log.d(Constants.TAG, "Service Started"); return START_NOT_STICKY; }
#Override public void onDestroy() { super.onDestroy(); Log.d(Constants.TAG, "Service Destroyed"); }
#Override public void onTaskRemoved(Intent rootIntent) { Log.e(Constants.TAG, "END"); //Perfome here want you want to do when app gets kill stopSelf(); } }
In Manifest -
<service android:name="Myservice"
android:stopWithTask="false" />
In Oncreate of your launcher activity or Application Class to start service -
startService(new Intent(getBaseContext(), OnClearFromRecentService.class));
You can use your activity's onDestroy() method.
I have a service based on a check box in Activity(user can start or stop it).
Once it start, it will run in background, and should not be stopped when the activity is onDestroy().
However, I want to stop it when user swipes the Application away in Android's task, because this service need to restart when user reopen the App.
How can I do that? Is it possible to stop service in onTerminate() method in Application.
How can I do that?
You can do it adding this on your manifest.xml on your service
android:stopWithTask="true"
If you want to controle it you can also do it on your Service adding the onTaskRemoved()
#Override
public void onTaskRemoved(Intent rootIntent) {
super.onTaskRemoved(rootIntent);
//STOP SERVICE OR WHATEVER YOU WANT
}
If you use onTaskRemoved() don't add android:stopWithTask="true" because it won't be called*
You can set a flag to false when onPause() or onDestroy() is called.Save this in SharedPreferences.Use this flag to check whether your app is running or not. Start your service only if flag is true.
My application has an activity and a service running in the same process. When the user terminates the activity by clicking the STOP button, the activity causes the service to terminate.
From the Android documentation I understand that the system can kill a process to reclaim resources:
"Once your activity is stopped, the system might destroy the instance if it needs to recover system memory. In extreme cases, the system might simply kill your app process without calling the activity's final onDestroy() callback, ..."
Question 1: Is it possible for my activity to be killed but not the service? I would prefer my service remain alive.
If the answer is 'yes' then
Question 2: Is there a mechanism where the service can be notified that the activity has been killed?
IBinder.linkToDeath has the functionality I need but seems to apply to a process, not an activity.
I've thought of an indirect method like having the activity take ownership of semaphore and having the service use a thread to wait on it. Then when the activity gets killed it will release the semaphore and the service will get it, providing the notification. But I was wondering if there wasn't an android-centric technique I could use.
[begin edit]
After reading the very helpful comments you've provided I'd like to clarify the scenario I'm presenting.
I've started two components: an activity and a service. The application is configured so that service can continue to run after the activity has stopped and been destroyed. The user can restart/start the activity multiple times and it will use the same instance of the service.
Normally the activity will notify the service it has been destroyed during onDestroy(). But onDestroy() may not be called.
I'd like to know whether there is some android-specific mechanism I can use to notify the service that the activity has been killed without the call to its onDestroy() method having been made.
[end edit]
Thanks for your help.
Will
As I said before, single activity won't be killed by android without calling onDestroy(). If Android needs more memory it kills whole process(with all activities and services). Here is description, documentation is wrong about this.
Service can be also created in other process but it has to be set int the manifest. And then you can use iBinder to get notification when process(with all activities) is killed by Android
Yes services and activities can run independently of each other.
To achieve what you're trying to do I would explicitly start your service using startService() in your activity's onStart() function (or wherever you wish to launch it) and also bind to it at the same point. Binding without an explicit startService will cause the service to stop when you kill the activity (unless some other activity is still bound to it).
In your activity's onStop() call a function on your service to tell it the activity has been killed.
In your Activity:
private ServiceRecordJourney yourService;
private ServiceConnection serviceConnection = new ServiceConnection() {
#Override
public void onServiceConnected(ComponentName className, IBinder service) {
YourServiceBinder binder = (YourServiceBinder) service;
yourService= binder.getService();
}
#Override
public void onServiceDisconnected(ComponentName arg0) {
}
};
#Override
public void onStart(){
super.onStart();
startService(new Intent(this, YourService.class));
// Bind to Service
Intent intent= new Intent(this, YourService.class);
bindService(intent, serviceConnection , Context.BIND_AUTO_CREATE);
}
#Override
public void onStop(){
super.onStop();
if(yourService != null){
yourService.activityKilledFunction();
unbindService(serviceConnection);
}
}
Your service will need to be foreground (and display a notification) to further stop it from being killed off by the OS. Also as it's been explicitly started you will need to handle an explicit stop on the service (either call stopSelf() on the service or stopService() in a context object.
You can handle communication to the service using multiple startService() calls with different intents but I prefer the above approach (and I'm sure that in the case binding is the preferable approach).
Also whilst the service is running the activity will bind and unbind to the service each time the activity is started or stopped by the user.
I have the following code in each of the 5 activities of my app. I wanted to keep the service running that is bound to these five activities. It will play music in the background. However when the user navigates away from the any of these five activities the Service should be killed. Using the code below I am able to get it so that the music plays in the background when navigating between the activities. but the Service keeps running after leaving the application. What is the best way to solve this problem? How about some creative ideas.
I put this Toast message in the onDestroy method of the service so I can tell when the service is stopped.
Toast.makeText(this, "My Service Destroyed", Toast.LENGTH_LONG).show();
I never see any Toast message pop up when I leave the application. The other toast messages do show to indicate that the service has started.
#Override
public void onPause() {
super.onPause();
unbindService(serviceConnection);
}
#Override
public void onResume() {
//After a pause OR at startup
super.onResume();
//add this to the onResume of the activity
// startService(new Intent(this, AudioService.class));
bindService(new Intent(this, AudioService.class),
serviceConnection, Context.BIND_AUTO_CREATE);
}
According to the documentation here:
Multiple clients can bind to the service at once. When a client is done interacting with the service, it calls unbindService() to unbind. Once there are no clients bound to the service, the system destroys the service.
So maybe you're missing some unbind in one of your activities. You can check this by printing a log in the onBind and onUnbind methods of your service.