Search code examples
androidandroid-serviceandroid-service-bindingandroid-8.0-oreo

Is a TileService considered as foreground process


In Android O we have some new background limitations. For example we can only register implicit broadcasts via the Context.registerReceiver method. When the system kills our process (e.g. as a result of low memory) the registered receivers will also be destroyed.

To reduce the chance that the system kills our process we have to tell the system that this process is still in the foreground. As per documentation an app is considered to be in the foreground if any of the following is true:

  • It has a visible activity, whether the activity is started or paused.
  • It has a foreground service
  • Another foreground app is connected to the app, either by binding to one of its services or by making use of one of its content providers. For example, the app is in the foreground if another app binds to its:
    1. IME
    2. Wallpaper service
    3. Notification listener
    4. Voice or text service

If none of those conditions is true, the app is considered to be in the background.

What about TileService (for quick setting tiles) which were introduced in Android N? When we register a TileService as ACTIVE_TILE in the mainfest file the system does not bind the service every time the tile becomes visible (as noted in this article) and therefore our service is bind to another application, in face the system process.

So is my application (as long as the tile is added to the quick settings pane) considered as foreground application? This would be nice because I do not need a persistent notification with this approach and it is nevertheless possible for the user to send my app in the background (by removing the tile)


Solution

  • So is my application (as long as the tile is added to the quick settings pane) considered as foreground application?

    Not normally. Quoting the article that you linked to:

    It is important to note that your TileService will mostly certainly be unbound (and destroyed) when the user is not viewing the tile — don’t assume that your Service will be alive outside of the onStartListening()/onStopListening() pair of methods.

    So, most of the time, your service will be unbound and destroyed.


    the system does not bind the service every time the tile becomes visible (as noted in this article)

    My guess is that you are referring to these paragraphs:

    In active mode, your TileService will still be bound for onTileAdded() and onTileRemoved() (and for click events). However, the only time you’ll get a callback to onStartListening() is after you call the static TileService.requestListeningState() method. You’ll then be able to update your tile exactly once before receiving a callback to onStopListening(). This gives you an easy one-shot ability to update your tile right when your data changes whether the tile is visible or not.

    Since active tiles don’t have to be bound every time the tile becomes visible, active tiles are better for system health. Building active tiles means less processes the system needs to bind to every time the quick settings panel becomes visible. (Of course, the system already limits the amount of bound TileServices based on available memory, etc, but by then you’re already near the border of memory thrashing — not where you want to be.)

    I would expect there to be some sort of timeout mechanism: if you call requestListeningState(), then do not update the tile within X seconds, you will be called with onStopListening(). The listening state is not durable; it only lives for one update. So, the system should be expecting an update in a timely fashion. I will test this scenario and will file a bug report if a TileService can be indefinitely bound this way, as that's a waste of system resources.