0

In our Application class in onCreate we have following code:

public class MyApplication extends Application {

@Override
public void onCreate() {
  super.onCreate();    
  if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O
                            && ((PowerManager) context.getSystemService(Context.POWER_SERVICE)).isIgnoringBatteryOptimizations(context.getPackageName())) {
      final Intent pendingIntent= new Intent(context, ScheduledUpdateService.class);
      startService(pendingIntent);
  }
}
}

On the line "startService()" we get many crashes according to Firebase Crashyltics:

Caused by java.lang.IllegalStateException: Not allowed to start service Intent { ... PairActivityUserId=11 }: app is in background uid UidRecord{3ec0561 u11a247 SVC  idle procs:1 seq(0,0,0)}
       at android.app.ContextImpl.startServiceCommon(ContextImpl.java:1538)
       at android.app.ContextImpl.startService(ContextImpl.java:1484)
       at android.content.ContextWrapper.startService(ContextWrapper.java:663)
       at com.myapp.app.MyApplication.onCreate(MyApplication.java:30)
       at android.app.Instrumentation.callApplicationOnCreate(Instrumentation.java:1125)
       at android.app.ActivityThread.handleBindApplication(ActivityThread.java:6062)
       at android.app.ActivityThread.-wrap1(ActivityThread.java)
       at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1764)
       at android.os.Handler.dispatchMessage(Handler.java:105)
       at android.os.Looper.loop(Looper.java:164)
       at android.app.ActivityThread.main(ActivityThread.java:6944)
       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)

Until now it happens on Android 8 and 9 on different devices (Samsung, Lenovo, ZTE, etc.) Shouldn't that check be enough to start an intent from the background? Any hints?

CodeWithVikas
  • 1,105
  • 9
  • 33
David
  • 3,971
  • 1
  • 26
  • 65
  • 3
    "In Our Application class in onCreate we have following code" -- why? Only start a service when it will be actively delivering value to the user. Starting a service just because the OS forks a process for you does not seem like a good plan. Beyond that, [the documentation on background execution limits on Android 8.0+](https://developer.android.com/about/versions/oreo/background.html) covers what you are seeing. – CommonsWare Nov 12 '19 at 14:08
  • We start a service to do some work each time the app starts, but that's another topic beyond the issue. – David Nov 12 '19 at 14:10
  • Can you share your manifest ? Do you use? – Eren Tüfekçi Nov 12 '19 at 14:11
  • We do use that permission in our app. – David Nov 12 '19 at 14:13
  • can you change startService() with startForegroundService() not sure, maybe it helps – Eren Tüfekçi Nov 12 '19 at 14:21
  • No, it's a background service for now. – David Nov 12 '19 at 14:34

1 Answers1

1

Since Android 8+, if an app is running in background, it's not allowed to start a service in background. Android asks us to start the service explicitly by content.startForegroundService instead of context.startService and when the service is started within 5 seconds it must be tied to the notification to have a UI element associated with it.

If you really need to start the service everytime your activity is created, you might be interested in android.support.v4.app.JobIntentService

This type of service is used to execute short tasks in the background of your app.

You must publish your JobIntentService subclass in your manifest for the OS to interact with. It should be published as a JobService i.e. include the android.permission.BIND_JOB_SERVICE permission, since on Android 8 and later platforms it will be executed that way.

 <service
    android:name=".YourJobService"
    android:permission="android.permission.BIND_JOB_SERVICE" />

You can find more info about JobIntentService here: https://developer.android.com/reference/android/support/v4/app/JobIntentService

matdev
  • 4,115
  • 6
  • 35
  • 56
  • Not necessarely, JobIntentService is recommended instead of an IntentService, but in this case we are using a normal Service which start the task in a ThreadPoolExecutor. Anyways, the issue should be independent from this I think, mabye it's only a bug/bad implementation on some devices, since for example in the case of Samsung we have reports only from S7 and a Galaxy Tab but none newer ones like S8-S9-S10. – David Nov 12 '19 at 15:56
  • It's allowed to start a background service if the app is whitelisted from battery optimization, that's the reasson of the check isIgnoringBatteryOptimizations() – David Nov 12 '19 at 16:00
  • This check does not make your app whitelisted. Again, if you don't want to use a foreground service, use JobIntentService. Check out this answer https://stackoverflow.com/a/57464381/2068732 – matdev Nov 12 '19 at 16:02
  • isIgnoringBatteryOptimizations() CHECKS if the app is whitelisted, I never said it adds it to the whitelist. – David Nov 12 '19 at 16:04
  • As of today I think the assumption that an app can start a service from the background if being whitelisted was wrong and we still need to dig into it to find the solution. – David Nov 28 '19 at 16:32