37

I recently was updating an app that I work on to handle notifications from push using a JobIntentService instead of a regular IntentService because it seems like the correct way to handle this on pre-Lollipop devices as well as post. I am enqueueing work as such:

enqueueWork(context, MyJobServiceExtension.class, JOB_ID, work);

This is the manifest declaration:

<service android:name="com.example.MyJobServiceExtension"
            android:permission="android.permission.BIND_JOB_SERVICE"
            android:exported="true"
            tools:node="replace">

I never see any callbacks in onHandleWork or any error logs in my logcat. Has anyone successfully integrated this that could help?

Update 1

I tested this on an API level 21 device and it worked.. but it doesn't seem to be getting called on my Android Oreo Pixel XL device.. Any clues as to why?

Update 2

Also I seem to be seeing the IntentService's onCreate be called, but none of the other lifecycle methods (including onHandleWork). Has anyone encountered this either?

JJD
  • 50,076
  • 60
  • 203
  • 339
Eshaan
  • 673
  • 1
  • 7
  • 11
  • 1
    I have the same symptoms, but no answer yet. Works fine on an API level 23 device, not on API level 26 Nexus 5X. How is your `work` Intent constructed? – Jule Sep 13 '17 at 07:15
  • @Jule currently my work intent is constructed it with a custom action plus some extras and that is it. – Eshaan Sep 13 '17 at 23:57
  • 1
    I have the same issue, I actually get this message "JobServiceContext: Time-out while trying to bind..." – agirardello Sep 16 '17 at 15:13

12 Answers12

71

I had the same issue after upgrading from IntentService to JobIntentService. Make sure you remove this method from your old implementation:

@Override
public IBinder onBind(Intent intent) {
    return null;
}

For me this solved the problem, and now it works both on pre- and post-Oreo.

agirardello
  • 2,895
  • 22
  • 22
  • wow, thanks a lot! This fixed it. I wish android would have given me back some error in this case =_= I actually never noticed that ServiceContext timeout when trying to bind log. – Eshaan Sep 18 '17 at 19:56
  • ok its working but i am seeing now that the service is running good when the app is open or in recents, but service is stopped when remove from recents pls help me here – Sunil Chaudhary Aug 03 '19 at 10:48
  • also had to remove onCreate and onStart overrides – syonip Oct 06 '19 at 09:19
10

I had the same problem (worked fine on a pre-O device, no indication of anything happening whatsoever on an O-device). Today, I tried again with exactly the same code as yesterday, now it works - only difference is that I rebooted the device in between.

My current theory is that my initial setup did not work; my current one does and just redeploying new code does not clear out the broken state from the JobScheduler; a reboot or an uninstall/reinstall of the package does.

The setup that's working now (migrated from a former IntentService):

<service
    android:name=".MyJobIntentService"
    android:exported="false"
    android:permission="android.permission.BIND_JOB_SERVICE"/>

and start with

Intent intent = new Intent(); 
intent.putExtra(EXTRA_NAME, extraValue);
JobIntentService.enqueueWork(context, MyJobIntentService.class, FIXED_JOB_ID, intent);

Note that the intent is not an explicit intent (i.e., the ComponentName is not set).

Jule
  • 871
  • 5
  • 13
3

This is what worked for me,

Remove the IBind Override as suggested by @agirardello

and added the following

@Override
public int onStartCommand(@Nullable Intent intent, int flags, int startId) {
    return super.onStartCommand(intent, flags, startId);
}

Have no idea why this worked.

JJD
  • 50,076
  • 60
  • 203
  • 339
Sanket Berde
  • 6,555
  • 4
  • 35
  • 39
3

If you have overridden the onCreate method in your JobIntentService, it will prevent the onHandleWork to be called.

I converted my Service to JobIntentService and only after I removed the onCreate method it worked.

Dimitar Darazhanski
  • 2,188
  • 20
  • 22
2

I ran into this issue trying to enqueue the JobIntentService using JobScheduler. While JobScheduler has its own enqueueWork() method, it doesn't work with JobIntentService. The service will start but onHandleWork() is never called.

It started working again when I used the static enqueueWork() method that is on the JobIntentService - eg:

MyJobIntentService.enqueueWork(context, ...)

None of this was obvious from reading Android's javadoc.

JJD
  • 50,076
  • 60
  • 203
  • 339
Kabliz
  • 310
  • 4
  • 12
1

I encountered a somewhat similar problem with onHandleWork not being called the second time after migrating from Service to JobIntentService. Logs were showing that enqueueWork was called but onHandleWork was executing only the first and appeared to be stuck.

After some more digging and logging, I discovered that the difference was that in a "stuck" scenario there was JobIntentService#onDestroy even though all operations in onHandleWork were performed and seemingly finished.

Turned out that the culprit was bindService call of that service to activity lifecycle which was preventing disposing of the first job and for some reason calling enqueueWork after this condition was causing the service to "stuck" and never run any of the following onHandleWork again.

So, here is an incorrect log of events in which JobIntentService will appear to be stuck after the first call never triggering onHandleWork again:

enqueueWork -> first call
onHandleWork started (log in the first line)
onHandleWork finished (log in the last line)
enqueueWork -> second call
enqueueWork -> third call

And here is the correct log of events with JobIntentService functioning correctly after removing bindService call:

