通知
アクションボタンとテキスト入力を備えたネイティブのシステム通知を表示します
はじめに
Wails は、デスクトップアプリケーション向けの包括的なクロスプラットフォーム通知システムを提供します。このサービスでは、次の機能を備えたネイティブのシステム通知を表示できます。
- タイトル、サブタイトル、本文を含む基本通知
- アクションボタンとテキスト返信を備えたインタラクティブ通知
- アクション用に再利用可能な通知カテゴリ
- カスタムサウンド(デフォルト、無音、または名前付き)
- 添付ファイル(すべてのプラットフォームで画像、macOS では音声と動画にも対応)
ThreadIDによる関連通知のグループ化InterruptionLevelによる優先度の設定(passive/active/timeSensitive/critical)- 配信のスケジュール設定(macOS ではネイティブ機能、Windows と Linux ではプロセス内タイマーを使用)
- ID による処理中の通知の更新
新しいオプションフィールドはいずれも、プラットフォームが対応できない場合には適切に機能を縮退させます。機能別のサポート表については、プラットフォームに関する考慮事項を参照してください。
基本的な使い方
サービスの作成
まず、通知サービスを初期化します。
import "github.com/wailsapp/wails/v3/pkg/application"
import "github.com/wailsapp/wails/v3/pkg/services/notifications"
// Create a new notification service
notifier := notifications.New()
//Register the service with the application
app := application.New(application.Options{
Services: []application.Service{
application.NewService(notifier),
},
})通知の許可
macOS で通知を使用するには、ユーザーの許可が必要です。許可を要求し、その状態を確認します。
authorized, err := notifier.CheckNotificationAuthorization()
if err != nil {
// Handle authorization error
}
if authorized {
// Send notifications
} else {
// Request authorization
authorized, err = notifier.RequestNotificationAuthorization()
}Windows と Linux では、常にtrueが返されます。
通知の種類
基本通知
一意の ID、タイトル、省略可能なサブタイトル(macOS および Linux)、本文テキストを含む基本通知をユーザーに送信します。
notifier.SendNotification(notifications.NotificationOptions{
ID: "unique-id",
Title: "New Calendar Invite",
Subtitle: "From: Jane Doe", // Optional
Body: "Tap to view the event",
})
インタラクティブ通知
アクションボタンとテキスト入力を備えた通知を送信します。この通知を使用するには、事前に通知カテゴリを登録する必要があります。
// Define a unique category id
categoryID := "unique-category-id"
// Define a category with actions
category := notifications.NotificationCategory{
ID: categoryID,
Actions: []notifications.NotificationAction{
{
ID: "OPEN",
Title: "Open",
},
{
ID: "ARCHIVE",
Title: "Archive",
Destructive: true, /* macOS-specific */
},
},
HasReplyField: true,
ReplyPlaceholder: "message...",
ReplyButtonTitle: "Reply",
}
// Register the category
notifier.RegisterNotificationCategory(category)
// Send an interactive notification with the actions registered in the provided category
notifier.SendNotificationWithActions(notifications.NotificationOptions{
ID: "unique-id",
Title: "New Message",
Subtitle: "From: Jane Doe",
Body: "Are you able to make it?",
CategoryID: categoryID,
})通知への応答
通知に対するユーザー操作を処理します。
notifier.OnNotificationResponse(func(result notifications.NotificationResult) {
response := result.Response
fmt.Printf("Notification %s was actioned with: %s\n", response.ID, response.ActionIdentifier)
if response.ActionIdentifier == "TEXT_REPLY" {
fmt.Printf("User replied: %s\n", response.UserText)
}
if data, ok := response.UserInfo["sender"].(string); ok {
fmt.Printf("Original sender: %s\n", data)
}
// Emit an event to the frontend
app.Event.Emit("notification", result.Response)
})通知のカスタマイズ
カスタムメタデータ
基本通知とインタラクティブ通知には、カスタムデータを含めることができます。
notifier.SendNotification(notifications.NotificationOptions{
ID: "unique-id",
Title: "New Calendar Invite",
Subtitle: "From: Jane Doe", // Optional
Body: "Tap to view the event",
Data: map[string]interface{}{
"sender": "jane.doe@example.com",
"timestamp": "2025-03-10T15:30:00Z",
}
})カスタムサウンド
通知の配信時に再生する音声は、Soundで制御します。nilのままにするとプラットフォームのデフォルト音が再生されます。サウンドを無効にするにはSilent: trueを設定し、名前付きまたはバンドル済みのサウンドを再生するにはNameを設定します。
// Silent
notifier.SendNotification(notifications.NotificationOptions{
ID: "silent-id",
Title: "Background sync complete",
Sound: ¬ifications.NotificationSound{Silent: true},
})
// Named sound
notifier.SendNotification(notifications.NotificationOptions{
ID: "named-id",
Title: "New message",
Body: "Tap to read",
Sound: ¬ifications.NotificationSound{Name: "Ping"},
})Nameは、プラットフォームごとに次のように解決されます。
- macOS —
Nameは[UNNotificationSound soundNamed:]に渡されます。音声ファイルは、アプリバンドルのLibrary/Sounds配下に配置する必要があります。 - Windows —
Nameがすでにms-winsoundevent:またはms-appx:で始まっている場合は、そのまま使用されます。それ以外の場合は、組み込みのトーストイベント名として使用できるようにms-winsoundevent:で囲まれます(Microsoft のトースト<audio>スキーマのドキュメントを参照してください)。 - Linux — freedesktop の
sound-nameヒントとして渡されます。再生されるかどうかは、動作中の通知デーモンとサウンドテーマによって決まります。
添付ファイル
Attachmentsを使用すると、通知にメディアファイルを添付できます。macOS は、あらゆるメディアタイプの複数の添付ファイルに対応します。Windows と Linux では、画像タイプとして指定された最初の添付ファイルが使用されます。
notifier.SendNotification(notifications.NotificationOptions{
ID: "image-id",
Title: "Photo uploaded",
Body: "Tap to view",
Attachments: []notifications.NotificationAttachment{
{
ID: "preview",
Path: "/absolute/path/to/image.png",
// Type hint:
// macOS: UTI like "public.png" / "public.audio" (often inferred)
// Windows: "hero" | "appLogoOverride" | "inline" (default "inline")
// Linux: ignored
Type: "inline",
},
},
})Pathには、ファイルシステム上の絶対パスを指定する必要があります。macOS では、file:// URL も使用できます。
アプリに同梱したファイルの添付
OS は通知の配信時にディスクから添付ファイルを読み取るため、Pathはエンドユーザーのマシン上に実在するファイルとして解決される必要があります。アプリケーションにバンドルするアセット(go:embedで埋め込んだアイコンや画像)は、ディスク上の既知の場所ではなくバイナリ内に存在するため、ハードコードできる固定の絶対パスはありません。起動時に一度だけ書き込み可能なディレクトリへ保存し、そのパスを渡します。
import (
_ "embed"
"os"
"path/filepath"
)
//go:embed assets/preview.png
var previewPNG []byte
// Materialise the embedded asset to a stable path the OS can read.
previewPath := filepath.Join(os.TempDir(), "myapp-preview.png")
if err := os.WriteFile(previewPath, previewPNG, 0o644); err != nil {
// handle error
}
notifier.SendNotification(notifications.NotificationOptions{
ID: "image-id",
Title: "Photo uploaded",
Body: "Tap to view",
Attachments: []notifications.NotificationAttachment{
{ID: "preview", Path: previewPath, Type: "inline"},
},
})ユーザーが指定したファイルやダウンロードしたファイルには、すでにディスク上の実在するパスがあるため、この手順を実行せずにPathへ直接渡せます。添付ファイルのバイト列をメモリ内で渡す機能は、将来のリリースで追加される可能性があります。
スレッド化とグループ化
ThreadIDは関連する通知をまとめ、OS が Notification Center / Action Center で折りたためるようにします。
notifier.SendNotification(notifications.NotificationOptions{
ID: "msg-42",
Title: "Jane Doe",
Body: "Are you free for lunch?",
ThreadID: "chat:jane.doe",
})割り込みレベル
InterruptionLevelは通知の優先度を制御します。エクスポートされている次の定数のいずれかを使用します。
notifier.SendNotification(notifications.NotificationOptions{
ID: "alert-id",
Title: "Server down",
Body: "Investigate immediately",
InterruptionLevel: notifications.InterruptionLevelTimeSensitive,
})| 定数 | 値 | 意味 |
|---|---|---|
InterruptionLevelPassive |
"passive" |
控えめに配信され、画面を点灯させず、デフォルトのサウンドも再生しません |
InterruptionLevelActive |
"active" |
デフォルトレベル |
InterruptionLevelTimeSensitive |
"timeSensitive" |
許可されている場合、集中モード/応答不可モードを突破して通知します |
InterruptionLevelCritical |
"critical" |
集中モードと着信音設定を無視します。macOS では Critical Alert エンタイトルメントが必要です(ない場合は警告などを出さずに機能が低下します) |
プラットフォームごとのマッピング:
- macOS —
UNNotificationContent.interruptionLevelを設定します。criticalには macOS 12以降と Critical Alert エンタイトルメントが必要です。 - Windows — トーストの
<toast scenario="...">属性にマッピングされます。 - Linux — freedesktop の
urgencyヒントにマッピングされます。
配信のスケジュール
Scheduleは配信を延期します。DelaySeconds(現在からの秒数)またはAt(UTC の Unix 秒)のいずれか一方だけを設定してください。
// Deliver in 60 seconds
notifier.SendNotification(notifications.NotificationOptions{
ID: "reminder-id",
Title: "Stand up and stretch",
Schedule: ¬ifications.NotificationSchedule{DelaySeconds: 60},
})
// Deliver at an absolute time
notifier.SendNotification(notifications.NotificationOptions{
ID: "alarm-id",
Title: "Meeting in 5 minutes",
Schedule: ¬ifications.NotificationSchedule{At: time.Now().Add(time.Hour).Unix()},
})通知の更新
UpdateNotificationは、同じIDを持つ処理中の通知を置き換えます:
notifier.UpdateNotification(notifications.NotificationOptions{
ID: "download-id",
Title: "Download complete",
Body: "report.pdf is ready",
})プラットフォームごとの動作:
- macOS —
UNUserNotificationCenterが識別子に基づいて自動的に重複を排除するため、既存の通知がその場で更新されます。 - Linux — D-Bus の
replaces_idパラメーターを使用して、以前の通知を置き換えます。 - Windows — 現在は新しい通知として再配信されます。既存の通知をその場で置き換えるには、上流の
wintoastによるtag/groupのサポートが必要です。
プラットフォームに関する考慮事項
macOS の通知には、次の特性があります:
- ユーザーの許可が必要
- アプリのパッケージ化と署名が必要(配布する場合は公証も必要)
- システム標準の通知表示を使用
Subtitleをサポート- ユーザーによるテキスト入力(返信)をサポート
Destructiveアクションオプションをサポート- 任意のメディア形式(画像、音声、動画)の複数の
Attachmentsをサポート - 通知センターでのグループ化に
ThreadIDをサポート - すべての
InterruptionLevel値をサポート(criticalには Critical Alert エンタイトルメントが必要) - アプリを再起動しても維持されるネイティブなスケジュール配信をサポート
UpdateNotification呼び出しの重複をIDに基づいて自動的に排除- ダークモードとライトモードを自動的に処理
Windows の通知には、次の特性があります:
wintoastバックエンドを介して Windows システムのトーストスタイルを使用- Windows のテーマ設定に適応
- ユーザーによるテキスト入力(返信)をサポート
- 高 DPI ディスプレイをサポート
Subtitleはサポートしない- 配置ヒントとして
hero、appLogoOverride、inline(デフォルトはinline)を指定できる、単一の画像Attachmentをサポート - アクションセンターでのグループ化に
ThreadIDをサポート - トーストの
scenario属性を介してInterruptionLevelをサポート - プロセス内タイマーによるスケジュール配信をサポート。ただし、配信前にアプリが終了すると、スケジュールされた通知は失われます
UpdateNotificationは現在、新しい通知として再配信されます(既存の通知をその場で置き換えるには、上流のwintoastによるtag/groupのサポートが必要です)
Linux では、通知に D-Bus のorg.freedesktop.Notificationsインターフェースを使用します。通知を機能させるには、互換性のある通知デーモンが実行中でなければなりません。
Linux の通知には、次の特性があります:
- デスクトップ環境のテーマに従う
- デスクトップ環境の規則に従って配置
Subtitleをサポート(個別に表示しないデーモンでは本文に連結)- ユーザーによるテキスト入力はサポートしない(freedesktop 仕様に含まれないため)
image-pathヒントを介して単一の画像AttachmentをサポートThreadIDをサポート(対応している場合はデーモンが処理)Sound.Nameはsound-nameヒントとして転送されます。再生されるかどうかは、稼働中のデーモンとサウンドテーマによって異なりますInterruptionLevelを freedesktop のurgencyヒントにマッピング- プロセス内タイマーによるスケジュール配信をサポート — 配信前にアプリが終了すると、スケジュールされた通知は失われます
UpdateNotificationは D-Bus のreplaces_idパラメーターを使用して、以前の通知をその場で置き換えます
ベストプラクティス
- 通知の許可状態を確認し、許可を要求します:
- macOS ではユーザーの許可が必要です
- 明確で簡潔な通知を提供します:
- 内容が分かりやすいタイトル、サブタイトル、テキスト、アクションタイトルを使用します
- 通知への応答を適切に処理します:
- 通知への応答にエラーがないか確認します
- ユーザーの操作に対するフィードバックを提供します
- プラットフォームの慣例を考慮します:
- プラットフォーム固有の通知パターンに従います
- システム設定を尊重します
- Linux では、デーモンへの依存を適切に処理します:
SendNotificationが返すエラーを確認します。デーモンが存在しない場合は D-Bus エラーが発生します- パッケージのドキュメントまたはアプリの README に、freedesktop 通知デーモンが必要であることを明記してください
例
次の例を参照してください:
API リファレンス
サービス管理
| メソッド | 説明 |
|---|---|
New() |
新しい通知サービスを作成します |
通知の許可
| メソッド | 説明 |
|---|---|
RequestNotificationAuthorization() |
通知を表示する許可を要求します(macOS) |
CheckNotificationAuthorization() |
現在の通知の許可状態を確認します(macOS) |
通知の送信
| メソッド | 説明 |
|---|---|
SendNotification(options NotificationOptions) |
基本的な通知を送信します |
SendNotificationWithActions(options NotificationOptions) |
アクション付きの対話型通知を送信します |
UpdateNotification(options NotificationOptions) |
送信済みで処理中の通知を ID によって更新します(通知の更新を参照) |
通知カテゴリー
| メソッド | 説明 |
|---|---|
RegisterNotificationCategory(category NotificationCategory) |
再利用可能な通知カテゴリーを登録します |
RemoveNotificationCategory(categoryID string) |
以前に登録したカテゴリーを削除します |
通知の管理
| メソッド | 説明 |
|---|---|
RemoveAllPendingNotifications() |
保留中の通知をすべて削除します(macOS および Linux のみ) |
RemovePendingNotification(identifier string) |
指定した保留中の通知を削除します(macOS および Linux のみ) |
RemoveAllDeliveredNotifications() |
配信済みの通知をすべて削除します(macOS および Linux のみ) |
RemoveDeliveredNotification(identifier string) |
指定した配信済みの通知を削除します(macOS および Linux のみ) |
RemoveNotification(identifier string) |
通知を削除します(Linux 固有) |
イベント処理
| メソッド | 説明 |
|---|---|
OnNotificationResponse(callback func(result NotificationResult)) |
通知への応答を処理するコールバックを登録します |
構造体と型
NotificationOptions
type NotificationOptions struct {
ID string // Unique identifier for the notification (required)
Title string // Main notification title (required)
Subtitle string // Subtitle text (macOS and Linux only)
Body string // Main notification content
CategoryID string // Category identifier for interactive notifications
Data map[string]interface{} // Custom data to associate with the notification
// Sound controls the sound played on delivery. nil = platform default.
Sound *NotificationSound
// Attachments are media files shown alongside the notification.
// macOS supports multiple attachments of any media type;
// Windows and Linux honour the first image-typed attachment.
Attachments []NotificationAttachment
// ThreadID groups related notifications together in
// Notification Center / Action Center / the Linux notification daemon.
ThreadID string
// InterruptionLevel controls priority. One of "passive",
// "active" (default), "timeSensitive", "critical".
InterruptionLevel string
// Schedule defers delivery. macOS uses a native trigger that survives
// restarts; Windows and Linux use an in-process timer that does NOT.
Schedule *NotificationSchedule
}NotificationSound
type NotificationSound struct {
Silent bool // If true, no sound is played
Name string // Named/bundled sound (see "Custom Sound" above)
}NotificationAttachment
type NotificationAttachment struct {
ID string // Optional identifier
Path string // Absolute filesystem path (macOS also accepts file:// URLs)
// Type is an optional placement/UTI hint:
// macOS: UTI like "public.png" / "public.audio" (often inferred)
// Windows: "hero" | "appLogoOverride" | "inline" (default "inline")
// Linux: ignored (always image-path hint)
Type string
}NotificationSchedule
// Exactly one of DelaySeconds or At must be set. At is Unix seconds (UTC).
type NotificationSchedule struct {
DelaySeconds int // Seconds from now until delivery
At int64 // Absolute Unix timestamp (seconds, UTC)
}InterruptionLevel 定数
const (
InterruptionLevelPassive = "passive"
InterruptionLevelActive = "active" // default
InterruptionLevelTimeSensitive = "timeSensitive"
InterruptionLevelCritical = "critical"
)NotificationCategory
type NotificationCategory struct {
ID string // Unique identifier for the category
Actions []NotificationAction // Button actions for the notification
HasReplyField bool // Whether to include a text input field
ReplyPlaceholder string // Placeholder text for the input field
ReplyButtonTitle string // Text for the reply button
}NotificationAction
type NotificationAction struct {
ID string // Unique identifier for the action
Title string // Button text
Destructive bool // Whether the action is destructive (macOS-specific)
}NotificationResponse
type NotificationResponse struct {
ID string // Notification identifier
ActionIdentifier string // Action that was triggered
CategoryID string // Category of the notification
Title string // Title of the notification
Subtitle string // Subtitle of the notification
Body string // Body text of the notification
UserText string // Text entered by the user
UserInfo map[string]interface{} // Custom data from the notification
}NotificationResult
type NotificationResult struct {
Response NotificationResponse // Response data
Error error // Any error that occurred
}