Context.startForegroundService() did not then call Service.startForeground()

236,235

Solution 1

From Google's docs on Android 8.0 behavior changes:

The system allows apps to call Context.startForegroundService() even while the app is in the background. However, the app must call that service's startForeground() method within five seconds after the service is created.

Solution: Call startForeground() in onCreate() for the Service which you use Context.startForegroundService()

See also: Background Execution Limits for Android 8.0 (Oreo)

Solution 2

I called ContextCompat.startForegroundService(this, intent) to start the service then

In service onCreate

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

        if (Build.VERSION.SDK_INT >= 26) {
            String CHANNEL_ID = "my_channel_01";
            NotificationChannel channel = new NotificationChannel(CHANNEL_ID,
                    "Channel human readable title",
                    NotificationManager.IMPORTANCE_DEFAULT);

            ((NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE)).createNotificationChannel(channel);

            Notification notification = new NotificationCompat.Builder(this, CHANNEL_ID)
                    .setContentTitle("")
                    .setContentText("").build();

            startForeground(1, notification);
        }
}

Solution 3

Why this issue is happening is because Android framework can't guarantee your service get started within 5 second but on the other hand framework does have strict limit on foreground notification must be fired within 5 seconds, without checking if framework had tried to start the service.

This is definitely a framework issue, but not all developers facing this issue are doing their best:

  1. startForeground a notification must be in both onCreate and onStartCommand, because if your service is already created and somehow your activity is trying to start it again, onCreate won't be called.

  2. notification ID must not be 0 otherwise same crash will happen even it's not same reason.

  3. stopSelf must not be called before startForeground.

With all above 3 this issue can be reduced a bit but still not a fix, the real fix or let's say workaround is to downgrade your target sdk version to 25.

And note that most likely Android P will still carry this issue because Google refuses to even understand what is going on and does not believe this is their fault, read #36 and #56 for more information

Solution 4

I know, too many answers have been published already, however the truth is - startForegroundService can not be fixed at an app level and you should stop using it. That Google recommendation to use Service#startForeground() API within 5 seconds after Context#startForegroundService() was called is not something that an app can always do.

Android runs a lot of processes simultaneously and there is no any guarantee that Looper will call your target service that is supposed to call startForeground() within 5 seconds. If your target service didn't receive the call within 5 seconds, you're out of luck and your users will experience ANR situation. In your stack trace you'll see something like this:

Context.startForegroundService() did not then call Service.startForeground(): ServiceRecord{1946947 u0 ...MessageService}

main" prio=5 tid=1 Native
  | group="main" sCount=1 dsCount=0 flags=1 obj=0x763e01d8 self=0x7d77814c00
  | sysTid=11171 nice=-10 cgrp=default sched=0/0 handle=0x7dfe411560
  | state=S schedstat=( 1337466614 103021380 2047 ) utm=106 stm=27 core=0 HZ=100
  | stack=0x7fd522f000-0x7fd5231000 stackSize=8MB
  | held mutexes=
  #00  pc 00000000000712e0  /system/lib64/libc.so (__epoll_pwait+8)
  #01  pc 00000000000141c0  /system/lib64/libutils.so (android::Looper::pollInner(int)+144)
  #02  pc 000000000001408c  /system/lib64/libutils.so (android::Looper::pollOnce(int, int*, int*, void**)+60)
  #03  pc 000000000012c0d4  /system/lib64/libandroid_runtime.so (android::android_os_MessageQueue_nativePollOnce(_JNIEnv*, _jobject*, long, int)+44)
  at android.os.MessageQueue.nativePollOnce (MessageQueue.java)
  at android.os.MessageQueue.next (MessageQueue.java:326)
  at android.os.Looper.loop (Looper.java:181)
  at android.app.ActivityThread.main (ActivityThread.java:6981)
  at java.lang.reflect.Method.invoke (Method.java)
  at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run (RuntimeInit.java:493)
  at com.android.internal.os.ZygoteInit.main (ZygoteInit.java:1445)

As I understand, Looper has analyzed the queue here, found an "abuser" and simply killed it. The system is happy and healthy now, while developers and users are not, but since Google limits their responsibilities to the system, why should they care about the latter two? Apparently they don't. Could they make it better? Of course, e.g. they could've served "Application is busy" dialog, asking a user to make a decision about waiting or killing the app, but why bother, it's not their responsibility. The main thing is that the system is healthy now.

