モバイル通信のデータ量の節約には余念がないのだが、通信データ量を調べていたら、思わぬことが分かった。前にも書いたが、家に居るのにWi-Fiでなくモバイルが使われることがある(以下、「家でもモバイル問題」)のだ。それで、それを何とかしたいと思って試行錯誤していたら、僕の要求が相反していて、同時に全部は満足できないことに気付いた。要求を以下に示す。

  • 電池消費率を削減する。
  • モバイル通信のデータ使用量を削減する。
  • (スケジュールなどの)同期を可能な限り定期的にする。

全部を満足させるのは無理で、どれを優先すべきなのか、それぞれをどういうふうに配分するのかの「さじ加減」が難しい。どれが一番重要かはいつも変わるのだが、(とりあえず今は)電池だということになった。その次はデータ量だ(上のリストの順に優先度が高い)。

その方針で、「家でもモバイル問題」に対処した。予想以上に大掛かりになり、うまく動くまでには結構(1週間くらい)時間が掛かった。以下に内容を示す。

現象

接続可能なWi-Fiルータがあっても、モバイルデータが使われてしまうことがある。

原因

Androidのディープスリープ(Dozeモード)に関係しているようだ(他に、アプリごとのディープスリープ"App standby"というのもあるらしい: 参考)。Androidのディープスリープ中はWi-Fi機能が停まり※、何かのアプリが通信する時に自動で再接続されるようなのだが、再接続が遅い(間に合わなかった?)場合にモバイルが使われるようだ。

※Wi-Fi機能の停止以外に、Wi-Fiの鍵の期限切れによる切断もある。

対処

基本的には、通信する時にWi-Fiが接続されていなかったら接続するようにすればいい。が、Androidにはそんな機能はないし(そうしているつもりなのだろうが、抜けがあるのか、「少しくらい(のモバイル)は大目に見て」いるから、この問題が起こっている)、調整するアプリもなさそう(調べてはいない)なので、Androidのグラフィカルなプログラミング言語Automagicでスクリプトを作った。ただ、Automagicではアプリの通信要求を検知することはできないし、その通信を保留することもできないので、以下のようにした。

注: 以下は私のスマフォ・OS・環境(AQUOS sense lite, Android 8)での確認結果に基づいており、すべての場合で同じであるとは言えない(スマフォのHW・ファームやOSが違えば、動作は異なる可能性が高い)。また、私はAndroidに関して詳しく調べた訳ではなく、Automagicのマニュアルの記述と実際の動作から推測したので、Androidの公式の仕様とは異なる可能性がある。以下で用いている単語(例: "Request Sync")はAutomagicで使われているものだが、Andoridでも同じかは不明である。

準備

Wi-Fiが停まっている時にも通信(同期)しそうなアプリ(例: メール、カレンダー、アドレス帳、Evernote)の設定を、自動で同期しないように変える(例: バックグラウンドデータや自動同期・受信をoffにする)。

注: Androidの、アプリに外部から同期要求を出す機能(Request Sync)を使うため、それに対応するアプリでしか対処できない。

定期同期処理

Automagicで以下の処理を実行する。

  1. なるべく頻繁に、かつ、ディープスリープ中も発生しそうな、しかも消費電力が少ないイベントを待ち受ける。
  2. イベント発生時に以下を実行する。
    1. 前回の処理からの経過時間が最小同期間隔(例: 30分)より短かったら、何もしない。
    2. Wi-Fiが有効な状態で、APに接続されていなかったら、再接続(WiFi Reassociate)する。
    3. Wi-Fiが使用可能(Active Network Type= WiFi)になるまで待つ。
      • Wi-Fiが無効だったり接続できなかったり使用可能にならなかったら諦める(→ モバイルが使われる)。
    4. 対象のアプリに同期の要求(Request Sync)を出す。

