I do not understand what difference between those two APIs. I mean when to use the first one. Why is there JobIntentService ?
Thanks in advance
I would recommend to read this article explaining about the difference between intent service and job intent service. When we look for the first time at these terms Service, IntentService, JobIntentService they would look almost similar - in one way or other they would perform some operations in background (which user does not notice). But there is few difference in the way they operate,
Service - This runs on the same main thread which invokes this service and performs some background operation. For any long running operation happening on the main thread it is recommended to create a new thread and do the job (eg; Handler) by not impacting the main thread's performance.
Drawback : Runs on main thread
IntentService - Intent service also helps in doing some long running (indefinite) background task. The only difference is that it creates a new thread to perform this task and does not run on the main thread. Does the given job on it's onHandleIntent.
Drawback: The job given to the IntentService would get lost when the application is killed
JobIntentService - Job intent service is very similar to IntentService but with few benefits like the application can kill this job at any time and it can start the job from the beginning once the application gets recreated/up.
But from Oreo, if the app is running in background it's not allowed to start the service in background. Android asks us to start the service explicitly by context.startForegroundService instead of context.startService and when the service is started within 5 seconds it must be tied to the notification to have a UI element associated with it.
Reference : https://developer.android.com/about/versions/oreo/background.html
Both work same but the only difference with JobIntentService is that JobIntentService gets restarted if the application gets killed while the service was executing. OnHandleWork() get's restarted after the application get's killed.
Basically, the two follow the same role, the difference being that an IntentService it is a base class for Service that handles an explicit asynchronous request with Intent on demand, it is starts through the startService (passing the Intent of the service), from hence the service is started as you wish, from the Android Oreo JobIntentService it also performs work processing however it is able to keep running in older versions, it also makes a process simpler. More in fact the 2 APIs have the same follow up. For the Execution of the work from the Oreo uses if JobScheduler.enqueue already in the older versions of the platform, it will be used Context.startService
Hope this helps.
I am using a JobIntentService perform some task after the task is ended I send a Broadcast which is also listened by one of my Activity.
Suppose in a case where the activity is closed by Android OS to free up some memory then if the Broadcast is sent from the JobIntentService will the OnCreate of the Application also be called?
I don't know if answer marked correct is still correct. On a phone running Android P, if you have a manifest declared broadcast receiver and an Application class defined in your <application> node, the onCreate() in your Application class is called before the onReceive in your broadcast receiver. I see no reason to believe other versions of Android would behave differently.
NO. It will never call the applications OnCreate() method (is called only during a cold start).
A cold start refers to an app’s starting from scratch: the system’s process has not, until this start, created the app’s process. Cold starts happen in cases such as your app’s being launched for the first time since the device booted, or since the system killed the app.
About BroadcastReceiver Lifecycle:
If your receiver is registered in activity then it's lifecycle is the activities lifecycle. So your receiver will not be able to listen once your activity gets destroyed.
If your receiver is registered in application then it's lifecycle will be applications lifecycle and it will be able to listen to the broadcasts as long as the application is not destroyed.
JobIntentService & Receiver
When you start a JobIntentServie (from a receiver) then your job intent service will not get killed by the OS as long as there is active jobs going on (please note that there may be a time limitation, to know more: How long is the "JobService execution time limit" mentioned in Android's JobIntentService docs?).
Now if your activity is destroyed in the meantime then your broadcast receiver will not listen to the broadcast because it's lifecyle has ended, if you don't unregister the receiver yourself, the system will kill it as system considers the BroadcastReceiver to be no longer active.
So if you want to listen to a broadcast as long as your application is not destroyed, you should register your broadcast receiver in applications onCreate() method.
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
I wanted to know if there is a way to create a common WorkerThread to all activity. This thread needs to open a socket, send a command, read the response and send it to the various activity. I tried to use an IntentService with a BroadcastReceiver but I have noticed that the commands sent from the activity are run one by one, respecting a queue. In my case, I need instead of a thread which is able to execute a command one by one but at the same time also to terminate an already running command to start a new one. What do you suggest?
Anything that's shared between Activities like that should be owned by a Service instead. Both Activities can start and/or bind the service to make sure they can connect to it.
You do not need to use an IntentService. IntentService is for queueing items to be run serially on its own Thread. Use the base Service class instead.
I have a pool of AsyncTasks which pass state data back to the service that executed them, but they keep being killed by Android.
I can't use an IntentService because the Service is keeping track of State used by UI and AsyncTasks.
How do I:
1) keep the service from being killed
2) Replace either service or AsyncTask with something better for this use case?
You should use foreground service. Android OS can kill service if it is running short on resources, but it will always spare foreground service.
The Android system will force-stop a service only when memory is low
and it must recover system resources for the activity that has user
focus. If the service is bound to an activity that has user focus,
then it's less likely to be killed, and if the service is declared to
run in the foreground (discussed later), then it will almost never be
killed.
Note: Another thing you should also consider
Caution: A service runs in the main thread of its hosting process—the
service does not create its own thread and does not run in a separate
process (unless you specify otherwise). This means that, if your
service is going to do any CPU intensive work or blocking operations
(such as MP3 playback or networking), you should create a new thread
within the service to do that work. By using a separate thread, you
will reduce the risk of Application Not Responding (ANR) errors and
the application's main thread can remain dedicated to user interaction
with your activities.