【ITニュース解説】Message Mirror: a tiny, resilient Android notification + SMS forwarder (Flutter + Kotlin)
2025年09月22日に「Dev.to」が公開したITニュース「Message Mirror: a tiny, resilient Android notification + SMS forwarder (Flutter + Kotlin)」について初心者にもわかりやすく解説しています。
ITニュース概要
Androidアプリ「Message Mirror」は、通知やSMSをユーザーが指定するWebhookへ転送するオープンソースツールだ。FlutterとKotlinで開発され、データのプライバシーを保ち、OEMの制限下でも安定稼動する。シンプルな設計で、再起動や通信不良時も確実な転送をめざす。
ITニュース解説
「Message Mirror」は、Androidスマートフォンの通知とSMSを、ユーザー自身が指定するウェブサービス(Webhook)に転送するための、小さくても非常に堅牢なオープンソースアプリケーションだ。このアプリは、既存の通知転送ソリューションが抱える問題を解決するために開発された。多くの既存アプリは特定のベンダーのクラウドサービスに依存したり、不要な広告や解析機能を含んでいたり、あるいはAndroidデバイスメーカー(OEM)による厳しいバックグラウンド処理制限に弱かったりする。Message Mirrorはこれらの課題を克服し、ユーザーが自身のデータを完全にコントロールできるように設計されている。
このアプリの主な目的は、通知やSMSをユーザーが管理するサーバーにJSON形式で転送することだ。これにより、ユーザーは自分のデータが第三者のクラウドに保存されることなく、自身でデータの処理や保存方法を決定できる。さらに、デバイスの再起動、OSによるアプリの強制終了、あるいは不安定なネットワーク環境下でも、この転送機能が途切れないように、非常に堅牢な設計が採用されている。特定のアプリからの通知のみを転送する設定や、繰り返されるノイズのある通知を重複排除する機能も備わっており、必要な情報だけを効率的に受け取ることが可能だ。また、転送するデータの形式(ペイロード)を自由にカスタマイズできる点も大きな特徴である。
Message Mirrorは、FlutterとKotlinという二つの主要な技術を組み合わせて構築されている。基本的なアーキテクチャは次の通りである。
まず、Android OSが何らかの通知を発行すると、Kotlinで書かれたMsgNotificationListenerというサービスがそれを検知する。これはAndroidのNotificationListenerServiceという、通知を監視するための特別な機能を利用している。このサービスは、通知のアプリ名、タイトル、本文などの情報を抽出する。
次に、抽出された通知データは、MethodChannelという仕組みを通じて、Flutterで書かれたDartコードに渡される。MethodChannelはAndroidネイティブコード(Kotlin)とFlutter(Dart)間の双方向通信を可能にする重要な橋渡し役だ。
Dart側では、このデータを受け取ると、ユーザーの設定に基づいたフィルタリングや重複排除処理が行われる。例えば、転送対象として許可されていないアプリからの通知はここで除外される。その後、データの形式を整形し、ユーザーが事前に設定したWebhookエンドポイントへHTTP POSTリクエストとして送信される。
ネットワークの状態が不安定で送信に失敗した場合に備え、Dart側には「再試行キュー」と「指数バックオフ」の機能が実装されている。再試行キューは送信できなかったデータを一時的に保存し、指数バックオフは再試行の間隔を徐々に長くしていくことで、サーバーへの過度な負荷を避けつつ、最終的なデータ送信を試みる。
この一連の処理を常時稼働させるために、Androidの「フォアグラウンドサービス」が利用されている。フォアグラウンドサービスは、アプリがバックグラウンドに移動してもOSによって強制終了されにくく、安定して動作し続けることを保証する。Message Mirrorは、UI(ユーザーインターフェース)を持たない「ヘッドレスFlutterエンジン」をフォアグラウンドサービス内で起動することで、バックグラウンドでもDartコードを実行し続ける。さらに、デバイスの再起動時にはBootReceiverという機能を使って自動的にサービスが再開される仕組みも備わっている。通知データはMethodChannelだけでなく、Androidのブロードキャスト(システム全体にメッセージを送信する仕組み)も使ってDart側に届けられるため、より堅牢な配信経路が確保されている。
Androidデバイスメーカー(OEM)は、バッテリー消費を抑えるために、バックグラウンドで動作するアプリを積極的に終了させることがある。Message Mirrorは、この「OEMによる強制終了」から生き残るために、前述のフォアグラウンドサービスを核とする設計を採用している。また、Android 13以降で導入されたPOST_NOTIFICATIONS権限や、サービス宣言に必要なBIND_NOTIFICATION_LISTENER_SERVICE、フォアグラウンドサービスに必要なFOREGROUND_SERVICE、ネットワーク通信に必要なINTERNETとACCESS_NETWORK_STATE、デバイス再起動時にサービスを起動するためのRECEIVE_BOOT_COMPLETED、そしてSMS転送を有効にする場合にのみ必要となるREAD_SMSといった、必要な権限を適切に取得する。ユーザーがデータセーバー機能やバッテリー最適化を設定している場合、アプリのバックグラウンド通信が制限されることがあるため、アプリ内からユーザーに設定の見直しを促す機能も提供している。
プライバシーとセキュリティも重要な考慮事項だ。Message Mirrorは、メッセージの内容がユーザーのデバイス上に留まり、設定したWebhookエンドポイントに送信されるまで第三者に渡ることはない。転送する通知はアプリごとに選択でき、SMS監視も任意だ。転送されるデータの形式はテンプレート機能を使ってカスタマイズできるため、不要な情報を含めないよう調整が可能だ。また、データ転送の際にはHTTPSを利用して通信を暗号化することが推奨されており、メッセージ内容に関する法的・プライバシー上の義務についてもユーザー自身が意識する必要がある。
開発においては、「KISS(Keep It Simple, Stupid:シンプルに保て)」という原則が重視されている。これは、コードを可能な限りシンプルにし、複雑な依存関係を避け、プラットフォームが提供する基本的な機能を使うことを意味する。また、「YAGNI(You Ain't Gonna Need It:それはいらないだろう)」という原則も採用されており、将来必要になるかもしれないという不確実な機能のために過度な設計を行わないという姿勢が貫かれている。アプリの動作状況を把握し、問題発生時に原因究明を助けるために、ログはアプリ内画面に表示されるだけでなく、Androidのログ出力機能(logcat)にもミラーリングされる。
もしWebhookが一時的に停止していた場合でも、アプリのキュー画面から「Force Retry(強制再試行)」を手動で実行することで、キューに溜まったデータをすぐに再送信できる。このアプリは、ユーザーが自分のデータをコントロールし、堅牢な仕組みでAndroidの通知やSMSを自身のシステムに連携させたいと考えるシステムエンジニア志望者にとって、非常に有用なツールであり、またその実装方法から多くの学びが得られるだろう。