リストで書くとシンプルなのだが、Automagicはプログラムを図で描くのと、デバッグ用の機能を入れたため、実際のプログラムは大規模になった。普通の言語のようにテキストで書くならそうでもないが、図(しかもスマフォの画面でいじる)だとデバッグや保守がなかなか困難だ。。。 ただ、並行処理がたやすく書ける・実現できるのは、とても楽でいい感じだった。

Automagicでの定期同期実行+Wi-Fi再接続プログラム (概観)

以下に設定や条件などを書く。

対象のアプリは以下とした。通信状況の調査結果から、最も通信頻度・量が多そうで、外部から同期できるものを選んだ。

  • メール(TypeApp): それまで使っていたAquaMailは外部から同期できないので換えた。いくつか試したうちでは一番良かった。 : TypeAppが原因の確証はないが、先ほどセキュリティ上の問題(GoogleのID・パスワード漏洩の可能性)が起こったので、使うのを止めた。AquaMailに戻し、この機能での同期は諦めることにした。詳細は追って書く予定。 (16:18) ← いろいろ調べたが、原因はTypeAppではなさそうだ。というのは、TypeAppにはGoogleのパスワードを入れていないからだ。余りにもタイミングが良かったので、誤解した。まとまったら書く。ただ、別件でも怖くなったので、TypeAppは止めることにした。 (21時) → 詳細をPS2に書いた。 (2/5 13:34)
  • Evernote
  • カレンダー同期アプリ
  • アドレス帳同期アプリ

待ち受けるイベントは以下にした。

  • Periodic Timer Inexact (定期的な(ただし正確でない)タイマー)
  • Display State: On (画面が点灯したら)
  • Notification on Statusbar (ステータスバーに通知が出たら)
  • WiFi State: Enabled (Wi-Fiがonになったら: 帰宅時にWi-Fi Maticがonにした場合に起こる)
  • WiFi Connected (Wi-Fiが接続されたら)
  • Phone Cell GSM: On every cell change (モバイルの基地局が変わったら)
  • Periodic Location Update (30min) (位置が変わったら: 注: 消費電力を増やさないため、GPSでなくNetworkのみを使う)
  • Calendar Event (予定の通知が出たら)
  • Automagic startup (Automagicの起動時)

基本的にはPeriodic Timer Inexactで同期間隔を実現するのだが、ディープスリープ中には間隔が長くなってしまう(例: 2時間)。そこで、なるべく同期間隔を正確にするため、ディープスリープ中も発生しそうなものを追加したので多くなった。が、実際にはPeriodic Timer InexactとDisplay Stateが同期の契機になることが多い。他のものはディープスリープ中にはほとんど発生しない感じだ。

同期間隔は30分としたが、アドレス帳はあまり変化しないので6時間にした。この間隔の種類を増やしてそれに対応する処理を追加すれば、アプリごとに間隔を変えることができるし、細かい処理を調整することもできる(ただし、プログラムは更に複雑になる)。

それから、Periodic Timer Inexactは発生間隔がアバウトなので、ある程度早目にイベントが起こった場合でも処理するようにした。

プログラムは概ねできて、今は動作確認・調整中である。なお、上にも書いたように、Periodic Timer Inexactはディープスリープ中は発生間隔がかなり長くなるため、同期間隔も長くなってしまう。これを解消できる方法も見つけた(下記「簡単にディープスリープを回避する方法」)のだが、消費電力が若干増えるので採用を見送った。これが、最初に書いたさじ加減の難しさの一つである。

ただ、実際に使う場面を考えると、家ではほぼPCしか使わないので、スマフォの通知が出なくても問題はないし、外では頻繁にスマフォを開くので、そのたびに同期が行われる可能性があるから、大きな問題ではなさそうだ。ちょっとした問題は、寝る前に作った予定や夜中に来たメールが朝になっても同期・受信されていない可能性があり、それに気付いて気分が悪くなる程度である。

以下、この過程で見つけた問題などについて書く。

通信遅延問題

