Question

I have an IntentService and I want to make it sticky with an ongoing notification. The problem is that the notification appears and then disappears immediately. The service continues to run. How should I use startForeground() in an IntentService?

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    super.onStartCommand(intent, flags, startId);
    Notification notification = new Notification(R.drawable.marker, "Notification service is running",
            System.currentTimeMillis());
    Intent notificationIntent = new Intent(this, DashboardActivity.class);
    notificationIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP|
        Intent.FLAG_ACTIVITY_SINGLE_TOP);
    PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);
    notification.setLatestEventInfo(this, "App",
            "Notification service is running", pendingIntent);
    notification.flags|=Notification.FLAG_NO_CLEAR;
    startForeground(1337, notification);
    return START_STICKY;
}

@Override
protected void onHandleIntent(Intent intent) {

    String id = intent.getStringExtra(ID);
    WebSocketConnectConfig config = new WebSocketConnectConfig();
    try {
        config.setUrl(new URI("ws://" + App.NET_ADDRESS
                + "/App/socket?id="+id));
    } catch (URISyntaxException e) {
        e.printStackTrace();
    }
    ws = SimpleSocketFactory.create(config, this);
    ws.open();
}

Thanks

Was it helpful?

Solution

This should not be an IntentService. As written, your IntentService will live for a millisecond or so. Once onHandleIntent() returns, the service is destroyed. This should be a regular Service, where you fork your own thread and manage the lifetime of the thread and the service.

The reason your Notification is going away immediately is because the service is going away immediately.

OTHER TIPS

As documentation for IntentService states:

...the service is started as needed, handles each Intent in turn using a worker thread, and stops itself when it runs out of work.

So, I suppose the problem, is that your service is out of work after onHandleIntent() is finished. Hence, service stops itself and notification is dissmissed. So, concept of IntentService is probably not the best case for your task.


As question's title is "StartForeground for IntentService", I would like to clarify some things:

It's really simple to make your IntentService to run in foreground (see code below), but for sure you need to consider several things:

  • Don't run service in foreground if it takes a few seconds only - that might bug your users. Imagine you run short tasks periodically - that will cause notification to appear and disappear - uhhhh*

  • You might need to make your service capable to keep device awake (but that's another story, which is covered pretty well on stackoverflow)*

  • If you queued up multiple Intents to your IntentService the below code will end up showing/hiding notification. (So there might be better solution for your case - as @CommonsWare suggests to extend Service and do everything yourself, however would like to mention - there is nothing in javadoc for IntentService saying that it works only a few seconds - it works as long as it has to do something.)


public class ForegroundService extends IntentService {

    private static final String TAG = "FrgrndSrv";

    public ForegroundService() {
        super(TAG);
    }

    @Override
    protected void onHandleIntent(Intent intent) {

        Notification.Builder builder = new Notification.Builder(getBaseContext())
                .setSmallIcon(R.drawable.ic_foreground_service)
                .setTicker("Your Ticker") // use something from something from R.string
                .setContentTitle("Your content title") // use something from something from
                .setContentText("Your content text") // use something from something from
                .setProgress(0, 0, true); // display indeterminate progress

        startForeground(1, builder.build());
        try {
            doIntesiveWork();
        } finally {
            stopForeground(true);
        }
    }

    protected void doIntesiveWork() {
        // Below should be your logic that takes lots of time
        try {
            Thread.sleep(10000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top