Search code examples
androidandroid-intentbroadcastreceiver

Register broadcast receivers for SCREEN_ON / SCREEN_OFF in a service


Can someone confirm whether I'm following proper design of desired functionality?

I need to listen two types of intents by broadcast receivers when my app is at least once ran on a device, which cannot be registered in AndroidManifest:

  • android.intent.action.SCREEN_ON
  • android.intent.action.SCREEN_OFF

For this reason I've created a service, which is started when my MainActivity is launched. Withing the service's method onStartCommand I register these broadcast receivers...

Next within these broadcast receivers there is done some stuff based on a flag taken from SharedPreferences either 0 (don't do anything) or 1 (do proper logic)

Do I undestand the lifecycle of service correctly, that it will not be stopped / killed (assiming that it doesn't cause any device disturbences and overloading) by Android even the MainActivity will be removed from the memory / stack and intents will be listening ?


Solution

  • A few things:

    • register the Receivers in the Service's onCreate() instead since this method is only called once in the creation of the service. If you call startService() multiple times, that results in more calls to onStartCommand(), which means you're constantly remaking the receivers.

    Note that multiple calls to Context.startService() do not nest (though they do result in multiple corresponding calls to onStartCommand()), so no matter how many times it is started a service will be stopped once Context.stopService() or stopSelf() is called;

    • Make sure to unregister your Receivers. I usually do this in onDestroy()

    Also, about your lifecyle question - a normal service should not be killed without reason and should run independently from the Activity that launched it (bound Services are a bit different from what I remember) but it still runs in the UI Thread and the same process (unless you specify otherwise). However, if a long time passes and your Service isn't in the foreground. It has the potential to be killed. This is why you should make onStartCommand() return START_STICKY. If the system does kill the Service, when it can, it will restart it. Your Service may also be killed if it is in the foreground, but it is as a last resort kill. START_STICKY can be bad if your Service is error prone though. For example, my Service kept crashing. START_STICKY made it restart some time later, and then it crashed again, the cycle repeated.

    The only times your service is safe from being killed under normal circumstances are these:

    If the service is currently executing code in its onCreate(), onStartCommand(), or onDestroy() methods, then the hosting process will be a foreground process to ensure this code can execute without being killed.