無線通信を使用してデータを転送することは、アプリのバッテリーを最も消耗する原因の一つです。ネットワーク アクティビティに関連するバッテリーの消耗を最小限に抑えるには、接続モデルが基盤となる無線ハードウェアにどのように影響するかを理解することが重要です。
このセクションでは、ワイヤレス無線ステートマシンと、アプリの接続モデルがそれとどのように相互作用するかについて説明します。また、アプリのデータ消費がバッテリーに及ぼす影響を最小限に抑えるための手法もいくつか紹介します。
無線通信のステートマシン
ユーザーのデバイスのワイヤレス無線には、消費電力を最小限に抑えるための省電力機能が組み込まれています。完全にアクティブな状態では、ワイヤレス無線は大量の電力を消費しますが、非アクティブな状態やスタンバイ状態では、無線はほとんど電力を消費しません。
重要な要素として、無線はスタンバイから完全なアクティブ状態に瞬時に移行できないという点に注意する必要があります。無線通信の「起動」には、レイテンシ期間が伴います。そのため、バッテリーは、無線通信の「電源投入」に伴うレイテンシを最小限に抑えながら、使用していないときの電力を節約するために、高エネルギー状態から低エネルギー状態にゆっくりと移行します。
一般的な 3G ネットワークの無線通信のステートマシンは、以下の 3 つのエネルギー状態で構成されます。
- フルパワー: 接続がアクティブな場合に使用され、デバイスは可能な限り高いレートでデータを転送できます。
- 低電力: バッテリー消費量を約 50% 削減する中間状態。
- スタンバイ: ネットワーク接続がアクティブでない、最小限の電力消費状態。
低電力状態とスタンバイ状態では、バッテリーの消耗は大幅に軽減されますが、ネットワーク リクエストのレイテンシが大幅に増加します。低電力状態からフルパワーに戻るには約 1.5 秒かかり、スタンバイからフルパワーに移行するには 2 秒以上かかることがあります。
レイテンシを最小限に抑えるため、ステートマシンは遅延を使用して、低エネルギー状態への移行を延期します。図 1 では、AT&T が測定した一般的な 3G 無線通信のタイミングを使用しています。
図 1. 一般的な 3G 無線通信のステートマシン
各デバイスの無線ステートマシン、特に関連する遷移遅延(「テールタイム」)と起動レイテンシは、採用されている無線技術(3G、LTE、5G など)によって異なり、デバイスが動作している携帯通信会社ネットワークによって定義、構成されます。
このページでは、AT&T から提供されたデータに基づいて、一般的な 3G ワイヤレス無線の代表的なステートマシンについて説明します。ただし、一般的な原則と、その結果として得られるベスト プラクティスは、すべてのワイヤレス無線実装に適用されます。
このアプローチは、ユーザーがウェブを閲覧する際の不要なレイテンシを回避できるため、一般的なモバイルウェブ ブラウジングに特に効果的です。また、テールタイムが比較的短いため、ブラウジング セッションが終了すると、無線通信は低電力状態に移行できます。
残念ながら、このアプローチは、Android のような最新のスマートフォン オペレーティング システムでは、アプリの効率低下につながる可能性があります。Android では、アプリはフォアグラウンド(レイテンシが重要)とバックグラウンド(バッテリー駆動時間を優先する必要がある)の両方で実行されます。
アプリが無線ステートマシンに与える影響
新しいネットワーク接続を作成するたびに、無線はフルパワー状態に移行します。前述の一般的な 3G 無線ステートマシンの場合、転送中と、それに続く 5 秒間のテールタイムの間はフルパワーを維持し、その後 12 秒間は低エネルギー状態になります。つまり、一般的な 3G デバイスでは、データ転送セッションごとに、無線が少なくとも 18 秒間電力を消費します。
実際には、1 秒間のデータ転送を 1 分間に 3 回行うアプリは、ワイヤレス無線を常にアクティブな状態に保ち、スタンバイ モードに入るとすぐに高電力モードに戻します。
図 2. 1 分間に 3 回実行される 1 秒間の転送の相対的な無線電力使用量。この数値には、実行間の「パワーアップ」レイテンシは含まれていません。
これに対し、同じアプリがデータ転送をバンドルし、1 分ごとに 3 秒間の転送を 1 回実行する場合、無線がハイパワー状態になるのは 1 分あたり合計 20 秒だけです。これにより、無線は 1 分のうち 40 秒間スタンバイ状態になり、バッテリー消費量が大幅に削減されます。
図 3. 1 分に 1 回実行される 3 秒間の転送の相対的な無線電力使用量。
最適化の手法
ネットワーク アクセスがバッテリー駆動時間に与える影響を理解したところで、バッテリーの消耗を抑えつつ、高速でスムーズなユーザー エクスペリエンスを提供するためにできることをいくつか紹介します。
データ転送をバンドルする
前のセクションで説明したように、データ転送をバンドルして、より多くのデータをより少ない頻度で転送することは、バッテリー効率を改善する最善の方法の一つです。
もちろん、ユーザーのアクションに応じてアプリがすぐにデータを送受信する必要がある場合は、必ずしもこれが可能とは限りません。この問題は、データを予測してプリフェッチすることで軽減できます。サーバーへのログや分析の送信、その他の緊急性の低いアプリ開始のデータ転送など、他のシナリオは、バッチ処理やバンドルに非常に適しています。バックグラウンド ネットワーク転送のスケジュール設定に関するヒントについては、アプリ開始型タスクの最適化をご覧ください。
プリフェッチ データ
データのプリフェッチは、アプリが実行する独立したデータ転送セッションの数を減らすためのもう一つの効果的な方法です。プリフェッチでは、ユーザーがアプリ内でアクションを実行したときに、次のユーザー アクションに必要となる可能性が最も高いデータをアプリが予測して、1 回の接続で一括取得します。
転送をフロントローディングすることで、データのダウンロードに必要な無線通信の起動回数を減らすことができます。その結果、バッテリーを節約できるだけでなく、レイテンシの改善、必要な帯域幅の削減、ダウンロード時間の短縮も実現できます。
プリフェッチは、アクションの実行やデータの表示の前にダウンロードの完了を待つことによって発生するアプリ内レイテンシを最小限に抑えることで、ユーザー エクスペリエンスを向上させます。
実際の例を見てみましょう。
ニュース リーダー
多くのニュースアプリでは、カテゴリが選択された後にのみ見出しをダウンロードし、ユーザーが読みたい場合にのみ記事全体をダウンロードし、スクロールして表示されたときにのみサムネイルをダウンロードすることで、帯域幅を削減しようとしています。
この方法では、ユーザーがヘッドラインをスクロールしたり、カテゴリを変更したり、記事を読んだりするニュース閲覧セッションの大半で、無線通信が強制的にアクティブな状態になります。それだけでなく、エネルギー状態が頻繁に切り替わるため、カテゴリの切り替えや記事の読み込み時に大きなレイテンシが発生します。
より良い方法は、起動時に適度な量のデータをプリフェッチすることです。まず、ニュースの見出しとサムネイルの最初のセットから始めて、低レイテンシの起動時間を確保します。その後、残りの見出しとサムネイル、および少なくともメインの見出しリストから利用可能な各記事の記事テキストをプリフェッチします。
別の方法として、すべての見出し、サムネイル、記事のテキスト、場合によっては記事の画像全体を、通常はバックグラウンドで、事前に決められたスケジュールに従ってプリフェッチすることもできます。このアプローチでは、使用されないコンテンツのダウンロードに大量の帯域幅とバッテリーが消費されるリスクがあるため、慎重に実装する必要があります。
その他の考慮事項
データのプリフェッチには多くのメリットがありますが、プリフェッチを過度に使用すると、使用されないデータをダウンロードすることになり、バッテリーの消耗や帯域幅の使用量、ダウンロード割り当てが増加するリスクもあります。また、プリフェッチの完了を待つ間にアプリの起動が遅れないようにすることも重要です。実際には、データを段階的に処理するか、アプリの起動に必要なデータが最初にダウンロードされて処理されるように優先順位を付けて連続転送を開始することを意味します。
データをどの程度積極的にプリフェッチするかは、ダウンロードするデータのサイズと、そのデータが使用される可能性によって異なります。大まかな目安として、前述の状態マシンに基づき、現在のユーザー セッション内で使用される可能性が 50% のデータの場合、通常は 6 秒程度(約 1 ~ 2 MB)プリフェッチできます。これは、未使用のデータをダウンロードする潜在的なコストが、そもそもそのデータをダウンロードしないことによる潜在的な節約額と一致する前の段階です。
一般的に、2 ~ 5 分ごとに 1 ~ 5 MB 程度の別のダウンロードを開始するだけで済むように、データをプリフェッチすることをおすすめします。
この原則に従って、動画ファイルなどの大きなダウンロードは、一定の間隔(2 ~ 5 分ごと)でチャンクに分割してダウンロードする必要があります。これにより、次の数分間に視聴される可能性が高い動画データのみを効果的にプリフェッチできます。
1 つの解決策は、Wi-Fi に接続しているとき、場合によってはデバイスが充電中のときにのみ、完全なダウンロードが行われるようにスケジュールすることです。WorkManager API は、まさにこのユースケースをサポートしており、デバイスがデベロッパー指定の条件(充電中、Wi-Fi に接続中など)を満たすまで、バックグラウンド処理を制限できます。
リクエストを行う前に接続を確認する
モバイル通信の電波を探すことは、モバイル デバイスで最も電力を消費するオペレーションの一つです。ユーザーが開始したリクエストのベスト プラクティスは、接続のステータスと種類をモニタリングするで説明されているように、まず ConnectivityManager を使用して接続を確認することです。ネットワークがない場合、アプリはモバイル無線に検索を強制しないことでバッテリーを節約できます。リクエストは、接続が確立されたときに、他のリクエストとともにバッチでスケジュールされ、実行されます。
プール接続
バッチ処理とプリフェッチに加えて、アプリのネットワーク接続をプールすることも有効な戦略です。
一般に、新しいネットワーク接続を開始するよりも、既存のネットワーク接続を再利用する方が効率的です。接続を再利用すると、ネットワークは輻輳や関連するネットワーク データの問題に、よりインテリジェントに対応できるようになります。
HttpURLConnection とほとんどの HTTP クライアント(OkHttp など)では、デフォルトで接続プーリングが有効になっており、複数のリクエストで同じ接続が再利用されます。
まとめと今後の展望
このセクションでは、ワイヤレス無線と、バッテリーの消耗を抑えながら高速で応答性の高いユーザー エクスペリエンスを提供するために幅広く適用できる戦略について学びました。
次のセクションでは、ほとんどのアプリに共通する 3 種類のネットワーク インタラクションについて詳しく説明します。これらの各タイプのドライバと、これらのインタラクションを効率的に管理するための最新の手法と API について説明します。