How it works - MShekow/stop-it GitHub Wiki

How Stop It! works

To be able to create bookmarks, we need Android to inform Stop It! about the following events:

  • Changes of the currently playing audio track
  • Playback state changed from playing to paused (or vice versa)

The first implementation made use of BroadcastReceivers, listening to com.android.music.playstatechanged Intents. However, devices running Android 8+ no longer receive such Intents. Instead, we use the Media API which pretty much all modern video/audio players implement. We take a lot of inspiration from the Media Controller Test sample app made by Google. Retrieving the MediaSessionManager we register an OnActiveSessionsChangedListener that notifies us whenever new MediaControllers exist / cease to exist (because a video/audio app was started or quit). We make copies from the MediaControllers given to us by OnActiveSessionsChangedListener.onActiveSessionsChanged(controllers), and register MediaController.Callbacks to be informed about state changes. From the MediaControllers we can also get MediaController.TransportControls to control the playback, which is useful to resume playback for a previously created bookmark.

To have sufficient permissions to use the Media API, Stop It! implements a NotificationListenerService. The user has to explicitly grant notification listening access to Stop It!. We need to be able to listen to notifications anyway, because notifications typically will cause audio playback to pause briefly, causing the MediaController.Callback functions to be called. These calls make it look like the user had briefly paused and unpaused the audio playback, wishing a bookmark to be created, but this is not the case. To avoid incorrect detections, the NotificationListenerService verifies that no notifications were posted during the last few seconds.

To persistently store bookmarks, Stop It! uses Room.