Skip to content
Haiku OSDeep Dive Published Updated 6 min readViews unavailable

Haiku BNotification: Native Alerts, Progress Updates, and Click Actions

Build Haiku notifications with BNotification, including asynchronous delivery, message-ID updates, progress state, click actions, and error checks.

Haiku applications can ask the system notification server to display a native alert by constructing a BNotification and calling Send(). The class supports informational, important, error, and progress notifications, along with a title, content, group, optional icon, and follow-up action. It is a small API, but its lifecycle and update semantics matter: sending a notification is asynchronous, and a successful Send() is not proof that a person saw it.

BNotification belongs to Haiku’s Application Kit. Its implementation archives the notification into a BMessage and sends that message to the notification server. The server then applies its display settings and filters. Applications should therefore use notifications as user-facing hints, not as a durable queue, transaction record, or application-to-application IPC protocol.

Construct and send a basic alert

The header defines four notification types: information, important, error, and progress. A basic notification can be created and sent like this:

#include <Notification.h>

BNotification notification(B_INFORMATION_NOTIFICATION);
notification.SetGroup("backup");
notification.SetTitle("Backup complete");
notification.SetContent("The scheduled archive finished successfully.");

status_t result = notification.Send();
if (result != B_OK) {
    // Record the failure or provide another user-visible path.
}

The constructor records the calling application’s identity and attempts to use its Tracker icon as the notification icon. An application can replace the icon with SetIcon(). Check return values for operations that can fail, including Send(), SetIcon(), and file-reference setup; do not report a completed operation merely because the notification API accepted a request.

Progress updates use a message identifier

For long-running work, use B_PROGRESS_NOTIFICATION, assign a stable message ID, update the same notification object, and send it again. The Haiku Book documents the message identifier as the mechanism that allows a displayed notification to be updated. The progress value is a float from 0.0 through 1.0; the implementation clamps values outside that range.

BNotification progress(B_PROGRESS_NOTIFICATION);
progress.SetGroup("backup");
progress.SetMessageID("nightly-backup");
progress.SetTitle("Creating backup");
progress.SetContent("Preparing the archive...");
progress.SetProgress(0.0f);
status_t result = progress.Send();

// After completing another unit of work:
progress.SetContent("Copying verified data...");
progress.SetProgress(0.7f);
result = progress.Send();

// Send a final update or a separate terminal-state notification.

Choose IDs and groups consistently. A stable message ID is for updating a notification; it should not be treated as a globally unique job identifier or durable storage key. Keep the actual job state in the application’s own model so that completion can still be recovered after a restart or a notification-server change.

The Send() API accepts a timeout in microseconds. In the current implementation, only a positive value is added to the message sent to the notification server; the default negative value and zero leave duration to system policy. A timeout changes presentation duration, not job lifetime. A task must continue, cancel, or persist according to its own logic even if the notification disappears.

The group is a user-facing classification and can help the notification server present related items together. Choose a stable, concise group for one feature area, not a unique value for every update. Pair it with a message ID that identifies the notification to update. Do not assume the pair is a durable key for a backup or download: retain the operation ID, progress, and result in the application’s own storage if they must survive an application or server restart.

Progress should represent completed work, not elapsed time dressed up as completion. If work has multiple phases, compute a weighted fraction from actual completed units and avoid moving backward unless the operation really restarted. On cancellation or failure, send a clear terminal state or remove/update the progress item according to the server’s supported behavior; a value of 1.0 should mean the underlying operation succeeded, not merely that the notification should disappear.

Click actions and user control

BNotification can direct a click to an application, an entry_ref file, or a list of references and arguments. This is useful for opening the result of a completed job, but the destination must be valid at click time. Handle deleted files, renamed items, and applications that are no longer installed. Do not encode secrets or authorization tokens in notification content or click arguments; the notification is display data, not a protected secret channel.

Keep click handling idempotent. A person can click after the operation has completed, after the result has been removed, or after another instance of the app has already processed the action. Re-resolve the entry reference, verify that the app still owns the job, and present a useful explanation when the action is stale. If a click launches the app with arguments, parse only the arguments your app intentionally emitted and do not treat them as an authorization token.

Notifications are subject to the user’s settings and system filters. A quiet mode, display preference, or server-side rule can prevent visible presentation. Critical state must remain available inside the application, and important errors should also be logged through the application’s normal diagnostic path.

Notification delivery and presentation are separate observability points. Record the operation result before sending the notification, then log the returned status if the send fails. Do not report a visible notification as proof that a user read it, and do not retry forever if the server is unavailable. A bounded retry may be appropriate for a transient server error, but only if duplicate/update semantics are understood and the underlying operation is not repeated.

The notification carries source identity and presentation metadata, not a trusted audit record. A title such as “Backup complete” should be emitted only after the application has verified the archive and committed its destination. If the notification is filtered, the same completion must still appear in the app’s job history or another durable status surface. This distinction also makes support reports actionable: the notification status describes delivery to the server, while the saved job result describes the work itself.

Keep titles and content concise enough for the user’s notification settings and display size. Put detailed logs, paths, and diagnostics behind an intentional click into the application instead of exposing them on a shared screen. A notification may appear while the machine is locked or in a public setting, so treat its text as visible to someone other than the account owner.

Failure handling and lifecycle

Send() delivers asynchronously to notification_server and returns the status of the send operation. Check that result, but avoid blocking the main thread on a notification as if it were an acknowledgment from the user. The object remains owned by the caller after sending, so it can be updated and reused; heap-allocated objects must still be freed by the application.

Check InitCheck() after construction and propagate failures from optional state changes such as icon and click-file setup. The current constructor attempts to discover the running app’s signature and Tracker icon; an absent icon is not the same as a failed business operation. Keep notification creation off a latency-sensitive callback if it needs application lookup or bitmap work, and avoid retaining pointers returned by getters beyond the lifetime or mutation of the notification object.

Test the app with notifications disabled or filtered, with notification_server unavailable, and with the target file removed before the notification is clicked. Verify progress transitions at 0, an intermediate value, and 1.0, and make sure repeated sends with the same message ID update only the intended logical notification. Also check that a notification failure does not change the outcome of the backup, download, or other underlying task.

BNotification gives Haiku applications a native presentation path with useful progress and action metadata. Its design stays understandable when the boundaries remain clear: the application owns task state, the notification server owns presentation, and the user controls whether an alert is displayed.

Related:

Sources:

Comments