setState method

Future<void> setState (
  1. {@required List<MediaControl> controls,
  2. List<MediaAction> systemActions: const [],
  3. @required AudioProcessingState processingState,
  4. @required bool playing,
  5. Duration position: Duration.zero,
  6. Duration bufferedPosition: Duration.zero,
  7. double speed: 1.0,
  8. Duration updateTime,
  9. List<int> androidCompactActions,
  10. AudioServiceRepeatMode repeatMode: AudioServiceRepeatMode.none,
  11. AudioServiceShuffleMode shuffleMode: AudioServiceShuffleMode.none}
)

Broadcasts to all clients the current state, including:

  • Whether media is playing or paused
  • Whether media is buffering or skipping
  • The current position, buffered position and speed
  • The current set of media actions that should be enabled

Connected clients will use this information to update their UI.

You should use controls to specify the set of clickable buttons that should currently be visible in the notification in the current state, where each button is a MediaControl that triggers a different MediaAction. Only the following actions can be enabled as MediaControls:

Any other action you would like to enable for clients that is not a clickable notification button should be specified in the systemActions parameter. For example:

In practice, iOS will treat all entries in controls and systemActions in the same way since you cannot customise the icons of controls in the Control Center. However, on Android, the distinction is important as clickable buttons in the notification require you to specify your own icon.

Note that specifying MediaAction.seekTo in systemActions will enable a seek bar in both the Android notification and the iOS control center. MediaAction.seekForward and MediaAction.seekBackward have a special behaviour on iOS in which if you have already enabled the MediaAction.skipToNext and MediaAction.skipToPrevious buttons, these additional actions will allow the user to press and hold the buttons to activate the continuous seeking behaviour.

On Android, a media notification has a compact and expanded form. In the compact view, you can optionally specify the indices of up to 3 of your controls that you would like to be shown.

The playback position should NOT be updated continuously in real time. Instead, it should be updated only when the normal continuity of time is disrupted, such as during a seek, buffering and seeking. When broadcasting such a position change, the updateTime specifies the time of that change, allowing clients to project the realtime value of the position as position + (DateTime.now() - updateTime). As a convenience, this calculation is provided by PlaybackState.currentPosition.

The playback speed is given as a double where 1.0 means normal speed.

Implementation

static Future<void> setState({
  @required List<MediaControl> controls,
  List<MediaAction> systemActions = const [],
  @required AudioProcessingState processingState,
  @required bool playing,
  Duration position = Duration.zero,
  Duration bufferedPosition = Duration.zero,
  double speed = 1.0,
  Duration updateTime,
  List<int> androidCompactActions,
  AudioServiceRepeatMode repeatMode = AudioServiceRepeatMode.none,
  AudioServiceShuffleMode shuffleMode = AudioServiceShuffleMode.none,
}) async {
  _state = PlaybackState(
    processingState: processingState,
    playing: playing,
    actions: controls.map((control) => control.action).toSet(),
    position: position,
    bufferedPosition: bufferedPosition,
    speed: speed,
    updateTime: updateTime,
    repeatMode: repeatMode,
    shuffleMode: shuffleMode,
  );
  List<Map> rawControls = controls
      .map((control) => {
            'androidIcon': control.androidIcon,
            'label': control.label,
            'action': control.action.index,
          })
      .toList();
  final rawSystemActions =
      systemActions.map((action) => action.index).toList();
  await _backgroundChannel.invokeMethod('setState', [
    rawControls,
    rawSystemActions,
    processingState?.index ?? AudioProcessingState.none.index,
    playing ?? false,
    position?.inMilliseconds ?? 0,
    bufferedPosition?.inMilliseconds ?? 0,
    speed ?? 1.0,
    updateTime?.inMilliseconds,
    androidCompactActions,
    repeatMode?.index ?? AudioServiceRepeatMode.none.index,
    shuffleMode?.index ?? AudioServiceShuffleMode.none.index,
  ]);
}