Notification (Windows)
Complete Kotlin mapping of the Windows Toast Notifications API via JNI. Show rich toast notifications with text, images, buttons, text input, selection boxes, progress bars, headers, and audio on Windows 10/11.
WinRT via WRL
Uses Microsoft WRL (Windows Runtime Library) for COM event handling — no JNA, no reflection. Supports both MSIX-packaged and unpackaged apps.
Installation
dependencies {
implementation ( "io.github.kdroidfilter:nucleus.notification-windows:<version>" )
}
Depends on core-runtime (compile-only) for NativeLibraryLoader, ExecutableRuntime, and NucleusApp.
Quick Start
import io.github.kdroidfilter.nucleus.notification.windows.*
// 1. Initialize (auto-detects APPX vs unpackaged)
WindowsNotificationCenter . initialize ()
// 2. Show a simple toast
WindowsNotificationCenter . showSimple (
title = "Hello!" ,
body = "Welcome to Nucleus." ,
tag = "greeting" ,
)
AUMID handling
APPX/MSIX : the AUMID is resolved automatically from the package identity.
Unpackaged apps (EXE, MSI, dev) : the library derives the AUMID from NucleusApp.appId, registers it on the process via SetCurrentProcessExplicitAppUserModelID, and creates a Start Menu shortcut with the AUMID property.
You can also pass an explicit AUMID: initialize(aumid = "MyCompany.MyApp").
API Reference
WindowsNotificationCenter
Main entry point. All methods are thread-safe.
Property / Method
Description
isAvailable: Boolean
true if native library loaded (Windows only)
Initialization
Method
Returns
Description
initialize(aumid?)
Boolean
Initialize the notification subsystem. Pass null (default) to auto-resolve the AUMID.
uninitialize()
Unit
Clean up native resources. Call on app shutdown.
Showing Notifications
Method
Description
show(content, tag, group, ...)
Show a toast from a ToastContent model. Supports initialData for data-bound progress bars.
showSimple(title, body, body2, tag, group)
Show a simple text-only toast (up to 3 lines).
showFromXml(xml, tag, group, ...)
Show a toast from raw XML string.
Updating & Removing
Method
Description
update(tag, group, data)
Update data-bound fields (progress bars) without replacing the toast.
remove(tag, group)
Remove a specific toast from Action Center.
removeGroup(group)
Remove all toasts in a group.
clearAll()
Remove all toasts for this app.
History & Listeners
Method
Description
getHistory(callback)
Get active notifications. Callback: (List<HistoryEntry>, String?) -> Unit
addListener(listener)
Register a ToastNotificationListener for lifecycle events.
removeListener(listener)
Unregister a listener.
ToastNotificationListener
Implement this interface to receive toast lifecycle events. All callbacks are dispatched on the Swing EDT.
Method
Description
onActivated(tag, group, arguments, userInputs)
User clicked the toast body or a button. userInputs contains text box / selection values.
onDismissed(tag, group, reason)
Toast was dismissed (USER_CANCELED, APPLICATION_HIDDEN, TIMED_OUT).
onFailed(tag, group, errorCode)
Toast failed to display (HRESULT error code).
Toast Content Model
The ToastContent data class maps the full toast XML schema :
ToastContent
├── visual: ToastVisual (required)
│ └── binding: ToastBindingGeneric
│ ├── children: List<ToastVisualChild>
│ │ ├── AdaptiveText (up to 3 at top level)
│ │ ├── AdaptiveImage (inline)
│ │ ├── AdaptiveGroup (multi-column layout)
│ │ └── AdaptiveProgressBar
│ ├── appLogoOverride: ToastGenericAppLogo?
│ ├── heroImage: ToastGenericHeroImage?
│ └── attribution: ToastGenericAttributionText?
├── actions: ToastActions?
│ ├── inputs: List<ToastInput> (max 5)
│ │ ├── ToastTextBox
│ │ └── ToastSelectionBox
│ ├── buttons: List<ToastButton> (max 5)
│ └── contextMenuItems: List<ToastContextMenuItem>
├── audio: ToastAudio?
├── header: ToastHeader?
├── launch: String
├── activationType: ActivationType
├── scenario: ToastScenario
└── displayTimestamp: String?
Data Types
Visual Elements
Type
Description
AdaptiveText
Text element. Properties: text, hintStyle, hintWrap, hintMaxLines, hintMinLines, hintAlign, language
AdaptiveImage
Inline image. Properties: source, hintCrop, hintRemoveMargin, hintAlign, alternateText, addImageQuery
ToastGenericAppLogo
App logo override (left of text). Properties: source, hintCrop, alternateText
ToastGenericHeroImage
Large hero image at top of toast. Properties: source, alternateText
ToastGenericAttributionText
Attribution text at bottom. Properties: text, language
Adaptive Layout
Type
Description
AdaptiveGroup
Multi-column layout container. Contains List<AdaptiveSubgroup>.
AdaptiveSubgroup
Column within a group. Properties: children, hintWeight, hintTextStacking
Progress Bar
Type
Description
AdaptiveProgressBar
Progress bar with data binding support. Properties: title, value (0.0-1.0), valueBind (binding key), valueStringOverride, status
Use valueBind and {key} syntax in string fields for live updates via WindowsNotificationCenter.update().
Type
Description
ToastTextBox
Text input. Properties: id, title, placeholderContent, defaultInput
ToastSelectionBox
Dropdown. Properties: id, title, defaultSelectionBoxItemId, items: List<ToastSelectionBoxItem>
ToastSelectionBoxItem
Selection item. Properties: id, content
Type
Description
ToastButton
Action button. Properties: content, arguments, activationType, imageUri, inputId, afterActivationBehavior, tooltipText
ToastButtonSnooze
System snooze button. Properties: customContent, selectionBoxId
ToastButtonDismiss
System dismiss button. Properties: customContent
ToastContextMenuItem
Right-click context menu item. Properties: content, arguments, activationType
Audio
Type
Description
ToastAudio
Sound configuration. Properties: source (use ToastAudioSource), customSource, loop, silent
Type
Description
ToastHeader
Groups notifications in Action Center. Properties: id, title, arguments, activationType
Data Binding
Type
Description
ToastNotificationData
Data for updating bound fields. Properties: sequenceNumber, values: Map<String, String>
Enums
Enum
Values
ActivationType
FOREGROUND, BACKGROUND, PROTOCOL
AfterActivationBehavior
DEFAULT, PENDING_UPDATE
ToastScenario
DEFAULT, REMINDER, ALARM, INCOMING_CALL
DismissalReason
USER_CANCELED, APPLICATION_HIDDEN, TIMED_OUT
AdaptiveTextStyle
17 styles: CAPTION, BODY, BASE, SUBTITLE, TITLE, SUBHEADER, HEADER + subtle/numeral variants
AdaptiveTextAlign
DEFAULT, AUTO, LEFT, CENTER, RIGHT
AdaptiveImageCrop
DEFAULT, NONE, CIRCLE
AdaptiveImageAlign
DEFAULT, STRETCH, LEFT, CENTER, RIGHT
ImagePlacement
INLINE, APP_LOGO_OVERRIDE, HERO
AdaptiveSubgroupTextStacking
DEFAULT, TOP, CENTER, BOTTOM
ToastAudioSource
25 sounds: DEFAULT, IM, MAIL, REMINDER, SMS, ALARM_DEFAULT-ALARM10, CALL_DEFAULT-CALL10
Kotlin DSL
A type-safe DSL builder is provided for convenient toast construction:
val content = toast {
launch = "action=viewMessage&id=123"
scenario = ToastScenario . REMINDER
visual {
text ( "Meeting Reminder" )
text ( "Team standup in 5 minutes" )
heroImage ( "https://example.com/hero.png" )
appLogo ( "https://example.com/logo.png" , crop = AdaptiveImageCrop . CIRCLE )
attribution ( "via Calendar" )
progressBar (
status = "{progressStatus}" ,
title = "{progressTitle}" ,
valueBind = "progressValue" ,
)
group {
subgroup ( weight = 1 ) {
text ( "Column 1" , style = AdaptiveTextStyle . CAPTION )
}
subgroup ( weight = 2 ) {
text ( "Column 2" , style = AdaptiveTextStyle . BODY )
}
}
}
actions {
textBox ( "replyBox" , title = "Reply" , placeholder = "Type a message..." )
selectionBox ( "snoozeTime" , title = "Snooze for" ) {
item ( "5" , "5 minutes" )
item ( "15" , "15 minutes" )
item ( "60" , "1 hour" )
}
button ( "Reply" , arguments = "action=reply" , inputId = "replyBox" )
button ( "Dismiss" , arguments = "action=dismiss" ,
activationType = ActivationType . BACKGROUND )
contextMenuItem ( "Open settings" , arguments = "action=settings" )
}
audio ( ToastAudioSource . REMINDER )
header ( id = "meetings" , title = "Meetings" , arguments = "action=openMeetings" )
}
WindowsNotificationCenter . show ( content , tag = "meeting-1" )
Progress Bar with Data Binding
To update a progress bar live without replacing the toast:
// 1. Show toast with bindable progress bar
val content = toast {
visual {
text ( "Downloading file.zip" )
progressBar (
title = "{title}" ,
valueBind = "progressValue" ,
valueStringOverride = "{progressOverride}" ,
status = "{status}" ,
)
}
}
WindowsNotificationCenter . show (
content ,
tag = "download-1" ,
initialData = ToastNotificationData (
sequenceNumber = 0 ,
values = mapOf (
"title" to "file.zip" ,
"progressValue" to "0" ,
"progressOverride" to "0%" ,
"status" to "Starting..." ,
),
),
)
// 2. Update the progress
WindowsNotificationCenter . update (
tag = "download-1" ,
data = ToastNotificationData (
sequenceNumber = 1 ,
values = mapOf (
"title" to "file.zip" ,
"progressValue" to "0.75" ,
"progressOverride" to "75%" ,
"status" to "Downloading..." ,
),
),
)
Data binding requirements
The toast must have a tag (required for update to find the notification).
Use {key} syntax in string fields and valueBind for the progress value.
The initial toast must include initialData with all binding keys set.
Each update call must increment sequenceNumber to avoid race conditions.
When a toast has input elements (text boxes, selection boxes), the user's input is delivered in the onActivated callback:
WindowsNotificationCenter . addListener ( object : ToastNotificationListener {
override fun onActivated (
tag : String ,
group : String ,
arguments : String ,
userInputs : Map < String , String > ,
) {
// arguments = "action=reply"
// userInputs = {"replyBox" to "Hello!"}
println ( "Reply text: ${ userInputs [ " replyBox " ] } " )
}
override fun onDismissed ( tag : String , group : String , reason : DismissalReason ) {}
override fun onFailed ( tag : String , group : String , errorCode : Int ) {}
})
Constraints
Constraint
Limit
Top-level text elements
3 max
Input elements per toast
5 max
Buttons per toast
5 max (shared with context menu items)
Toast XML payload
5 KB max
Image size
3 MB (1 MB on metered connections)
Notifications per app in Action Center
20 max
Tag / Group length
16 characters max
Native Library
Ships pre-built Windows DLLs (x64 + ARM64). No macOS or Linux native — isAvailable returns false on other platforms and all methods are no-op.
nucleus_notification_windows.dll — linked against ole32, runtimeobject, shell32, shlwapi, user32, advapi32, propsys
Requires Windows 10 (build 10240+)
Headers and progress bars require Creators Update (build 15063+)
Uses WRL Callback<> for COM event handlers
ProGuard
-keep class io.github.kdroidfilter.nucleus.notification.windows.NativeWindowsNotificationBridge {
native <methods>;
static ** on*(...);
}
GraalVM
Reachability metadata is included in the JAR at META-INF/native-image/io.github.kdroidfilter/nucleus.notification-windows/reachability-metadata.json. No additional configuration needed.