enqueueWork -> first call
onHandleWork started (log in the first line)
onHandleWork finished (log in the last line)
onDestroy (service is destroyed after the job is finished)
enqueueWork -> second call
onHandleWork started (log in the first line)
onHandleWork finished (log in the last line)
onDestroy
enqueueWork -> third call
onHandleWork started (log in the first line)
onHandleWork finished (log in the last line)
onDestroy

Hope this will be helpful to someone.

git pull origin
  • 353
  • 4
  • 8
0

For me I was still starting the service after enqueueWork and was giving me error because of that.

Tarun Goel
  • 36
  • 4
0

Just try exiting and running the Android Studio again. Then test again. In my case, the version of Android Studio is v 3.3.1. See the sample code that works properly.

public class CustomizedIntentService extends JobIntentService
{
    public static final String MY_ACTION = "action.SOME_ACTION";
    private static final int MY_JOB_INTENT_SERVICE_ID = 500;

    public CustomizedIntentService() {
    }

    // Helper Methods to start this JobIntentService.
    public static void enqueueJobAction(Context context, String action) {
        Intent intent = new Intent(context, CustomizedIntentService.class);
        intent.setAction(MY_ACTION);

        enqueueWork(context, CustomizedIntentService.class, MY_JOB_INTENT_SERVICE_ID, intent);
    }

    @Override
    protected void onHandleWork(@NonNull Intent intent) {
        String action = intent.getAction();

        // action will be "action.SOME_ACTION"
    }

    @Override
    public void onCreate() {
        super.onCreate();
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
    }

    @Override
    public boolean onStopCurrentWork() {
        return super.onStopCurrentWork();
    }
}

// start the JobIntentService as you need.

CustomizedIntentService.enqueueJobAction(context, CustomizedIntentService.MY_ACTION);

Jay
  • 75
  • 1
  • 7
0

As funny as this may sound, l had a similar issue because l did not change the name of the class to its own name in the enqueueWork() because l copied the code from one of my classes. After l made the update it started working properly.

CanCoder
  • 1,073
  • 14
  • 20
0

I finally found the solution for that problem LoL

If you Override the "onBind" method and u call the work using the "enqueueWork" method you need to return the bind to the engine of the work doing this:

@Override @Nullable
    public IBinder onBind(@NonNull Intent intent) {
        [... Do What You Want ... ]
        return super.onBind(intent);
    }

So returning the IBinder of the "super.onBind" method, so you must use that to bind to the JobIntentService.

If you want to bind and return another binder you can do that:

@Override @Nullable
    public IBinder onBind(@NonNull Intent intent) {
        IBinder binder = initSynchronizer();
        new Thread(
                () -> onHandleWork(intent)
            ).start();
        return binder;
    }

So by starting you "onHandleWork" in another Thread. This way you can use:

"bindService(....., JobIntentService.BIND_AUTO_CREATE);"

to bind to the service and return your Binder. Anyway when you unbind from the service the service will get killed, and if it still run you cannot bind again to it because the service got killed but the thread in which the "onHandleWork" is still running...

So I suggest you to use this version only if you have to do a task which need to communicate with the activity until it is alive and need to still working if the activity get killed (without the possibility to bind again the jobService, but only to start a new one...)

To don't kill the service after the unbind you need to start it in "foreground" the "stopForeground" in the "onDestroy". This way you service still be alive just for the thread which is handling the "onHandleWork" methods.

I hope google's will solve this sh*t fast LoL, I converted all the older "Service" and "IntentService" to the new one jobs but... they work really worst than before!

Bye have a nice coding ;)

Z3R0
  • 1,011
  • 10
  • 19
  • I'm also using the JobIntentService and wanted to use onBind to pass a reference into that service. Seems like this is not really built for that but the onBind was allowing the method to be executed and the reference passed. But now the onHandleWork is not called at all. This class could use some more refinement to limit the use cases. – Sergio Jan 12 '21 at 20:05
  • @SergioCouture Hello (o ciao se sei italiano)! I think that JobIntentService class is bugged because, as u saw, it calls the "OnBind" but after that it never call the "onHandleWork". There are 2 ways to solve that: you can use another class like "Service" where the binding works right or u use the method I wrote above so manually starting the "onHandleWork". It is bad I know, but I didn't find any other solution. Personally I used the "Service" class to handle the binding correctly in my background service which search BLE Tags. Hope this help you! Have a nice day and coding :D – Z3R0 Jan 14 '21 at 08:21
0

I think that I have such problem since I try to toast some text inside onHandleWork() but actually the problem was that it was wrong. I should use a Handler. It may be the problem if one uses for example AsyncTask subclasses to execute on another thread inside onHandleWork() which is a very bad idea.

JJD
  • 50,076
  • 60
  • 203
  • 339
M Shafaei N
  • 409
  • 3
  • 6
-2

For everyone who couldn't solve the problem with the other answers:

Try using different JOB_IDs every time enqueueWork is called. If a previous job hasn't finished, the Service may just be stuck (similar to the problem the user "git pull origin" has described) and a new job with a different ID may solve this issue.

Redaniat
  • 43
  • 7
  • 1
    this causes `java.lang.IllegalArgumentException: Given job ID 1001 is different than previous 1000` – Chisko Jun 10 '20 at 23:45