Google は、黒人コミュニティに対する人種平等の促進に取り組んでいます。取り組みを見る

冗長なダウンロードを回避する

アプリのユーザーの多くは、インターネット アクセスが断続的であったり、デバイスにダウンロードできる情報の量に制限があったりします。アプリでダウンロードする必要があるデータの量を減らすことで、ユーザーがアプリをより頻繁に操作するように促すことができます。

ダウンロードを削減する最も基本的な方法は、必要なものだけをダウンロードすることです。データに関しては、これは REST API を実装することを意味します。この API では、最終更新日時などのパラメータを使用して、返されるデータを制限するクエリ条件を指定できます。

同様に、画像をダウンロードする場合は、フルサイズの画像をダウンロードしてクライアント側で削減してもらうのではなく、サーバー側で画像のサイズを削減することをおすすめします。

ファイルをローカルにキャッシュする

もう 1 つの重要な手法は、重複データのダウンロードを回避することです。キャッシュを使用すると、同じデータを繰り返しダウンロードする可能性を減らすことができます。アプリのデータとリソースをキャッシュすることにより、アプリが参照する必要がある情報のローカルコピーを作成します。アプリが同じ情報に短期間に何度もアクセスする必要がある場合、キャッシュにダウンロードする必要があるのは 1 回だけです。

ダウンロードするデータの合計量を減らすには、できるだけ積極的にキャッシュすることが重要です。合理的に可能な限り、静的リソース(フルサイズの画像などのオンデマンド ダウンロードを含む)をキャッシュするようにしてください。オンデマンド キャッシュを定期的にフラッシュしてサイズを管理できるように、オンデマンド リソースは個別に保存する必要があります。

キャッシュによってアプリに古いデータが表示されないようにするには、HTTP 応答ヘッダーから、要求されたコンテンツの最終更新日時と有効期限を抽出してください。これにより、関連付けられたコンテンツを更新するタイミングを決定できます。

Kotlin

    val conn: HttpsURLConnection = url.openConnection() as HttpsURLConnection
    val currentTime: Long = System.currentTimeMillis()
    val expires: Long = conn.getHeaderFieldDate("Expires", currentTime)
    val lastModified: Long = conn.getHeaderFieldDate("Last-Modified", currentTime)
    if (lastModified < lastUpdateTime) {
        // Skip update
    } else {
        // Parse update
        lastUpdateTime = lastModified
    }
    

Java

    // url represents the website containing the content to place into the cache.
    HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();

    long currentTime = System.currentTimeMillis();
    long expires = conn.getHeaderFieldDate("Expires", currentTime);
    long lastModified = conn.getHeaderFieldDate("Last-Modified", currentTime);

    // lastUpdateTime represents when the cache was last updated.
    if (lastModified < lastUpdateTime) {
        // Skip update
    } else {
        // Parse update
        lastUpdateTime = lastModified;
    }
    

また、この手法を使用すると、動的コンテンツを効果的にキャッシュしつつ、アプリに古い情報が表示されないようにすることができます。

機密情報でないデータは、Context#getExternalCacheDir() を通じて取得した非マネージド外部キャッシュ ディレクトリにキャッシュできます。

あるいは、Context#getCacheDir() を通じて取得したマネージド セキュア アプリ キャッシュを使用することもできます。ただし、この内部キャッシュは、システム内の利用可能なストレージが不足すると、フラッシュされる可能性があります。

注: どちらのキャッシュ場所にファイルを保存したとしても、アプリをアンインストールすると、すべて消去されます。

HttpsURLConnection レスポンス キャッシュを使用する

Android 4.0 で、HttpsURLConnection にレスポンス キャッシュが追加されました。リフレクションを使用することで、サポート対象デバイス上で HTTP レスポンス キャッシュを有効にできます。たとえば、次のようになります。

Kotlin

    private fun enableHttpResponseCache() {
        try {
            val httpCacheSize: Long = 10L * 1024L * 1024L // 10 MiB
            val httpCacheDir = File(cacheDir, "http")
            Class.forName("android.net.http.HttpResponseCache")
                    .getMethod("install", File::class.java, Long::class.javaPrimitiveType)
                    .invoke(null, httpCacheDir, httpCacheSize)
        } catch (httpResponseCacheNotAvailable: Exception) {
            Log.d(TAG, "HTTP response cache is unavailable.")
        }
    }
    

Java

    private void enableHttpResponseCache() {
      try {
        long httpCacheSize = 10 * 1024 * 1024; // 10 MiB
        File httpCacheDir = new File(getCacheDir(), "http");
        Class.forName("android.net.http.HttpResponseCache")
             .getMethod("install", File.class, long.class)
             .invoke(null, httpCacheDir, httpCacheSize);
      } catch (Exception httpResponseCacheNotAvailable) {
        Log.d(TAG, "HTTP response cache is unavailable.");
      }
    }
    

このサンプルコードは、以前のリリースに影響を与えることなく、Android 4.0 以降のデバイス上でレスポンス キャッシュを有効にします。

キャッシュを導入すると、完全にキャッシュされた HTTP リクエストをローカル ストレージから直接配信できるようになるため、ネットワーク接続を開く必要がなくなります。条件に応じてレスポンスをキャッシュすることで、サーバーからのデータ鮮度を確認できるため、ダウンロードに伴う帯域幅コストを削減できます。

まだキャッシュされていなかったレスポンスは、今後のリクエストに備えてレスポンス キャッシュに保存されます。