From my observations, this happens relatively rarely, in my case approximately 1 crash in a month for 1K users. Reproducing it is impossible, and even if it's reproduced, there is nothing you can do to fix it permanently.

There was a good suggestion in this thread to use "bind" instead of "start" and then when service is ready, process onServiceConnected, but again, it means not using startForegroundService calls at all.

I think, the right and honest action from Google side would be to tell everyone that startForegourndServcie has a deficiency and should not be used.

The question still remains: what to use instead? Fortunately for us, there are JobScheduler and JobService now, which are a better alternative for foreground services. It's a better option, because of that:

While a job is running, the system holds a wakelock on behalf of your app. For this reason, you do not need to take any action to guarantee that the device stays awake for the duration of the job.

It means that you don't need to care about handling wakelocks anymore and that's why it's not different from foreground services. From implementation point of view JobScheduler is not your service, it's a system's one, presumably it will handle the queue right, and Google will never terminate its own child :)

Samsung has switched from startForegroundService to JobScheduler and JobService in their Samsung Accessory Protocol (SAP). It's very helpful when devices like smartwatches need to talk to hosts like phones, where the job does need to interact with a user through an app's main thread. Since the jobs are posted by the scheduler to the main thread, it becomes possible. You should remember though that the job is running on the main thread and offload all heavy stuff to other threads and async tasks.

This service executes each incoming job on a Handler running on your application's main thread. This means that you must offload your execution logic to another thread/handler/AsyncTask of your choosing

The only pitfall of switching to JobScheduler/JobService is that you'll need to refactor old code, and it's not fun. I've spent last two days doing just that to use the new Samsung's SAP implementation. I'll watch my crash reports and let you know if see the crashes again. Theoretically it should not happen, but there are always details that we might not be aware of.

UPDATE No more crashes reported by Play Store. It means that JobScheduler/JobService do not have such a problem and switching to this model is the right approach to get rid of startForegroundService issue once and forever. I hope, Google/Android reads it and will eventually comment/advise/provide an official guidance for everyone.

UPDATE 2

For those who use SAP and asking how SAP V2 utilizes JobService explanation is below.

In your custom code you'll need to initialize SAP (it's Kotlin) :

SAAgentV2.requestAgent(App.app?.applicationContext, 
   MessageJobs::class.java!!.getName(), mAgentCallback)

Now you need to decompile Samsung's code to see what's going on inside. In SAAgentV2 take a look at the requestAgent implementation and the following line:

SAAgentV2.d var3 = new SAAgentV2.d(var0, var1, var2);

where d defined as below

private SAAdapter d;

Go to SAAdapter class now and find onServiceConnectionRequested function that schedules a job using the following call:

SAJobService.scheduleSCJob(SAAdapter.this.d, var11, var14, var3, var12); 

SAJobService is just an implementation of Android'd JobService and this is the one that does a job scheduling:

private static void a(Context var0, String var1, String var2, long var3, String var5, SAPeerAgent var6) {
    ComponentName var7 = new ComponentName(var0, SAJobService.class);
    Builder var10;
    (var10 = new Builder(a++, var7)).setOverrideDeadline(3000L);
    PersistableBundle var8;
    (var8 = new PersistableBundle()).putString("action", var1);
    var8.putString("agentImplclass", var2);
    var8.putLong("transactionId", var3);
    var8.putString("agentId", var5);
    if (var6 == null) {
        var8.putStringArray("peerAgent", (String[])null);
    } else {
        List var9;
        String[] var11 = new String[(var9 = var6.d()).size()];
        var11 = (String[])var9.toArray(var11);
        var8.putStringArray("peerAgent", var11);
    }

    var10.setExtras(var8);
    ((JobScheduler)var0.getSystemService("jobscheduler")).schedule(var10.build());
}

As you see, the last line here uses Android'd JobScheduler to get this system service and to schedule a job.

In the requestAgent call we've passed mAgentCallback, which is a callback function that will receive control when an important event happens. This is how the callback is defined in my app:

private val mAgentCallback = object : SAAgentV2.RequestAgentCallback {
    override fun onAgentAvailable(agent: SAAgentV2) {
        mMessageService = agent as? MessageJobs
        App.d(Accounts.TAG, "Agent " + agent)
    }

    override fun onError(errorCode: Int, message: String) {
        App.d(Accounts.TAG, "Agent initialization error: $errorCode. ErrorMsg: $message")
    }
}

MessageJobs here is a class that I've implemented to process all requests coming from a Samsung smartwatch. It's not the full code, only a skeleton:

