title: Context.startForegroundService() did not then call Service.startForeground()?
body: <p>I have hundred of crashes reported by my users and I still can't find a fix for it. These crashes are coming from Android 8 (Samsung, Huawei, Google).</p>
  
  <p>I am getting these two crashes:</p>
  
  <pre><code>Fatal Exception: android.app.RemoteServiceException: Context.startForegroundService() did not then call Service.startForeground()
         at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1881)
         at android.os.Handler.dispatchMessage(Handler.java:105)
         at android.os.Looper.loop(Looper.java:164)
         at android.app.ActivityThread.main(ActivityThread.java:6938)
         at java.lang.reflect.Method.invoke(Method.java)
         at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:327)
         at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1374)
  </code></pre>
  
  <p>and the other one:</p>
  
  <pre><code>Fatal Exception: android.app.RemoteServiceException: Context.startForegroundService() did not then call Service.startForeground()
         at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2104)
         at android.os.Handler.dispatchMessage(Handler.java:108)
         at android.os.Looper.loop(Looper.java:166)
         at android.app.ActivityThread.main(ActivityThread.java:7428)
         at java.lang.reflect.Method.invoke(Method.java)
         at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:245)
         at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:921)
  </code></pre>
  
  <p>I assume these crashes are the same, but as you can see the stack trace shows different line of code.</p>
  
  <p>The problem is that I can't reproduce it, everything works fine on my devices and my emulator. However, I (somehow) reproduced by creating a service without calling the <code>startForeground()</code> within the <code>Service</code> class.</p>
  
  <p>I'm unable to "catch" the exception, because it comes from system-level right after 5 seconds when the service was created.</p>
  
  <p>What have I done is that I have created a method which creates a sticky notification and calling the <code>startForeground</code> method (my Service class):</p>
  
  <pre><code>private void startWithNotification() {
       Resources res = getResources();
       String title = res.getString(R.string.application_name);
  
       if (Build.VERSION.SDK_INT &gt;= Build.VERSION_CODES.O) {
           createChannels();
       }
  
       NotificationCompat.Builder builder =  new NotificationCompat.Builder(context, ANDROID_CHANNEL_ID)
               .setContentTitle(title)
               .setChannelId(ANDROID_CHANNEL_ID)
               .setCategory(NotificationCompat.CATEGORY_SERVICE)
               .setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
               .setPriority(NotificationCompat.PRIORITY_DEFAULT)
               .setOngoing(true)
               .setAutoCancel(false)
               .setSmallIcon(R.drawable.ic_siluette)
               .setColor(ContextCompat.getColor(this, R.color.colorPrimary))
               .setLargeIcon(BitmapFactory.decodeResource(getResources(), R.drawable.application_icon));
  
       startForeground(NOTIFICATION_APP, builder.build());
   }
  
   private void createChannels() {
       // create android channel
       NotificationChannel androidChannel = new NotificationChannel(ANDROID_CHANNEL_ID, ANDROID_CHANNEL_NAME, NotificationManager.IMPORTANCE_DEFAULT);
       // Sets whether notifications posted to this channel should display notification lights
       androidChannel.enableLights(true);
       // Sets whether notification posted to this channel should vibrate.
       androidChannel.enableVibration(true);
       // Sets the notification light color for notifications posted to this channel
       androidChannel.setLightColor(Color.GREEN);
       // Sets whether notifications posted to this channel appear on the lockscreen or not
          androidChannel.setLockscreenVisibility(Notification.VISIBILITY_PRIVATE);
  
       NotificationManager nm = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
  
       nm.createNotificationChannel(androidChannel);
   }
  </code></pre>
  
  <p>This method is getting called from different Service life-cycle-events:</p>
  
  <pre><code>onCreate()
  onStartCommand()
  stopService()
  onDestroy()
  </code></pre>
  
  <p>I am calling the method within these events, because people said that the Service might not being created and it's automatically destroyed.</p>
  
  <p>The service gets started when an incoming or an outgoing call is made via <code>BroadcastReceiver</code>:</p>
  
  <pre><code>public class IncomingOutgoingCallReceiver extends BroadcastReceiver {
     private void callAppService(Context context, int callType) {
          Intent intent = new Intent(context, MyService.class);
          Bundle bundle = new Bundle();
          bundle.putInt(CALL_TYPE, callType);
          intent.putExtras(bundle);
  
          if (Build.VERSION.SDK_INT &gt;= Build.VERSION_CODES.O) {
              context.startForegroundService(intent);
          }
          else {
              context.startService(intent);
          }
      }
  
      private void onCallEnd(Context context) {
         context.stopService(new Intent(context, MyService.class));
      }
  }
  </code></pre>
  
  <p>The Service class:</p>
  
  <pre><code>public class MyService extends Service {
  
      private void handleIntent(Intent intent) {
          // Use intent data and do work
  
          if (canStartService(intent)) {
              return;
          }
      }
  
      private boolean canStartService(Intent intent) {
          // multiple checks
          // if (intent bundle contains ... ) return false;
          // if (phone number contains .... ) return false;
  
          return true;
      }
  
      @Override
      public void onCreate() {
          super.onCreate();
  
          startWithNotification();
      }
  
      @Override
      public int onStartCommand(Intent intent, int flags, int startId) {
  
          handleIntent(intent);
          startWithNotification();
  
          return START_NOT_STICKY;
      }
  
      private void startWithNotification() {
          // Contains the code from above (didn't put here because of space)
      }
  
      @Override
      public boolean stopService(Intent name) {
          startWithNotification();
  
          return super.stopService(name);
      }
  
      // Can be called from different Views which are attached to the WindowManager (user interacting with the UI)
      public void stopService() {
          startWithNotification();
  
          stopForeground(true);
          stopSelf();
      }
  
      @Override
      public void onDestroy() {
          startWithNotification();
  
          super.onDestroy();
      }
  
      @Nullable
      @Override
      public IBinder onBind(Intent intent) {
          return null;
      }
  }
  </code></pre>