when I open the activity of my project I call the startService(Intent intent) method to start a new Service.
When the activity is destroyed the service shouldn't be killed (because I didn't use the bindService() method), but the fact is that when I close my activity the service is killed and after a second the system creates a new Service (I verified that, the system calls again the onCreate() method of my service). What do I have to do to keep only one service ? Thank you
To have a service running independently of your application's main process and to be sure that Android does not kill it while it's doing something, there are two things you should do/try.
Run your service in a separate process. You can achieve this by adding the following attribute to your service declaration in the manifest:
android:process=":somenamehere"
When your service is running and you do not want it to be killed by the OS, you have to use the startForeground(int id, Notification notification) method. When the service finishes whatever is doing and can be killed by the OS, call stopForeground(boolean removeNotification). "startForeground" requires a notification as argument because every foreground service must display a notification so the user realizes about it
I hope this helps you.
I mean I hold the home button and then kill my activity from the list of app open
That does not "close" an activity. That terminates your process. The user is welcome to terminate your process whenever the user wants, whether via this means or through third-party task manager apps. There is nothing you can do about this -- you cannot stop the user from terminating your process. Since your process will stop for other reasons as well (e.g., sheer old age), you have plenty of reasons to handle this case.
Edit: Please refer to CommonsWare's answer
Old answer: You should override public int onStartCommand(Intent intent, int flags, int startId) method and return START_STICKY value as the mode of your service.
this will keeps your service working when the activity is destroyed or even when you exit your app unless you call stopService(Intent) explicitly
Related
This question already has an answer here:
Android Service run indefenitely
(1 answer)
Closed 7 years ago.
Can anyone explain me suppose I have an Accessibility Service defined by my application. It starts running when the Accesibility permission is given to the App. Suppose due to some reason memory issues the service is stopped. How can I make the Service start again cannot find any way to do it. Please help.
Thank u very much.
Hi Oblivion, I am new to asking questions untill today i used to just refer Stack Overflow :-) . Sorry I ll make sure I ll be putting the complete description. Now my problem.
I am thinking of two approaches
Start as Sticky service
Run the Service in a different process
first approach -> Suppose the app crashes and due to the fact it is sticky it restarts and due to some bug of previous crash it crashes again with some exception after that Android will not start the service
Posible Soln -> Make the Service logic as much error free as possible
second approach -> Run the Service in a different process as http://mindtherobot.com/blog/37/android-architecture-tutorial-developing-an-app-with-a-background-service-using-ipc/
and make sure you take all the solutions mentioned for first approach.
All these things I have done and it is solving my problem.
My original question is suppose I have bound a client to the Accesibility service and I have come to know that my Accesibility service is not running, is there a way by which I can fire an intent and tell Android to start my AccesibilityService.
I need to do this because I want to control the lifecycle of my Accesibilityand not Android.
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Toast.makeText(this, "service starting", Toast.LENGTH_SHORT).show();
//your code!!!
// If we get killed, after returning from here, restart
return START_STICKY;
}
Change your return statement like above. It will restart your service again.
START_NOT_STICKY
If the system kills the service after onStartCommand() returns, do not recreate the service, unless there are pending intents to deliver. This is the safest option to avoid running your service when not necessary and when your application can simply restart any unfinished jobs.
START_STICKY
If the system kills the service after onStartCommand() returns, recreate the service and call onStartCommand(), but do not redeliver the last intent. Instead, the system calls onStartCommand() with a null intent, unless there were pending intents to start the service, in which case, those intents are delivered. This is suitable for media players (or similar services) that are not executing commands, but running indefinitely and waiting for a job.
START_REDELIVER_INTENT
If the system kills the service after onStartCommand() returns, recreate the service and call onStartCommand() with the last intent that was delivered to the service. Any pending intents are delivered in turn. This is suitable for services that are actively performing a job that should be immediately resumed, such as downloading a file.
we can return any of above, depends on our requirement.
Source:Here!!!
About using START_STICKY in Android Service.
official document says:
if this service's process is killed while it is started (after
returning from onStartCommand(Intent, int, int)), then leave it in the
started state but don't retain this delivered intent. Later the system
will try to re-create the service. Because it is in the started state,
it will guarantee to call onStartCommand(Intent, int, int) after
creating the new service instance;
This is understandable, so when an started service's process is killed due to lack of memory, the OS will automatically try to start the service again later.
My question is, if my code starts the service startService(...), and later stop it(e.g. I have a "STOP" button on my app's UI, when press it, I call stopService(...)), will system later start the service again? Or will the service instance be cleared from memory completely without later being created by system? (No service binding for this scenario)
START_STICKY- tells the system to create a fresh copy of the service, when sufficient memory is available, after it recovers from low memory. Here you will lose the results that might have computed before.
And answer for your query is the service only recreate if it's killed by the OS in any circumstances when working with START_STICKY. if we were terminating the service why android need to reproduce it again.if your using stopSelf() the service does not recreate even it is sticky.
I have had that stopService() button in my app during testing. Once you stop it using the command, it will not start again until you call startService().
Android kill the process from time to time. However Sticky service is recreated automatically by android system. Somebody told, Sticky services are destroyed and are recreated after 5 seconds.
START_STICKY is the operation mode of the started services, depending on the value they return from on StartCommand() method.START_STICKY is used for services that create the copy of service but it won`t store any result of services which is performed before.
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Logs.d(TAG, "# Service - onStartCommand() starts here");
// If service returns START_STICKY, android restarts service automatically after forced close.
// At this time, onStartCommand() method in service must handle null intent.
return Service.START_STICKY;
}
I have a Service running in the foreground, and an Activity that interacts with it. If the Activity crashes, Android kills the entire process, including the foreground Service and its associated Threads.
However, the ongoing notification provided by the Service does not go away, and upon closer inspection, Android's task manager reveals that the Service itself is still running.
How can I kill the foreground Service in this circumstance?
Have you override onStartCommand method of the Service? What value is it returning? If not, try to override it and return START_NOT_STICKY from it.
START_STICKY: If this service's process is killed while it is started, then leave it in the started state but don't retain this delivered intent. Later the system will try to re-create the service.
START_NOT_STICKY: If this service's process is killed while it is started, and there are no new start intents to deliver to it, then take the service out of the started state and don't recreate.
Not sure, as I have never worked on foreground services, but this might be the reason.
Are you sure the service is not running it its own process...
Also can you confirm whether the service is getting restarted..If its getting restarted-it is because you are returning START_STICKY from onStartCommand()
I have an app with one activity and one service. If I kill the activity while the service is running it gets killed too. It is very important for me that the service doesn't get killed. How to make that when the system kills (or I kill it by clearing the "Recent apps" list) the activity the service still remains active until it finishes its job? Thanks in advance!
You can try returning START_STICKY from onStartCommand in your Service:
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
handleCommand(intent);
// We want this service to continue running until it is explicitly
// stopped, so return sticky.
return START_STICKY;
}
It is very important for me that the service doesn't get killed
Your processes can be killed at any time, for any reason, based on user activity (recent tasks list, a third-party task manager, "Force Stop" in Settings, etc.) or based on OS needs (system RAM is getting low). You cannot prevent this.
You can take some steps to minimize the odds of the OS deciding on its own to terminate your process, such as using startForeground() on the service, but this does block the user from doing what the user wants with your app's process.
I'm displaying a window from that service so if the service stops then the window disappears.
Presumably, the user wants your window to disappear if the user is explicitly getting rid of your app via the recent tasks list, a task manager, etc. You are certainly welcome to advise users in your documentation of any negative effects that this will have.
You are also welcome to experiment with having that service be in a separate process. My understanding is that this will not help with the recent-tasks list on Android 4.4, though it might on earlier versions of Android. Whether this helps with third-party task managers probably depends on the manager, and this should not help with "Force Stop" from settings. It also means that you will have to deal with IPC, increased system RAM consumption while your main and service processes are both running, etc.
Are you running a bound service? If so, then the system will kill it when the last client activity disconnects (terminates). Here's the blurb from the reference page:
When the last client unbinds from the service, the system destroys the
service (unless the service was also started by startService()).
I am developing an application in which a background service is created to collect sensor data. I am starting the service from my activity:
startService(new Intent(this, MyService.class));
I created the service so if the application is destroyed, the background service still continues to collect data. I tried this, and it worked to a certain extent. My problem is that when I kill the application, the service seems to restart because the onCreate() service and the onStart() methods are invoked. Is there any way with which the service isn't restarted please?
UPDATE:
As suggested in an answer below, I added the following method in the service but no luck.
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
return START_NOT_STICKY;
}
It depends on the value returned in onStartCommand.
You must return START_NOT_STICKY
According to the documentation:
For started services, there are two additional major modes of operation they can decide to run in, depending on the value they return from onStartCommand(): START_STICKY is used for services that are explicitly started and stopped as needed, while START_NOT_STICKY or START_REDELIVER_INTENT are used for services that should only remain running while processing any commands sent to them
In short:
If you return START_STICKY the service gets recreated whenever the resources are available. If you return START_NOT_STICKY you have to re-activate the service sending a new intent.
Since all of this triggered my curiosity, I made a sample app to test this. You can find the zip with all the sources here
There are a startService button and a stopService button that do what you would expect from them.
The service returns START_NOT_STICKY in onStartCommand.
I placed toasts in onCreate, onStartCommand and onDestroy.
Here what happens:
If I press start, onCreate and onStart are called
If I press stop, onDestroy is triggered
If I press start twice, onCreate is called once and onStartCommand twice
So it behaves as one would expect.
If I start the service and kill the app as you described, onDestroy does not get called but neither onCreate or onStart.
If I get back to the app and I press start again, onCreate gets called which means that, as I wrote before, START_NOT_STICKY prevents the service to getting restarted automatically.
I guess you have something else in your app that starts the service again (maybe a pending intent).
The app and the service live on the same process, which means when the app is killed so is your service. Changing the return value of onStartCommand doesn't affect this process. It simply tells the Service to either start/stop when you tell it or when it's finished doing what it needs to. As mentioned in your comment to your original post, setting it as a foreground process worked, but that's really just forcing the service to have a high priority, not solving the problem.
To change the Service so that it's killed separately and assuming it's a started service rather than a bound service due to the use of onStartCommand, specify a process name in the manifest for that Service.
From the Process and Threads Developer Guide:
The manifest entry for each type of component element— <activity>, <service>, <receiver>, and <provider>—
supports an android:process attribute that can specify a
process in which that component should run. You can set
this
attribute so that each component runs in its own process or so
that some components share a process while
others do not. You can also set android:process so that
components of different applications run in the same
process—provided that the applications share the same
Linux user ID and are signed with the same certificates.
Android might decide to shut down a process at some
point, when memory is low and required by other
processes that are more immediately serving the user.
Application components running in the process that's
killed are consequently destroyed. A process is started
again for those components when there's again work for them to do.
From <service> in Manifest File:
android:process
The name of the process where the service is to run.
Normally, all components of an application run in the default process
created for the application. It has the same name as the application
package. The element's process attribute can set a
different default for all components. But component can override the
default with its own process attribute, allowing you to spread your
application across multiple processes.
If the name assigned to this
attribute begins with a colon (':'), a new process, private to the
application, is created when it's needed and the service runs in that
process. If the process name begins with a lowercase character, the
service will run in a global process of that name, provided that it
has permission to do so. This allows components in different
applications to share a process, reducing resource usage.
Not sure why the other answer that mentioned this was down voted. I've used this method in the past and, today, created a simple one Activity app with a Service on a different process just to make sure I wasn't crazy. I used Android Device Monitor to kill the app's process. You can see both, separate processes in ADM and can see that when the app's process is killed, the Service's is not.
Start not sticky doesn't work above kitkat, and the other onTaskRemoved not working above Marshmellow.
onTaskRemoved could be used by handled some exceptions. Did not worked on that. But try that one.
If you are using an IntentService, it has an
onHandleIntent()
method where you should place the code that needs to be executed. It is executed in a separate thread (not a UI thread where your application runs) therefore your app shouldn't affect it. When the code has finished executing, the thread is terminated and the service is stopped automatically.
I ran into the same problem and was able to resolve it by making the service run in a global process. You do this by adding the following to the manifest tag:
process="com.myapp.ProcessName"
(Make up whatever name.)
When I did this I found that my service wasn't killed (and restarted) when the app is swiped off the list. Presumably this is because the app process is killed when you swipe it off, but global service processes are not.
The disadvantage of this is that communication between your app and service now has to be via the IBinder interface; you can't directly call functions in the application or service from the other one, because they're running in different processes.
I know its much late to answer this question, but may be it can be helpful to others. This really helped me for my Music Player App.
If there are services which can be disruptive or can affect the user experience like music etc , then in that case you have to use Notification and when service is started successfully, then create the Notification and use the function
startForeground(int Notification_id,Notification);
This will run your service in background without restarting and reinvoking its methods
https://developer.android.com/reference/android/app/Service.html