iPhone notification actions¶
iOS attaches actions to some notifications: Accept/Decline on an incoming call or a calendar invitation, or Clear. With this opt-in feature, BlueFerry shows them as buttons on the desktop popup. Clicking a button asks the iPhone to perform that action over ANCS.
The buttons carry the iPhone's own text, in the phone's language.
sequenceDiagram
participant iPhone
participant Daemon as BlueFerry daemon
participant Desktop as Notification server
iPhone->>Daemon: Notification announced, with positive/negative action flags
Daemon->>iPhone: Request title, message and the action labels
iPhone->>Daemon: Attributes incl. "Accept" / "Decline"
Daemon->>Desktop: Popup with two buttons
Desktop->>Daemon: Button "Decline" clicked
Daemon->>iPhone: PerformNotificationAction (negative)
Note over Daemon,Desktop: On failure: short "iPhone action not completed" notice
Turn it on¶
- Select All iPhone Notifications in the client.
- Keep notification content shown (
BLUEFERRY_SHOW_NOTIFICATION_CONTENTis true by default). - Turn on Show iPhone action buttons under Desktop Notifications in the iPhone settings of the Qt, GTK or Quickshell client, or run:
blueferry notification-actions enable
The change applies immediately; turning it off closes popups that still
show buttons. Turning it on needs the two settings above; turning it off
is always possible, under any notification setting. BLUEFERRY_ANCS_ACTIONS=true in local.env only sets the
initial value; a choice saved from a client wins.
Optional, in ~/.config/blueferry/local.env (restart the service after
editing):
# How long popups with buttons stay, 1000-120000 ms (default 30000)
BLUEFERRY_ANCS_ACTION_TIMEOUT_MS=30000
blueferry notification-actions and blueferry doctor show whether actions
are on, and why they are inactive if they are. GetStatus contains
ancs_actions, ancs_actions_preference and notification_content_shown.
What it does and doesn't do¶
- Nothing is sent to the iPhone unless you click a labelled button. Dismissing a popup, letting it expire, clicking its body, or handling the notification on the phone never triggers an action. Popups with buttons carry an explicit "do nothing" default action, because some notification servers would otherwise run the only button on a body click.
- Buttons appear only if your notification server can draw them (it reports
the
actionscapability). Otherwise you get the normal popup. - Each notification accepts one successful action. If a click did not go through, you can try again.
- Accept on a call answers it on the iPhone. This is independent of hands-free calling: the audio stays wherever iOS routes it.
- Popups with buttons stay for
BLUEFERRY_ANCS_ACTION_TIMEOUT_MS(30 s by default) instead of the normal popup timeout, so there's time to answer a ringing call. Some notification servers ignore the requested timeout. - When the notification is handled or removed on the iPhone, its popup closes.
- iOS reuses notification numbers. A button is bound to the exact notification that offered it: when the iPhone sends anything new for that number, replays its existing notifications, or the Bluetooth connection is re-established, the old buttons are retired and their popups close.
- If the action can't be performed (already handled on the phone, phone disconnected, action refused), a short "iPhone action not completed" notice appears. It contains no notification content. If the phone was only busy or the send failed, the notice has a Retry button.
- Messages popups come from MAP and keep their normal behaviour (click opens the conversation, dismiss marks it read).
Limits¶
- Off by default. While it is off, popups and the data requested from the iPhone are unchanged.
- No buttons at all while
BLUEFERRY_SHOW_NOTIFICATION_CONTENT=false. A generic "Positive"/"Negative" label could mislabel a destructive action, so there is no fallback. - Only notifications whose app passes the All iPhone Notifications policy and the allow/block lists get buttons.
- A click is sent one at a time with the other requests to the iPhone, because Bluetooth LE allows one outstanding request. The phone usually answers within milliseconds; if it leaves an earlier request unanswered, a click can wait up to 15 s before it goes out.
- Clients only switch the feature on or off; the popup is the only place where an action can be triggered. The terminal client (TUI) has no settings; use the CLI there.
- Whether every iOS version sends labels for every kind of notification is up to iOS and the app.
Privacy¶
- Button labels are chosen by the app that posted the notification. They are often generic ("Accept", "Clear") but can contain content, for example "Pay CHF 50 to Bob". They are treated like notification content: requested only while content is shown, never logged, never stored, and never put on D-Bus. They only appear in the transient popup.
- Logs contain only the notification number, the action kind (positive/negative), the result and error codes.