河本の実験室

河本が作ったものを紹介するブログです。こっち(https://kawalabo.blogspot.com/)から移転してきました。ポートフォリオ: http://俺.jp

「ポケットに入れたままメールを読む」を実現する『モールス通知』を作った

こんなアプリを作りました:モールス通知

いろんなアプリの通知を文字や音ではなく「振動」で伝えるAndroidアプリです。モールス信号が分かる人なら、訓練すればポケットに入れたままメールが読めるようになるはず。

動画を見ると雰囲気が分かると思います:


なんで?

最近歩きながら大事なメールを待ち構えることがあり、スマホが振動するたびに立ち止まって画面を見ている自分に気づきました。「ポケットからいちいち出さなくても要件がわかればいいのに!」と思って作ってみました。

イヤホンで聞けばいいじゃんとか言われがちですが、僕は「歩きイヤホン」反対派です。むかし後ろから近づいてくる不良に気づかなかったことがあるので。気をつけよう。

仕組み

Play Storeでアプリを公開しつつも、今回はソースをGithubにアップしました。何故かというと少し危ない「通知へのアクセス」許可をユーザーから頂くからです。自分だったらソースも公開されていない個人アプリに通知閲覧を全て許可するのは怖すぎるので、せめてソースを読めるようにしておきました。

せっかくなので、以降はソースを参照しながら作り方を解説していきます。

通知を受け取る仕組み

本アプリは、他のアプリが受け取った通知を全部読み取れる必要があります。これは「NotificationListenerService」といって、危険でパワフルな権限です。通知が読めるというのは、メールや電話番号が(通知バーに表示されている部分は)すべて読めるということです。信用してないアプリには絶対許可しちゃだめです。

AndroidManifest.xmlにintent serviceを追加するだけでは足りなくて、

<service android:name=".NotificationIntercepterService" android:label="@string/app_name" android:permission="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE">
  <intent-filter>
    <action android:name="android.service.notification.NotificationListenerService" />
  </intent-filter>
</service>

Androidの設定の「通知へのアクセス」画面でユーザーに明示的にアプリへの許可を与えてもらう必要があります。

そうすると、スマホに来るすべての通知が受け取れるようになります:

    override fun onNotificationPosted(sbn: StatusBarNotification) {
        val packageName = sbn.packageName
        val text = sbn.notification.tickerText ?: return
        // textに「Kenさんがリツイートしました」みたいな文字列が入ってる。
        ...
    }

ちなみにStatusBarNotificationからどの程度情報が取れるかはアプリによってまちまちでした:

  • TwitterだとDMの送信者や内容
  • Lineもメッセージの送信者や内容
  • Gmailアプリは送信者の名前だけ

想定していた用途では送信者の名前さえわかればいい気もするので、だいたい十分です。

執筆時点でのアプリはTwitterだけ少し特別な変換を行って、リツイートは「rt」とだけ再生してます。他に特別な表示の仕方をしてほしいアプリがあったら要望教えてくれたら作るかもしれません

和文をモールス信号に変換する仕組み

さて、Lineに「お腹空いた。帰り何時?」みたいなメッセージが来たら自分のアプリで受け取れるようになりました。英文ならばこれをそのまま欧文モールス符号に変換するだけです。
一方、和文モールス符号漢字をそのままモールス符号に変えることはできないため、もうひと工夫必要です。
今回はAndroidから使いやすい形態素解析ライブライのKuromojiのお世話になりました。
形態素解析とは文章を見て単語(正確には形態素)に分けつつ、読みや品詞を判別する作業です。
Kuromojiの出力のToken#pronunciation()を使って、

原文 : お腹空いた。帰り何時?
変換後:オナカスイタ。カエリナンジ?

というように読みに変換し、和文符号に割り当てます。

モールス符号に合わせてスマホを振動させる仕組み

ただモールス符号列を振動長に変換してandroid.os.Vibratorに渡すだけです。
つまづく点としては、配列で渡す最初の値は待ち時間だということです。気をつけましょう。

まとめ

ぼく実を言うとモールス信号全然わかんないんですが、このアプリを一日使っているだけで「・ー・ ー」(RT; リツイート)が分かるようになりました。
多分どんなに訓練しても正確に通知内容を読み取るのは難しいと思うのですが、「何言ってるのかわかんないけど何となくあの人からのメールな気がする」という直感を育てるのは出来そうだと感じました。
正確な情報伝達をせずに「なんとなく」で伝えるアンビエントな情報伝達手段、意外といろんな場面で使えるんじゃないですかね。
画面を見ずに「いま日経平均が2万円割れた気がする」とか言えるの、中二病心をくすぐられません?