class MessageJobs (context:Context) : SAAgentV2(SERVICETAG, context, MessageSocket::class.java) {


    public fun release () {

    }


    override fun onServiceConnectionResponse(p0: SAPeerAgent?, p1: SASocket?, p2: Int) {
        super.onServiceConnectionResponse(p0, p1, p2)
        App.d(TAG, "conn resp " + p1?.javaClass?.name + p2)


    }

    override fun onAuthenticationResponse(p0: SAPeerAgent?, p1: SAAuthenticationToken?, p2: Int) {
        super.onAuthenticationResponse(p0, p1, p2)
        App.d(TAG, "Auth " + p1.toString())

    }


    override protected fun onServiceConnectionRequested(agent: SAPeerAgent) {


        }
    }

    override fun onFindPeerAgentsResponse(peerAgents: Array<SAPeerAgent>?, result: Int) {
    }

    override fun onError(peerAgent: SAPeerAgent?, errorMessage: String?, errorCode: Int) {
        super.onError(peerAgent, errorMessage, errorCode)
    }

    override fun onPeerAgentsUpdated(peerAgents: Array<SAPeerAgent>?, result: Int) {

    }

}

As you see, MessageJobs requires MessageSocket class as well that you would need to implement and that processes all messages coming from your device.

Bottom line, it's not that simple and it requires some digging to internals and coding, but it works, and most importantly - it doesn't crash.

Solution 5

Your app will crash if you call Context.startForegroundService(...) and then call Context.stopService(...) before Service.startForeground(...) is called.

I have a clear repro here ForegroundServiceAPI26

I have opened a bug on this at : Google issue tracker

Several bugs on this have been opened and closed Won't Fix.

Hopefully mine with clear repro steps will make the cut.

Information provided by google team

Google issue tracker Comment 36

This is not a framework bug; it's intentional. If the app starts a service instance with startForegroundService(), it must transition that service instance to the foreground state and show the notification. If the service instance is stopped before startForeground() is called on it, that promise is unfulfilled: this is a bug in the app.

Re #31, publishing a Service that other apps can start directly is fundamentally unsafe. You can mitigate that a bit by treating all start actions of that service as requiring startForeground(), though obviously that may not be what you had in mind.

Google issue tracker Comment 56

There are a couple of different scenarios that lead to the same outcome here.

The outright semantic issue, that it's simply an error to kick something off with startForegroundService() but neglect to actually transition it to foreground via startForeground(), is just that: a semantic issue. That's treated as an app bug, intentionally. Stopping the service before transitioning it to foreground is an app error. That was the crux of the OP, and is why this issue has been marked "working as intended."

However, there are also questions about spurious detection of this problem. That's is being treated as a genuine problem, though it's being tracked separately from this particular bug tracker issue. We aren't deaf to the complaint.

Share:
236,235
NiceGuy
Author by

NiceGuy

Updated on July 15, 2022

