何十億人ものユーザーを対象としたネットワーク接続

世界の半数以上のユーザーはアプリを 2G 接続で利用します。このようなユーザーのエクスペリエンスを改善するには、最適なパフォーマンスをふまえたデータの保存、リクエストのキューへの格納、画像処理を行うことで、低速接続とオフライン処理を最適化します。

ここでは、この目標を達成するためのヒントをご紹介します。

画像を最適化する

画像のダウンロードを簡単にする方法はいくつかあります。WebP 画像の配信、画像の動的なサイズ変更、画像読み込み用のライブラリの使用などが可能です。

WebP 画像を配信する

  • ネットワーク経由で WebP ファイルを配信すると、画像の読み込み時間を短縮し、ネットワーク帯域幅を節約できます。WebP ファイルは、PNG や JPG で提供した場合よりもファイルサイズが小さく、画質は同じです。不可逆圧縮の設定でも、WebP は元の画像とほぼ同等の画像を生成できます。Android 4.0(API レベル 14: Ice Cream Sandwich)以降では、不可逆圧縮の WebP サポートの対象となり、Android 4.2(API レベル 17: Jelly Bean)以降では、WebP は可逆圧縮と透明度に対応しています。

画像のサイズを動的に変更する

  • アプリはデバイスの仕様に基づいて、対象のレンダリング サイズで画像をリクエストし、サーバーは適切なサイズの画像を提供するようにします。このようにすると、ネットワークで送信されるデータを最小限に抑え、各画像の保存に要するメモリ量を削減でき、パフォーマンスとユーザーの満足度を改善できます。
  • 画像のダウンロードに時間がかかると、ユーザー エクスペリエンスが低下します。適切な画像サイズを使用すれば、このような問題を解決できます。 ネットワークの種類や品質に応じて画像サイズのリクエストを行うことを検討します。このサイズは対象のレンダリング サイズより小さくなる場合があります。
  • 事前に計算されたパレット値や低解像度のサムネイルなどの動的なプレースホルダを使用すると、画像を取得する際のユーザー エクスペリエンスが向上します。

画像読み込みライブラリを使用する

  • アプリでは画像を何度も取得しないでください。GlidePicasso などの画像読み込みライブラリは、画像を取得してキャッシュに保存し、ビューにフックを提供して実際の画像が表示できるようになるまでプレースホルダ画像を表示します。画像はキャッシュに保存されているため、次回画像がリクエストされたときにはこのライブラリがローカルコピーを返します。
  • 画像読み込みライブラリはキャッシュを管理して最新の画像を保持するため、アプリ ストレージが無制限に増大することはありません。

ネットワークを最適化する

最適なネットワーク エクスペリエンスを提供することで、ユーザー エクスペリエンスを改善できます。 たとえば、WorkManagerRoom を使用してネットワークをオフラインで使用可能にしたり、ネットワーク リクエストの重複を排除したりできます。

アプリをオフラインで使用可能にする

  • 郊外や利用の少ない地域では、デバイスがネットワーク接続を失うことがよくあります。適切なオフライン状態を作成して、ユーザーがいつでもアプリを操作できるようにします。そのためには、データのローカル保存、データのキャッシュへの保存、送信リクエストのキューへの追加を行い、接続が復元されたときにアクションを実行できるようにします。
  • 可能であれば、接続が失われたことをユーザーに通知しないようにします。通知する必要があるのは、ユーザーがネットワーク接続が不可欠な操作を行うときだけです。
  • デバイスが接続していない場合、アプリはネットワーク リクエストをユーザーに代わって一括処理する必要があります。このリクエストは、接続が回復したときに実行できます。たとえばメール クライアントでは、デバイスがオフラインの場合でも、ユーザーがメールの作成、送信、読み取り、移動、削除を行えます。これらの操作は、キャッシュに保存され、接続が復旧したときに実行できます。これにより、デバイスがオンラインかオフラインかにかかわらず、アプリが同じようなユーザー エクスペリエンスを提供できます。

Room を使用してデータを取得してキャッシュに保存する

  • アプリでデータベースまたはデータベース同様の構造を使用してすべてのデータをディスクに保存するようにして、ネットワークの状態に関係なく最適なパフォーマンスを実現します。 Room 永続ライブラリを使用してローカル データベースにデータをキャッシュ保存し、WorkManager を使用してデバイスがネットワーク接続されたときにこのキャッシュを更新します。
  • アプリはネットワークから取得したコンテンツをキャッシュに保存する必要があります。それ以降のリクエストを実行する前に、ローカルでキャッシュ保存したデータを表示する必要があります。この処理により、デバイスがオフラインの場合や、低速または信頼性が低いネットワークに接続している場合でも、アプリを機能させることができます。

