I have recently replaced all my service to foreground services and JobIntentService since there are some background execution limits (https://developer.android.com/about/versions/oreo/background) in oreo and above. As per documentation, JobIntentService acts like Intent Service for Android 7 & below and acts like JobScheduler for Android 8 & above. I have noticed there is an issue in new JobIntentService provided by Google.
Android 8 & above:
There is a crash happening continuously in android 8 and above. There was a ticket raised here mentioning about the same issue https://issuetracker.google.com/issues/63622293 and I have added a temp fix suggested by few geeks.
Android 7 & below: JobIntentService which acts like Intent Service is not getting stopped once the work is done.
I have implemented JobIntentService within a service which triggers whenever some action is performed by a user.
Code
public class SampleJobIntentService extends FixedJobIntentService {
public static void postData(Context context, String data) {
Intent intent = new Intent(context, SampleJobIntentService.class);
intent.setAction(INITIAL_ACTION);
intent.putExtra(SAMPLE_ID, data);
SampleJobIntentService.enqueueWork(context,intent);
}
public static void enqueueWork(Context context, Intent work) {
SampleJobIntentService.enqueueWork(context, SampleJobIntentService.class, JOB_ID, work);
@Override
protected void onHandleWork(@NonNull Intent intent) {
if (intent != null) {
SampleRequest sampleRequest = requests.get(intent.getAction());
if (sampleRequest != null) {
try {
// perform some networking operations
} catch (Exception ex) {
Log.d("Error for intent ");
}
Log.i("send action ");
} else
Log.e("action not found for ");
}
}
}
To avoid the crash with JobIntentService, I took few references from https://issuetracker.google.com/issues/63622293
public abstract class FixedJobIntentService extends JobIntentService {
@Override
GenericWorkItem dequeueWork() {
try {
return new FixedGenericWorkItem(super.dequeueWork());
} catch (SecurityException ignored) {
doStopCurrentWork();
}
return null;
}
private class FixedGenericWorkItem implements GenericWorkItem {
final GenericWorkItem mGenericWorkItem;
FixedGenericWorkItem(GenericWorkItem genericWorkItem) {
mGenericWorkItem = genericWorkItem;
}
@Override
public Intent getIntent() {
if (mGenericWorkItem != null) {
return mGenericWorkItem.getIntent();
}
return null;
}
@Override
public void complete() {
try {
if (mGenericWorkItem != null) {
mGenericWorkItem.complete();
}
} catch (IllegalArgumentException ignored) {
doStopCurrentWork();
}
}
}
}
I think you just need this much of a code. Create a new Class MyJobIntentService and write this much of a code and call postData() to start your service.
And make sure to add your service in manifest file
JobIntentService which acts like Intent Service is not getting stopped once the work is done
The issue is in your extended class FixedJobIntentService dequeueWork method.
Try changing it to something like below
Looking at the JobIntentSerivce code, Work Items processor logic is below, i.e until there are no work items left in the queue all items are processed (i.e onHandleWork is called for each item)
Issue in your implementation is after processing the first work item, the super.dequeueWork() returns null, which you are not taking care of and just sending a new FixedGenericWorkItem object passing null value. You might observe that a null value is passed to your onHandleWork in your subsequent calls.
Hope this helps resolve your issue.
I have already lost my 2 complete years in reading google documentations... Which are
use-less
... Withno proper documentation
and withno proper sample codes for its developers
..!! So i mention this in every of my posts onstack-overflow
, As it will help to save time of others..!!It looks you are a good programmer; just need some
hints to your posted question
:Hint-1 :
foreground service :
If you need
ALL THE TIME RUNNING PROCESS; WHICH WILL NEVER END... ONCE IT IS STARTED
it is used in service which returnsSTART_STICKY
from itsOnStartCommand
. Which is again not advised to use as if you want to implement it at any cost ... then you will have to use a notification withsetOngoing(true)
Which end user would not be able to swipe away your notification, it will remain there forever....Use of the foreground service :
There has been restrictions on receivers too; above
Oreo
onwards and you can not use all the receivers and intent actions by declaring it in manifest and by just making a receiver... I advice to just useBootComplete
permission and use a singlereceiver
which receives theboot_completed
intent and calls aservice
if below O and calls a foreground service above O. Now from that foreground service you implement the runtime receivers for all and unregister it in Ondestroy methods. I have never found an official sample code for implementing runtime receiver and finally i have implemented it successfully by many months hard-work... Yes it was not a smart work due to googleWhen to use foreground service :
Only if you want to implement broadcast receivers.... If you do not want to implement any broadcast receivers; STAY AWAY.......
Hint-2 :
** service has its quality of :**
Just doing a very tiny work... and just exit... it has to be exited by S
topSelf()
... Again,Services can cause data-loss
if called multiple times... As same service thread can be run more than once... Again if you want a service to do a lot of work... UseSTART_STICKY
... But again it is not recommended and i have suggested already, when to use it in Hint 1.** Intentservice has its quality of :**
Doing a relatively long running tasks and it has
property of execution serially only
If you again and again calls the sameintentService
, then all calls will be kept in aqueue
and will be executedone by one
after finishingone by one
. Which is not the case in service as depicted above. It ends on its own... no need to end it by a developer..!!** Unique Quality of all :**
Once they are
crashed
android can stop them calling in future without notifying you as it crashes the app. Need to be handled them withtry-catch-exception
toavoid crash
. Again... Ifyou are implementing threads within services
thentry-catch-exception
will not save your application from being crashing
...** THEN WHAT THE HELL & HOW TO IMPLEMENT IT THEN :**
Use
FireBaseJobScedular
:-EVEN ALL THE TIME RUNNING TASK
EVEN SUPPORTED BY NON STANDARD COMPANIES
like vivo, mi, oppo, one+3, ... which takesstock-android
makes changes to it and gives names like FunTouchOs, ColorOs, OxygenOsGooglePlyService
and runs within it, And obviously non-standards companies too would not restrict google apps from being doing its tasks.Oreo
.., Even i have tested it onAndroid P
and works below Android version 5.0 asAlarmManager
tasks.minsdk above 16
,target sdk 26
as if in case you wants to upload your app togoogle play
it is compulsory now and that news would have been heard you. andcompile sdk 26
.JobService
in manifest and use a single line permission ofreceive_boot_complete
cold boot
andhot boot
you can focus on actual tasks
.return false
to indicate task has been finished and it will end the JobService.Why i am suggesting because i am
CTO
of a well-UNKNOwn
company and has been experienced the problems caused byforeground service
across the many types of android phone manufacturers... It is not theApple and ios
so we had to experienced it. Remain developer since past 18 years and i mostly codes today too... in all of the development projects and its development strategies are thought by me only.