Closed10

TauriアプリからのNotificationを受け取るまでに躓いたところ

8beeeaaat8beeeaaat

いわゆる「アプリ通知」「Notification」。
これを実現するまでの道のりをまとめておく。

8beeeaaat8beeeaaat

以下 Tauri v2 x macOS を前提としたお話。
恐らくその他環境にも通ずるかと思いますのでご参考に。

Notificationを有効にするためにRust / フロントエンドでそれぞれv2対応のプラグインをインストールする
https://github.com/tauri-apps/tauri-plugin-notification

[dependencies]
...
tauri-plugin-notification = "2.0.0-beta"
...
  "dependencies": {
    ...
    "@tauri-apps/plugin-notification": "^2.0.0-beta.7",
    ...
  }

公式ドキュメント ではRust側の準備としてプラグインを登録するだけの様に記載されているので、それに従う

tauri::Builder::default()
  .plugin(tauri_plugin_notification::init())

[追記 2024/07/23] 上記とは別に後述する手順が必要だったので、READMEの修正PRを送り修正してもらいました

8beeeaaat8beeeaaat

フロントエンド側からのNotificationの認可と送出はこちらのサンプルを見ると分かりやすい
https://v2.tauri.app/reference/javascript/notification/#example-12

import { isPermissionGranted, requestPermission, sendNotification } from '@tauri-apps/plugin-notification';
let permissionGranted = await isPermissionGranted();
if (!permissionGranted) {
  const permission = await requestPermission();
  permissionGranted = permission === 'granted';
}
if (permissionGranted) {
  sendNotification('Tauri is awesome!');
  sendNotification({ title: 'TAURI', body: 'Tauri is awesome!' });
}

アプリからのNotificationの送出をOSに認可してもらう必要があるので isPermissionGranted() 時に未認可だった場合 ( Notification.permission === "default" )、 フロントエンド -- [IPC] -- Rust -> OS という経路でOSから認証を取り付けている。
https://github.com/tauri-apps/tauri-plugin-notification/blob/v2/dist-js/index.cjs#L75-L99

Notification API自体の仕様はこちらでチェック
https://developer.mozilla.org/ja/docs/Web/API/Notification/permission_static

8beeeaaat8beeeaaat

📝 ここまでやったこと

  • v2対応のプラグインをインストール
  • フロントエンドからの通知サンプルを実装

これで公式ドキュメント上は通知を送れるはずである。
そう、はずなのである。

ところがどっこい、送れませーん!

Unhandled Promise Rejection: notification.is_permission_granted not allowed. Permissions associated with this command: notification:allow-is-permission-granted, notification:default

なじぇ...。

8beeeaaat8beeeaaat

圧倒的ググり力を活かして類似のissueを発見
どうやら capabilities への追加が必要。
https://github.com/tauri-apps/tauri/issues/8967#issuecomment-1962328236

ヒントはフロントエンド側のプラグインにありました

core.invoke("plugin:notification|is_permission_granted")

https://github.com/tauri-apps/tauri-plugin-notification/blob/v2/dist-js/index.cjs#L79

これは気づかんわー。
invokeするにあたってプラグインの登録とは別に権限付与を行う必要があります。
src-tauri/capabilities/main.jsonnotification:default 権限を追加すると...。

{
    ...
  "permissions": [
    ...
    "notification:default"
  ],
  ...
}

やりました✌

  sendNotification('Tauri is awesome!');
  sendNotification({ title: 'TAURI', body: 'Tauri is awesome!' });

メッセージをtitleとbodyを分けずにstringで送出するとアプリケーション名が自動でタイトルに当てられるようですね。
送信元がターミナルとなっているのは npm run tauri dev で立ち上げた開発ビルドだからでしょう。

sendNotificationに渡す Option型の定義はこちら。 title だけが必須で、その他はオプショナル。
sound や icon などのプロパティもあるので細かく調整できそうですね。
https://github.com/tauri-apps/tauri-plugin-notification/blob/v2/guest-js/index.ts#L18-L131

なお notification:default で付与される権限はこちらを参照。
細かな権限調整を行う場合はこちらで最低限の権限だけ付与すればOKでしょう。
https://github.com/tauri-apps/tauri-plugin-notification/blob/v2/permissions/default.toml#L7-L30

8beeeaaat8beeeaaat

同様にTauri (Rust) 側からの送出も試みます。
アプリケーションの起動直後に通知させてみましょう。

    tauri::Builder::default()
        .plugin(tauri_plugin_os::init())
        .plugin(tauri_plugin_shell::init())
        .plugin(tauri_plugin_notification::init())
        .setup(|app| {
            use tauri_plugin_notification::NotificationExt;
            app.notification()
                .builder()
                .title("Tauri")
                .body("from Rust")
                .show()
                .expect("error");

起動直後なのでフロントエンド側よりも先に通知されていますね。ぴすぴす。

8beeeaaat8beeeaaat

フロントエンドから汎用的にメッセージを送れる様にしてみましょう

  • 関数化
import { Options, isPermissionGranted, requestPermission, sendNotification } from '@tauri-apps/plugin-notification';

async function checkPermission() {
  if (!(await isPermissionGranted())) {
    const permission = await requestPermission();
    return permission === 'granted';
  }
  return true;
}

export async function enqueueNotification(options: Options) {
  if (!(await checkPermission())) {
    return;
  }
  sendNotification(options);
}
  • 利用側
      await enqueueNotification({
        title: 'Tauri',
        body: 'from Frontend その1',
      })
      await enqueueNotification({
        title: 'タウリ',
        body: 'from Frontend その2',
      })

ぴすぴすぴーす

8beeeaaat8beeeaaat

なお、developmentモードでは通知元がターミナルになっていますが、productionビルドではアプリケーション名になり、アイコンもアプリケーションのものに差し替わります。

初回は他のアプリケーション同様にOS側で通知を許可する必要がありますので、お忘れなく。



これにて一件落着

このスクラップは4ヶ月前にクローズされました