ネットワーク リクエストの重複除去

  • オフラインを優先したアーキテクチャでは、まずローカル ストレージからデータを取得しようとします。これに失敗すると、ネットワークからのデータ取得をリクエストします。データがネットワークから取得されると、後で取得できるようにローカルでキャッシュに保存されます。これにより、同じデータに対するネットワーク リクエストは 1 回だけ実行され、後続のリクエストはローカルで処理されるようになります。その場合、長期間にわたって使用するデータにはローカル データベースを使用します(通常は android.database.sqlite または SharedPreferences)。
  • このアーキテクチャでは、オフライン状態とオンライン状態の間のアプリのフローが簡素化されます。一方ではネットワークから取得してキャッシュに保存し、他方ではキャッシュからデータが取得され、ユーザーに表示されます。
  • 一時的なデータには、DiskLruCache などの制限付きディスク キャッシュを使用します。 通常、変更されないデータは、ネットワーク経由で 1 回だけリクエストされ、将来の使用に備えてキャッシュに保存されます。ニュース記事やソーシャル投稿など、画像や一時的ではないドキュメントがこれに該当します。

データ転送を微調整する

アプリをネットワークの状態に適応させてユーザー エクスペリエンスを改善する方法はいくつかあります。たとえば、ネットワーク リクエストに優先順位を付け、ユーザーに情報が表示されるまでの待ち時間を最小限にできます。また、低速なネットワーク速度やネットワーク接続で発生する変更を検出して調整することもできます。

帯域幅の優先度を設定する

  • デバイスの接続先ネットワークが長時間接続でき、または信頼できるとは限りません。このため、アプリはネットワーク リクエストの優先順位を設定し、できるだけ早く最も有用な情報をユーザーに表示する必要があります。
  • 必要性の薄い情報を取得するために待たせるより、表示可能で関連性の高い情報をすぐに見せるほうがユーザー エクスペリエンスは向上します。これにより、ユーザーの待ち時間が短縮され、低速のネットワークでもアプリの利便性が高まります。
  • そのためには、リッチメディアよりも先にテキストを取得するようにネットワーク リクエストのシーケンスを設定します。テキスト リクエストのほうがサイズが小さく、圧縮率が高く、高速に転送できる傾向があるため、有用なコンテンツを迅速にアプリで表示できます。ネットワーク リクエストの管理の詳細については、ネットワークの使用状況の管理に関する Android トレーニングをご覧ください。

低速の接続で利用する帯域幅を少なくする

  • アプリが適切なタイミングでデータを転送できるかどうかは、ネットワーク接続に依存します。ネットワークの品質を検出してアプリ側でネットワークの使用方法を調整すれば、最適なユーザー エクスペリエンスを実現できます。
  • 次の方法を使用して、基盤となるネットワークの品質を検出できます。これらのメソッドで取得したデータを使用して、アプリでのネットワークの使用方法を調整し、ユーザー アクションにタイムリーなレスポンスを返し続ける必要があります。
  • 低速の接続では、低解像度のメディアのみダウンロードするか、メディアを一切ダウンロードしないことを検討してください。これにより、ユーザーは低速の接続でアプリを使用できます。画像がないか、画像がまだ読み込み中の場合、必ずプレースホルダを表示します。Palette ライブラリを使用して、対象の画像に合ったプレースホルダのカラーを生成することで、動的なプレースホルダを作成できます。
  • Android 7.0(API レベル 24)以降を搭載したデバイスでは、データセーバー設定をオンにしてデータ使用量を最小限に抑えることができます。Android 7.0 では ConnectivityManager が拡張され、データセーバー設定が検出されます。この機能の詳細については、データセーバーをご覧ください。

ネットワークの変化を検出してアプリの動作を変更する

  • ネットワークの品質は一定ではありません。場所、ネットワークトラフィック、ローカルのユーザー密度に応じて変化します。アプリはネットワークの変化を検出し、それに応じて帯域幅を調整する必要があります。そうすることで、ネットワークの品質に合わせてアプリのユーザー エクスペリエンスを調整できます。ネットワークの状態を検出するには、次のメソッドを使用します。
  • ネットワークの品質が低下したら、リクエストの数とサイズを削減します。接続品質が向上すれば、最適なレベルにリクエストをスケールアップできます。
  • 高品質の定額制ネットワークでは、データをプリフェッチしてあらかじめ利用できるようにすることを検討してください。つまり、ユーザー エクスペリエンスの観点から言えば、2G 接続の場合にはニュース リーダー アプリで一度に 3 件の記事が取得されますが、Wi-Fi 接続であれば一度に 20 件の記事が取得できるということです。ネットワークの変化に基づくアプリの動作の調整について詳しくは、接続ステータスのモニタリングに関する Android トレーニングをご覧ください。
  • ネットワーク接続の変化が発生すると、CONNECTIVITY_CHANGE のブロードキャストが送信されます。アプリがフォアグラウンドのときは、registerReceiver を呼び出して、このブロードキャストを受信できます。このブロードキャストを受信したら、現在のネットワークの状態を再評価して、UI とネットワークの使用を適切に調整する必要があります。Android 7.0(API レベル 24)以降では使用できないため、マニフェストでこのレシーバを宣言しないでください。 この点を含む Android 7.0 の変更点の詳細は、Android 7.0 の変更点をご覧ください。

参考情報

さまざまな接続速度のサポートについて詳しくは、次のリソースをご覧ください。

ブログ投稿