Comments

  • NiceGuy
    NiceGuy almost 2 years

    I am using Service Class on the Android O OS.

    I plan to use the Service in the background.

    The Android documentation states that

    If your app targets API level 26 or higher, the system imposes restrictions on using or creating background services unless the app itself is in the foreground. If an app needs to create a foreground service, the app should call startForegroundService().

    If you use startForegroundService(), the Service throws the following error.

    Context.startForegroundService() did not then call
    Service.startForeground() 
    

    What's wrong with this?

  • Kimi Chiu
    Kimi Chiu over 6 years
    I did this in the onStartCommand method, but I'm still getting this error. I called startForegroundService(intent) in my MainActivity. Maybe the service is started too slow. I think the five seconds limit should not exist before they can promise the service is started immediately.
  • Kimi Chiu
    Kimi Chiu over 6 years
    Me too. But I'm still getting this error occasionally. Maybe the Android can't guarantee it will call the onCreate in 5 seconds. So they should redesign it before they force us follow the rules.
  • Tyler
    Tyler over 6 years
    I was calling startForeground in onStartCommand(), and I was occasionally getting this error. I moved it to onCreate and I haven't seen it since (crossing fingers).
  • Artist404
    Artist404 over 6 years
    This creates a local notification in Oreo saying "APP_NAME is running. Tap to close or see info". How to stop showing that notification?
  • humazed
    humazed over 6 years
    you can't if you want to run Foreground service this is a new restriction introduced in android o.
  • Artist404
    Artist404 over 6 years
    @KimiChiu was doing exactly same but still it was crashing, but only while i was in the foreground so I put a check on the ContextCompat.startForegroundService(this, intent) , if app is in foreground do ContextCompat.startService(this, intent), but if it is in background then only do ContextCompat.startForegroundService(this, intent). Check if it helps
  • Kimi Chiu
    Kimi Chiu over 6 years
    No, the Android Team claimed this is an intended behavior. So I just redesigned my app. This is ridiculous. Always need to redesign apps due to these "intended behavior". It's the third time.
  • Kimi Chiu
    Kimi Chiu over 6 years
    The main cause of this problem is the service was stopped before it was promoted to the foreground. But the assertion didn't stop after the service get destroyed. You can try to reproduce this by adding StopService after calling startForegroundService.
  • southerton
    southerton about 6 years
    5 seconds period is definitely not enough, this exception happens very often in debug sessions. I suspect it also WOULD happen in release mode from time to time. And being FATAL EXCEPTION it just crashes the app! I tried to catch it with Thread.setDefaultUncaughtExceptionHandler(), but even on getting it there and ignoring android freezes the application. That's becuase this exception is triggered from handleMessage(), and main loop effectively ends... looking for workaround.
  • Amrut
    Amrut about 6 years
    Do we need to make these changes in case of JobIntentService? Or it is handling it internally?
  • humazed
    humazed about 6 years
    no, the job classes are created to handle the background work in android Oreo. so you don't need to show notification.
  • Alex
    Alex about 6 years
    Did you tried it in some app that has at least several thousands users? I tried, some users still have the crash issues.
  • Ahmad Arslan
    Ahmad Arslan about 6 years
    No no I am using the exact code and I don't see the clients getting crash.
  • Alex
    Alex about 6 years
    How much users u have? I seen ~10-30+ crashes daily (with the error) in app that had 10k users per day. Of course, it happens only for users with android 8.0 and android 8.1, in case targetSdkVersion is 27. All the problems disappear to 0 crashes right after I set targetSdkVersion to 25.
  • Ahmad Arslan
    Ahmad Arslan about 6 years
    only 2200 user :-/ but did not get any crash
  • southerton
    southerton about 6 years
    I was getting this exception quite often in debug mode, finally decided to catch the exception with custom exception handler and keep the app running. choruscode.blogspot.com/2018/05/…
  • Ahmad Arslan
    Ahmad Arslan almost 6 years
    @Alex strange I am getting the ANR on nexus and HTC devices :( do you have any solution ?
  • Jeeva
    Jeeva almost 6 years
    @Alex how did you fix this issue??
  • Ahmad Arslan
    Ahmad Arslan almost 6 years
    I was using intent service right inside of this foreground service which creates error and sometimes crashes, I have removed it and worked perfectly well
  • Alex
    Alex almost 6 years
    @Jeeva, not really. Atm, I use targetSdkVersion 25 with compileSdkVersion 27. It looks likes the best way after lot of experiments.... Hope they will finish developer.android.com/topic/libraries/architecture/… before August 2018 because android-developers.googleblog.com/2017/12/…
  • Jeeva
    Jeeva almost 6 years
    @Alex Thanks mate let me know if you have any better solutions
  • swooby
    swooby almost 6 years
    Best update I have seen is issuetracker.google.com/issues/76112072#comment56. I rewrote my code to use Context.bindService which completely avoids the problematic call to Context.startForegroundService. You can see my sample code at github.com/paulpv/ForegroundServiceAPI26/tree/bound/app/src/‌​…
  • Anand Savjani
    Anand Savjani almost 6 years
    I called Context.startForegroundService() method in broadcast receiver. so how to handle in this situation? because onCreate() is not available in broadcast receiver
  • rcell
    rcell almost 6 years
    Why both onCreate and onStartCommand? Can you just put it in onStartCommand?
  • Vasily Kabunov
    Vasily Kabunov over 5 years
    Don't forget to add setSmallIcon method to the chain of builder methods, otherwise the default notification "App is running" will be shown
  • Marlon
    Marlon over 5 years
    Don't use higher numbers for the notification ID also. Try to use one digit IDs. stackoverflow.com/a/12228555/2527204
  • Amin Pinjari
    Amin Pinjari over 5 years
    In my case I was using ID 1, thanks, issue got resolved
  • makovkastar
    makovkastar over 5 years
    You should call it instead of context.stopService(serviceIntent) when you want to stop the service.
  • CopsOnRoad
    CopsOnRoad over 5 years
    I am using ID 101, still I receive this error sometimes.
  • M. Usman Khan
    M. Usman Khan over 5 years
    If I call startForeground in onCreate(), then even startService() will start it in foreground. what's the purpose of startForegroundService()?
  • Frank
    Frank over 5 years
    stopSelf must not be called before startForeground => or directly after, because it seems to cancel the "startForeground" when you do.
  • Gerry
    Gerry about 5 years
    FATAL EXCEPTION: main android.app.RemoteServiceException: Bad notification for startForeground: java.lang.RuntimeException: invalid channel for service notification: Notification(channel=null pri=0 contentView=null vibrate=null sound=null defaults=0x0 flags=0x40 color=0x00000000 vis=PRIVATE) at android.app.ActivityThread$H.handleMessage(ActivityThread.ja‌​va:1821) at android.os.Handler.dispatchMessage(Handler.java:106) at android.os.Looper.loop(Looper.java:164) at android.app.ActivityThread.main(ActivityThread.java:6626)
  • Andris
    Andris about 5 years
    Should be Util.SDK_INT >= 26, not just bigger
  • android developer
    android developer about 5 years
    @southerton I think you should call it on onStartCommand() instead of onCreate, because if you close the service and start it again, it might go to onStartCommand() without calling onCreate ...
  • Prags
    Prags about 5 years
    We can check response from google team here issuetracker.google.com/issues/76112072#comment56
  • Lxu
    Lxu almost 5 years
    I executed some tests, and even if onCreate is not called if the service is already created, you don't need to call startForeground again. Hence you could call it only on the onCreate method and not in the onStartCommand. Probably they consider the single instance of service as being in foreground after the first call till its end.
  • matdev
    matdev almost 5 years
    This causes a crash "Bad notification for startForeground: java.lang.RuntimeException: invalid channel for service notification". Also, Notification.Builder is deprecated as of API 26
  • user3135923
    user3135923 almost 5 years
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { stopForeground(true); } else { stopForeground(true); } what is this if else for? both case you were doing the same, stopForeground(true);
  • DarShan
    DarShan almost 5 years
    no need for version check manually, simply use ContextCompat.startForegroundService(), it will do that for you.
  • Justin Stanley
    Justin Stanley almost 5 years
    I believe you meant to put stopSelf(); inside of the else block instead of stopForeground(true);
  • sandy
    sandy almost 5 years
    Yes, @JustinStanley use stopSelf();
  • CopsOnRoad
    CopsOnRoad over 4 years
    Good answer but there is a major issue, JobIntentService runs immediately as an IntentService below Oreo, but schedules a Job on and above Oreo, so JobIntentService doesn't start immediately. More info
  • Oleg Gryb
    Oleg Gryb over 4 years
    @CopsOnRoad Service doesn't start immediately when you call startFregroundService either. It starts when Mr. Looper decides to start it, which is obvious from the stack trace, and that's actually the root cause of the problem.
  • CopsOnRoad
    CopsOnRoad over 4 years
    You're right foreground service may not start within 5 seconds of the time limit (and Google is the one to be blamed for this), but JobService is for like 15 mins interval stuff, I upvoted your post because the approach is good but not useful.
  • Oleg Gryb
    Oleg Gryb over 4 years
    @CopsOnRoad It's very useful and it starts immediately in my case, As I wrote, it is used for real time interactions between phone and a smartwatch. No way, a user would wait 15 minutes to send data between these two. Works very well and never crashes.
  • CopsOnRoad
    CopsOnRoad over 4 years
    Sounds cool, would make your answer much worth if you can share some sample code, I am new to Android, and found that Job... takes time to start and it is advance version of AlarmManager.
  • Oleg Gryb
    Oleg Gryb over 4 years
    Probably I will when time permits: I'll need to de-couple it from custom-specific code and de-compile some proprietary Samsung libs
  • CopsOnRoad
    CopsOnRoad over 4 years
    No worries, take your time. Good day!
  • Aba
    Aba over 4 years
    Shouldn't startForeground be called in onCreate?
  • Prajwal Waingankar
    Prajwal Waingankar over 4 years
    I m using NotificationManager and not Notification class. How can i implement this?
  • mr5
    mr5 over 4 years
    I'm using 0 as the notification ID of the initial call for startForeground. Changing it to 1 fixes the issue for me (hopefully)
  • Emil
    Emil over 4 years
    hey, i just voted your comment up because i am exactly looking for SAP for samsung. Do you have any code sample or github repo where i can see your implementation.
  • Oleg Gryb
    Oleg Gryb over 4 years
    @batmaci I used examples provided by Samsung in AccessorySDK_v2.6.1.zip. Go to Samples(Web), find HelloMessage, Provider(Android)_Consumer(Tizen) and see ProviderActiviy.java and ProviderService.java. I had to convert them to Kotlin in my case.
  • Emil
    Emil over 4 years
    @OlegGryb when you use JobService, does it work independent than provider android app. Currently with Foreground service, I am updating Provider app on real time using Consumer watch app. Are you able to do this? FitnesPall app has interesting implementation. When you start watch app, it automatically initializes fitnesspall service on your android phone. I guess that they use job instead of foregroundservice
  • Oleg Gryb
    Oleg Gryb over 4 years
    @batmaci - JobService is used by SAP internally. See Update 2 in OP for details.
  • Emil
    Emil over 4 years
    quick quesiton: SAAgentV2.requestAgent - where do you call this? within mainactivity oncreate? using SAAgent it wasnt required as it it was registered automatically.
  • Emil
    Emil over 4 years
    @OlegGryb i achieved connection using SAAgentV2 and tested it yesterday for an hour between my watch and phone. it is fluent. Amazing how awesome is the connection without dropping. thank you for your help. I did it using xamarin.android and with c# was bit trickier from java and kotlin ;) now have to check in older android versions if it works also.
  • Oleg Gryb
    Oleg Gryb about 4 years
    yes, as I wrote, bind should work, but I've switched already to JobServive and am not going to change anything unless this one gets broken too ':)
  • IgorGanapolsky
    IgorGanapolsky about 4 years
    So what is the solution?
  • Mateen Chaudhry
    Mateen Chaudhry about 4 years
    in some Xiaomi devices activities can't be started from the background
  • Mateen Chaudhry
    Mateen Chaudhry about 4 years
    you are starting your service from background or in activity?
  • a54studio
    a54studio about 4 years
    Background. The problem is that Android can't guarantee the service will start in the allotted time. One would think they would just throw an error to ignore it if you want, but alas, not Android. It has to be fatal. This helped in our app, but didn't fix it totally.
  • a54studio
    a54studio about 4 years
    This actually just kicks the service to startService rather than startForegroundService if null. The if statement would have to be nested, otherwise the app would crash trying to use services on a later version at some point.
  • Dmytro Rostopira
    Dmytro Rostopira almost 4 years
    But, according to docs, stopForeground ...does not stop the service from running (for that you use stopSelf() or related methods)
  • Roy Solberg
    Roy Solberg almost 4 years
    @DimaRostopira Yes, in practice I see the system taking care of stopping the service from running after being inactive for a while (maybe a minute). It isn't ideal, but it stops the system from complaining.
  • Atif Waqar
    Atif Waqar over 3 years
    That was a quick solution. Thanks ^^
  • fsljfke
    fsljfke over 3 years
    I think the first comment about it not running immediately is right. I am experiencing this. I am using a widget button to start a JobIntentService.
  • gregko
    gregko over 3 years
    Thank you, just implemented your solution in an app with well over 5M installs, let's see. Hope for the best.
  • JohnnyLambada
    JohnnyLambada over 3 years
    My app has this permission yet is still experiencing the issue described in the question.
  • Shrdi
    Shrdi over 3 years
    @JohnnyLambada it seems only an activity can startForgroundService, try to startService in background instead.
  • gregko
    gregko over 3 years
    It works for me so far - almost a month later and no more crashes or ANRs related to startForegroundService() - Thanks!
  • user924
    user924 over 3 years
    you don't need to create a service to stop it, just use local broadcast manager ))
  • Gaurav Singla
    Gaurav Singla over 3 years
    Its not a different Service. Its the same service which I want to stop!
  • user924
    user924 over 3 years
    I didn't say anything about different service, I mean why are you trying to stop while it's being started?
  • user924
    user924 over 3 years
    use broadcast locale messages
  • Gaurav Singla
    Gaurav Singla over 3 years
    Dear user924, If I have to stop the service, There is no need to BroadCast too, I can call context.stopService() directly. Above answer is a trick to solve the issue happening on Samsung devices in case you stop the service just before its onStartCommand is actually called.
  • Malachiasz
    Malachiasz over 3 years
    I have been calling startForeground() in both onCreate() and onStartCommand() and I have no issues. Before when I had in one of them there were some crashes.
  • Malachiasz
    Malachiasz over 3 years
    I had also the issue that foreground notification was not removed, when my service was very short running. Adding 100ms delay before the call to stopForeground(true); stopSelf(); has helped. Your solution did not help. (Pixel 3, Android 11)
  • Duna
    Duna over 3 years
    I have an app that has 30k active users on Play Store. And I have the same issue: ~30 daily crashes on Android 8+ because of 5 sec time limit to start foreground. Crashes comes from various devices, even this year phones releases(S20Ultra, Motorola...)The Android design does not guarantee the call will be triggered within 5 sec and the service get killed by the OS. Google has a long list of feedback regarding this issue but they do not admit this is design flaw. They should redesign it better before for force us to drop background services.
  • user924
    user924 over 3 years
    @OlegGryb Does JobService work all the time?. For example will it work for background video recording with screen turned of for 24 hours?
  • user924
    user924 over 3 years
    So this is wrong to call JobService as good replacement, cause it can't run all the time, only sticky foreground service can do it
  • MikkelT
    MikkelT about 3 years
    Tried this on my app (200k MAU) and still get this error. Mostly Samsung it seems for some reason (maybe statistical, but idk).
  • thirtyyuan
    thirtyyuan about 3 years
    Some phone like VIVO, you will still crash even if you are call stopService() after startForeground(), on Android 8.1. see: my logcat
  • lasec0203
    lasec0203 about 3 years
    @swooby your solution helped me greatly.
  • user924
    user924 about 3 years
    the question is too old for Android 12
  • user924
    user924 about 3 years
    why do make it foreground only for Oreo, nonsense
  • user924
    user924 about 3 years
    a tricky solution, I will try it, have 80k active users in my app
  • user924
    user924 about 3 years
    because if your service is already created and somehow your activity is trying to start it again, onCreate won't be called. - if service was started before then this service is already in foreground because it becomes foreground in onCreate, so this sentence doesn't make any sense...
  • user924
    user924 about 3 years
    what an offtopic question. it's not about oreo, it still will crash from time to time, just test it with app which has at least 30K users
  • user924
    user924 about 3 years
    you are so smart!!! we all do it... but boy your users will still face crash from time to time
  • user924
    user924 about 3 years
    in my case it's not possible because I don't use context.stopService. I send local broadcast from activity to stop service, service registers to this broadcast, calls stopSelf, so it stops itself, when it calls stopSelf, startForeground was called before 100%
  • user924
    user924 about 3 years
    but you have to unbind service in onStop of activity cycle
  • user924
    user924 about 3 years
    ` // This is the key: Without waiting Android Framework to call this method // inside Service.onCreate(), immediately call here to post the notification.` - I'm not sure about this, how can you start notification before onCreate of Service was called. And when onServiceConnected was called, then it means onCreate was already called, so there is quite nonsense in your sentence
  • user924
    user924 about 3 years
    myService.startForeground(myNotificationId, MyService.getNotification()); you can move it to onCreate, because onServiceConnected is called after onCreate!!!
  • user924
    user924 about 3 years
    this is still didn't help, I have 80K active users (200K downloads)
  • user924
    user924 about 3 years
    this is still didn't help, I have 80K active users (200K downloads)
  • Hexise
    Hexise about 3 years
    @user924 As I mentioned, it can reduce at least 95% of this kind of crash, but still cannot 100% avoid this problem. I did not find a way to solve this exception 100%. Sorry.
  • CopsOnRoad
    CopsOnRoad almost 3 years
    @RavindraKushwaha Not really.
  • Malachiasz
    Malachiasz over 2 years
    How is this a solution if Context.startForeground() is necessary to start a service from the app's in background state?
  • zelig74
    zelig74 over 2 years
    Although this solution is recommended by @CommonsWare in his comment stackoverflow.com/questions/55894636/…, it doesn't work perfectly. After calling startForeground() unbindService(), the service is sometimes destroyed by system, and immediately started again. When the service initializes a worker thread during startup, we get an Error java.lang.InternalError: Thread starting during runtime shutdown :-(
  • Beloo
    Beloo over 2 years
    @user924 Your comments to this topic are quite reasonable. Have you found a solution? I'm also struggling to find one. Looks like the best option we can do is to ensure that startForegroundService is called when an app is not overloaded. For example calling it on an app initialization should be avoided.
  • DIRTY DAVE
    DIRTY DAVE over 2 years
    I had wasted so much time figuring out why it was crashing and not understanding why. The issue was the notification ID for startForeground(). Change it to something other than 0.
  • Vicente Domingos
    Vicente Domingos over 2 years
    If you are testing on your AVD, remove the code: startService(serviceIntent). Well, AVD will always try to run this code - but it will find a version greater than 26.
  • Hzzkygcs
    Hzzkygcs over 2 years
    I'm using 0 as the notification ID of the initial call for startForeground. Changing it to 1 fixes the issue for me (hopefully) This solution resolved my problem too. Has anyone figured out why it is the way it is?
  • ManxJason
    ManxJason over 2 years
    Fixed it for us, thanks.
  • Martin Zeitler
    Martin Zeitler about 2 years
    Randomizing the NOTIFICATION_ID is quite problematic - a public static constant would be better, because one needs it to update the Notification later on ...anything but 0 works.
  • Emil
    Emil almost 2 years
    onCreate is called before onStartCommand i thought. are you not doing otherway around here?
  • Emil
    Emil almost 2 years
    do you mean that startService will still work for all SDK versions?
  • Gaurav Singla
    Gaurav Singla almost 2 years
    @Emil You are right. Idea to let the onCreate complete and stop the service from onStartCommand. So that OS thinks onCreate was called, Notification was shown, finally stopped and won't throw the exception.
  • Kunal Kalwar
    Kunal Kalwar almost 2 years
    Guys see my answer its working for me stackoverflow.com/a/72754189/12228079
  • Kunal Kalwar
    Kunal Kalwar almost 2 years
    Guys see my answer its working for me stackoverflow.com/a/72754189/12228079
  • Kunal Kalwar
    Kunal Kalwar almost 2 years
    Guys see my answer its working for me stackoverflow.com/a/72754189/12228079
  • Kunal Kalwar
    Kunal Kalwar almost 2 years
    Guys see my answer its working for me stackoverflow.com/a/72754189/12228079
  • Kunal Kalwar
    Kunal Kalwar almost 2 years
    Guys see my answer its working for me stackoverflow.com/a/72754189/12228079
  • Kunal Kalwar
    Kunal Kalwar almost 2 years
    Guys see my answer its working for me stackoverflow.com/a/72754189/12228079
  • Kunal Kalwar
    Kunal Kalwar almost 2 years
    Guys see my answer its working for me stackoverflow.com/a/72754189/12228079
  • Kunal Kalwar
    Kunal Kalwar almost 2 years
    Guys see my answer its working for me stackoverflow.com/a/72754189/12228079
  • Kunal Kalwar
    Kunal Kalwar almost 2 years
    Guys see my answer its working for me stackoverflow.com/a/72754189/12228079
  • Kunal Kalwar
    Kunal Kalwar almost 2 years
    Guys see my answer its working for me stackoverflow.com/a/72754189/12228079
  • Kunal Kalwar
    Kunal Kalwar almost 2 years
    Guys see my answer its working for me stackoverflow.com/a/72754189/12228079
  • Kunal Kalwar
    Kunal Kalwar almost 2 years
    Guys see my answer its working for me stackoverflow.com/a/72754189/12228079
  • Kunal Kalwar
    Kunal Kalwar almost 2 years
    Guys see my answer its working for me stackoverflow.com/a/72754189/12228079
  • Kunal Kalwar
    Kunal Kalwar almost 2 years
    Guys see my answer its working for me stackoverflow.com/a/72754189/12228079
  • Kunal Kalwar
    Kunal Kalwar almost 2 years
    Guys see my answer its working for me stackoverflow.com/a/72754189/12228079
  • Kunal Kalwar
    Kunal Kalwar almost 2 years
    Guys see my answer its working for me stackoverflow.com/a/72754189/12228079
  • Kunal Kalwar
    Kunal Kalwar almost 2 years
    Guys see my answer its working for me stackoverflow.com/a/72754189/12228079
  • Kunal Kalwar
    Kunal Kalwar almost 2 years
    Guys see my answer its working for me stackoverflow.com/a/72754189/12228079
  • Kunal Kalwar
    Kunal Kalwar almost 2 years
    Guys see my answer its working for me stackoverflow.com/a/72754189/12228079
  • Kunal Kalwar
    Kunal Kalwar almost 2 years
    Guys see my answer its working for me stackoverflow.com/a/72754189/12228079
  • Dan Alboteanu
    Dan Alboteanu almost 2 years
    this is what I needed inside Manifest to be able to continue Play Audio <service android:name=".common.audio.AudioPlayerService" android:foregroundServiceType="mediaPlayback" ....