ディープスリープの関係なのか、上記プログラムのログに書かれた同期時刻より遅れて実際の同期(通信)が行われることがある(サーバのログと比較して分かった)。呼び出す方(Automagic)からは同期処理が実行されたように見えているのだが、実際にはどこかに貯められていて、あとでまとめて実行されるような感じだ(→ 参考)。左の参考ページによれば、回避策はGCMを使うことらしい(が、それは廃止になり、FCMに移行すべきのようだ)。。。 いずれにしても、クライアントプログラムが非互換なので、そのままでは使えない。

簡単にディープスリープを回避する方法

今まではどうしてもディープスリープを回避できなかったのだが、偶然、方法が分かった。Periodic timer (Like alarm clock)を設定れば良い※。間隔は、例えば1時間でも2時間でも大丈夫だった。ただ、ステータスバーやロック画面にマークやアラーム時刻が表示されるので、紛らわしいし鬱陶しい。

※これはAutomagicだから可能なのか、Android全般に有効なのかは分からない。時計アプリにアラームを設定すれば確認できそうではある。

これより、Periodic timer (Like alarm clock)を待ち受けるイベントに追加すれば、同期間隔がかなり正確に保てることが分かった。しかし、消費電力が若干増える(例: 使用しない場合: 0.3-0.5%/h, 使用した場合: 0.5-0.6%/h)ために見送った。

 

PS. これの発端を調べたら、「(ディープスリープ時に)同期間隔が長くなるので、改善できないか」だった。結局は、同期間隔は諦めてモバイルデータ量の削減となった。やっぱり優先順位が変動しているw そして、こうやって書いておかないと、あとでまた同じことを気にし出す可能性が高いから、困ったものだw

PS2. セキュリティの問題を疑った件について

2/4に、何もしていないのにGoogleから確認コードの電話とSMSが来た。それで、Googleのパスワードが漏れたのかと思って心当たりを考えたところ、数日前にTypeAppをインストールしたので、そこから漏れたのかと思って検索したところ、件数は少ないものの、いくつかの悪い情報があった(→ )。それによれば、TypeApp(BlueMailと同じもの)はIDとパスワードを彼らのサーバに送っているとのことで、それが漏れたのかも知れないと思ってTypeAppを使うのは止め、登録したすべてのアカウントのパスワードを変更した。

ただ、そのあとで良く考えたら、TypeAppからGmailへのアクセスにはIDもパスワードも入れていない(Androidで「アクセス許可」をしただけ)ので、それらが漏れることはないのに気付いた。その他には、昨日インストールした別のアプリにも幅広く権限を得るものがあって疑わしかったのだが、それにしてもパスワードが漏れることは考えにくい。一方、昔、Linuxで使ったメールアプリにパスワードを入れた覚えがあるので、そこからの漏洩は考えられた。その他には、前述の疑わしいアプリがパスワードを総当りで推測した可能性はあるが、何度もログインに失敗したら警告が来そうだ。それでも、念のため、疑わしいアプリは削除した。

更に調べたら、他の人が自分のGoogleアカウントに2段階認証を設定する時などに電話番号を間違えて入れると、間違った電話番号にコードが届くそうだ(これは間違いであることが分かるように欲しいが、良く考えるとどうしようもない(SMSに本人の名前などを入れたらセキュリティリスクだ)。ただ、いたずら電話の道具になりそうで、嫌な予感がする)。他に、僕のメールアドレスはわかっているので、そのパスワードをリセットしようとしていることも考えられたが、その時には再設定用のアドレスにメールが届くようだからから分かる。

確かに、Googleのアカウントページには何も異常の記録がなく、警告のメールもなかったので、電話番号を間違われた可能性が高い。そういえば、どういう訳か、僕のところには以前から何度か間違い電話が掛かって来ているので、押し間違えやすい番号なのかも知れない。あるいは、ずっと僕(のアカウント)を狙っている人が居て、その工作の痕跡なのかも知れない。別に大したものはないから考え過ぎだろうが、ハインリッヒの法則からすれば、安心し過ぎるのも良くなさそうだ。注意一秒怪我一生。 (2/5 13:34)

  •   0
  •   1

コメントを書く

名前    

メール 

URL