Subscribe buttons are used to detect changes to hard buttons located in the car's center console or steering wheel. You can subscribe to the following hard buttons:
| Button | Template |
|---|---|
| Play / Pause | Media only |
| Ok | Media only |
| Seek left | Media only |
| Seek right | Media only |
| Tune up | Media only |
| Tune down | Media only |
| Preset 0-9 | Any |
| Search | Any |
| Center Location | NavigationFullscreenMap only |
| Zoom In | NavigationFullscreenMap only |
| Zoom Out | NavigationFullscreenMap only |
| Pan Up | NavigationFullscreenMap only |
| Pan Up-Right | NavigationFullscreenMap only |
| Pan Right | NavigationFullscreenMap only |
| Pan Down-Right | NavigationFullscreenMap only |
| Pan Down | NavigationFullscreenMap only |
| Pan Down-Left | NavigationFullscreenMap only |
| Pan Left | NavigationFullscreenMap only |
| Pan Up-Left | NavigationFullscreenMap only |
| Toggle Tilt | NavigationFullscreenMap only |
| Rotate Clockwise | NavigationFullscreenMap only |
| Rotate Counter-Clockwise | NavigationFullscreenMap only |
| Toggle Heading | NavigationFullscreenMap only |
Media is the default template for media apps and NavigationFullscreenMap is the default template for navigation apps.
In the screenshot below, the pause, seek left and seek right icons are subscribe buttons.

There is no way to customize a subscribe button's image or text.
The play/pause, seek left, seek right, tune up, and tune down subscribe buttons can only be used in the MEDIA template. Depending on the manufacturer of the head unit, the subscribe button might also show up as a soft button in the media template. For example, the SYNC 3 HMI will add the ok, seek right, and seek left soft buttons to the media template when you subscribe to those buttons. You will automatically be assigned the media template if you set your app's appType to MEDIA.
Before library v.6.1 and SDL Core v.5.0, Ok and PlayPause were combined into Ok. Subscribing to Ok will, in v.6.1, also subscribe you to PlayPause. This means that for the time being, you should not simultaneously subscribe to Ok and PlayPause. In a future major version, this will change. For now, only subscribe to either Ok or PlayPause and the library will execute the right action based on the version of Core to which you are connected.
SDLSubscribeButton *subscribeButton = [[SDLSubscribeButton alloc] initWithButtonName:SDLButtonNamePlayPause handler:^(SDLOnButtonPress * _Nullable buttonPress, SDLOnButtonEvent * _Nullable buttonEvent) { <#subscribe button selected#> }]; [manager sendRequest:subscribeButton withResponseHandler:^(__kindof SDLRPCRequest * _Nullable request, __kindof SDLRPCResponse * _Nullable response, NSError * _Nullable error) { if (error != nil) { return; } <#subscribe button sent successfully#> }];
let subscribeButton = SDLSubscribeButton(buttonName: .ok) { (buttonPress, buttonEvent) in <#subscribe button selected#> } sdlManager.send(request: subscribeButton) { (request, response, error) in guard error == nil else { return } <#subscribe button sent successfully#> }


Preset buttons may not work in the same way as seen on the above screenshots on all head units. Some head units may have physical buttons on their console and these will trigger the subscribed button. You can check if an HMI supports subscribing to preset buttons, and how many, by calling the SDLManager.systemCapabilityManager.displayCapabilities.numCustomPresetsAvailable.
SDLSubscribeButton *preset1 = [[SDLSubscribeButton alloc] initWithButtonName:SDLButtonNamePreset1 handler:^(SDLOnButtonPress * _Nullable buttonPress, SDLOnButtonEvent * _Nullable buttonEvent) { if (buttonPress == nil) { return; } <#Button Selected#> }]; SDLSubscribeButton *preset2 = [[SDLSubscribeButton alloc] initWithButtonName:SDLButtonNamePreset2 handler:^(SDLOnButtonPress * _Nullable buttonPress, SDLOnButtonEvent * _Nullable buttonEvent) { if (buttonPress == nil) { return; } <#Button Selected#> }]; [self.sdlManager sendRequests:@[preset1, preset2] progressHandler:nil completionHandler:^(BOOL success) { if(success) { <#subscribe button sent successfully#> } }];
let preset1 = SDLSubscribeButton(buttonName: .preset1, handler: { (buttonPress, buttonEvent) in guard buttonPress != nil else { return } <#subscribe button selected#> }) let preset2 = SDLSubscribeButton(buttonName: .preset2, handler: { (buttonPress, buttonEvent) in guard buttonPress != nil else { return } <#subscribe button selected#> }) self.sdlManager.send([preset1, preset2], progressHandler: nil, completionHandler: { (success) in guard success else { return } <#subscriptions sent#> })