「ポケットに入れたままメールを読む」を実現する『モールス通知』を作った
こんなアプリを作りました:モールス通知
いろんなアプリの通知を文字や音ではなく「振動」で伝えるAndroidアプリです。モールス信号が分かる人なら、訓練すればポケットに入れたままメールが読めるようになるはず。
動画を見ると雰囲気が分かると思います:
歩きながらでもスマホの通知の中身がわかるように、TwitterとかMessengerの通知内容をモールス信号で振動させるアプリ作った。今は鍛錬が足りないのでスマホを手で触れてないと感じ取れないけど、いつかポケットに入ったままでも腿でメール読めるようになりたい。 pic.twitter.com/yuL0CsNW1t
— Ken Kawamoto(ガリのほう) (@kenkawakenkenke) February 3, 2019
なんで?
最近歩きながら大事なメールを待ち構えることがあり、スマホが振動するたびに立ち止まって画面を見ている自分に気づきました。「ポケットからいちいち出さなくても要件がわかればいいのに!」と思って作ってみました。
イヤホンで聞けばいいじゃんとか言われがちですが、僕は「歩きイヤホン」反対派です。むかし後ろから近づいてくる不良に気づかなかったことがあるので。気をつけよう。
仕組み
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だけ少し特別な変換を行って、リツイートは「rt」とだけ再生してます。他に特別な表示の仕方をしてほしいアプリがあったら要望教えてくれたら作るかもしれません。
和文をモールス信号に変換する仕組み
さて、Lineに「お腹空いた。帰り何時?」みたいなメッセージが来たら自分のアプリで受け取れるようになりました。英文ならばこれをそのまま欧文モールス符号に変換するだけです。
一方、和文モールス符号は漢字をそのままモールス符号に変えることはできないため、もうひと工夫必要です。
今回はAndroidから使いやすい形態素解析ライブライのKuromojiのお世話になりました。
形態素解析とは文章を見て単語(正確には形態素)に分けつつ、読みや品詞を判別する作業です。
Kuromojiの出力のToken#pronunciation()を使って、
原文 : お腹空いた。帰り何時?
変換後:オナカスイタ。カエリナンジ?
というように読みに変換し、和文符号に割り当てます。
モールス符号に合わせてスマホを振動させる仕組み
ただモールス符号列を振動長に変換してandroid.os.Vibratorに渡すだけです。
つまづく点としては、配列で渡す最初の値は待ち時間だということです。気をつけましょう。