ネットワークに関する問題のトラブルシューティング

アプリによって生成されるネットワーク トラフィックは、デバイスのバッテリー駆動時間に大きな影響を与える可能性があります。このトラフィックを最適化するには、トラフィックを測定してそのソースを特定する必要があります。ネットワーク リクエストは、ユーザーのアクション、独自のアプリコード、アプリと通信するサーバーから直接送信されることがあります。

このトピックでは、ネットワーク トラフィックをモニタリングして分類する方法と、問題を特定して解決するためのガイダンスについて説明します。

Network Profiler を使用してリクエストをモニタリングする

Network Profilerを使用して、アプリのネットワーク リクエストを追跡します。アプリがデータを転送した方法とタイミングをモニタリングし、基盤となるコードを適切に最適化できます。



図 1. ネットワーク トラフィックの追跡。ネットワーク トラフィック パターンから、リクエストのプリフェッチやアップロードのバンドルによって効率を大幅に改善できることがわかります。

データ転送の頻度と、各接続中に転送されるデータ量をモニタリングすることで、アプリのバッテリー効率を向上できる領域を特定できます。一般に、遅延する可能性のある短いスパイクを探します。

転送の急増の原因をより正確に特定するために、Traffic Stats API を使用すると、TrafficStats.setThreadStatsTag() を使用して、特定の Thread 内のソケットから発生するデータ転送にタグを付けることができます。この関数を呼び出しても、特定のスレッドのすべてのトラフィックに自動的にタグが付けられるわけではありません。タグはソケットに適用する必要があります。

スレッドタグを設定したら、TrafficStats.tagSocket() と TrafficStats.untagSocket() を使用して、個々のソケットを手動でタグ付け / タグ解除できます。スレッドでソケットが開かれた場合や、サーバー ソケットが接続を受け入れた場合にも、タグが適用されます。

複数のスレッドが同じソケットに同時にアクセスすると、ネットワーク パケットの送受信時にソケットに設定されていたタグが使用されます(バッファリングと再送信により、ユーザーがデータを書き込んだり読み取ったりしたときとは異なる場合があります)。

たとえば、次のコードサンプルに示すように、さまざまなタイプのネットワーク トラフィックを表す定数を定義できます。

Kotlin

const val USER_INITIATED = 0x1000
const val APP_INITIATED = 0x2000
const val SERVER_INITIATED = 0x3000

Java

public static final int USER_INITIATED = 0x1000;
public static final int APP_INITIATED = 0x2000;
public static final int SERVER_INITIATED = 0x3000;

その後、ネットワーク リクエストに適切なタグを付けることができます。

Kotlin

TrafficStats.setThreadStatsTag(USER_INITIATED)
TrafficStats.tagSocket(outputSocket)
// Transfer data using socket
TrafficStats.untagSocket(outputSocket)

Java

TrafficStats.setThreadStatsTag(USER_INITIATED);
TrafficStats.tagSocket(outputSocket);
// Transfer data using socket
TrafficStats.untagSocket(outputSocket);

HttpURLConnection ライブラリは、現在の TrafficStats.getThreadStatsTag() 値に基づいてソケットに自動的にタグを付けます。次のコードサンプルに示すように、このライブラリは、キープアライブ プールを介してリサイクルされるときにソケットのタグ付けとタグ解除も行います。

Kotlin

class IdentifyTransferSpikeTask {
    @WorkerThread
    fun request(url: String) {
        TrafficStats.setThreadStatsTag(APP_INITIATED)
        // Make network request using HttpURLConnection.connect()
        ...
        TrafficStats.clearThreadStatsTag()
    }
}

Java

public class IdentifyTransferSpikeTask {
    @WorkerThread
    public void request(String url) {
        TrafficStats.setThreadStatsTag(APP_INITIATED);
        // Make network request using HttpURLConnection.connect()
        ...
        TrafficStats.clearThreadStatsTag();
    }
}

ネットワーク トラフィックのタイプを分析する

アプリが生成したネットワーク トラフィックについて調査する際は、トラフィックのソースを把握する必要があります。これにより、ネットワーク トラフィックを適切に最適化できます。アプリが頻繁にネットワーク アクティビティを生成している場合でも、それがユーザーのアクションに応答したものであれば完全に適切です。しかし、アプリがフォアグラウンドにいなかった場合や、デバイスがポケットやかばんに入っていた場合は、完全に不適切です。

ユーザー開始型トラフィックを分析する

ユーザーが開始するネットワーク トラフィックは、ユーザーがアプリ内で特定のタスクを実行している場合は、効率的にグループ化され、ユーザーがアプリに対して追加情報を取得するようリクエストした場合は、不均一に広がることがあります。ユーザー開始型ネットワーク トラフィックを分析する目的は、ネットワークを頻繁に使用するパターンを調べて、リクエストをグループ化することで頻度を減らすことです。

ユーザー リクエストは予想できないため、アプリ内でこのタイプのネットワーク使用を最適化するのは難しい場合があります。また、ユーザーはアプリを積極的に使用しているとき、迅速なレスポンスを期待するため、リクエストが遅延すると、ユーザー エクスペリエンスの低下につながる可能性があります。一般的に、ユーザーがアプリを直接操作しているときは、ネットワーク使用の効率化よりも、迅速なレスポンスを優先することをおすすめします。

ユーザー開始型トラフィックを最適化するための推奨事項については、ユーザー開始型リクエストを最適化するをご覧ください。

アプリ開始型トラフィックを分析する

一般的に、アプリ開始型ネットワーク トラフィックは、ネットワーク帯域幅の効率的な使用に大きく影響します。アプリのネットワーク アクティビティを分析する際は、非アクティブになっている期間を探し出し、それを増やすことができるかどうかを判断します。アプリのネットワーク アクセスに一貫したパターンが見つかった場合は、そのようなトラフィックをバッチ処理して、アクティビティの合間にデバイスの無線通信を低消費電力モードに切り替えることができるようにします。

アプリ開始型トラフィックを最適化するための推奨事項については、アプリ開始型リクエストを最適化するをご覧ください。

サーバー開始型トラフィックを分析する

サーバーがアプリと通信する際に開始するネットワーク アクティビティも、ネットワーク帯域幅の効率的な使用に大きく影響します。Firebase Cloud Messaging(FCM)は、サーバーから特定のアプリ インスタンスにデータを送信するために使用される軽量なメカニズムです。FCM を使用すると、サーバーは、特定のデバイスで実行されているアプリに、新しいデータが利用可能であることを通知できます。

サーバー開始型トラフィックを最適化するための推奨事項については、サーバー開始型リクエストを最適化するをご覧ください。

Battery Historian を使用してネットワーク トラフィックの影響を可視化する

Battery Historian は、一定期間におけるデバイスのバッテリー消費量を可視化するツールです。このツールを使用すると、ネットワーク アクティビティがバッテリー消費にどのように影響するかを分析できます。たとえば、Battery Historian を使用すると、アプリが想定よりも頻繁にセル無線通信を使用しているかどうかを確認できます。Battery Historian の使用方法について詳しくは、Batterystats と Battery Historian を使用してバッテリー使用量をプロファイリングするをご覧ください。