Closed15

Now in Android のインターネット接続まわりの調査

sanaosanao

now in android はアプリがインターネットに接続してるかをどうやってチェックしているんだろうかと気になったので調査する。

どうやらisOfflineという変数でチェックしているように見える

https://github.com/android/nowinandroid/blob/b85d149f0d8a9cdc855654459562ebfd47521259/app/src/main/kotlin/com/google/samples/apps/nowinandroid/ui/NiaAppState.kt#L106-L112

Flowを使っている。
networkMonitor とはなんだろう

networkMonitor: NetworkMonitor
sanaosanao

40~45行目
https://github.com/android/nowinandroid/blob/b85d149f0d8a9cdc855654459562ebfd47521259/core/data/src/main/kotlin/com/google/samples/apps/nowinandroid/core/data/util/ConnectivityManagerNetworkMonitor.kt#L40-L45

まずApplicationContextからConnectivityManagerクラスを取得しようとしている。
https://developer.android.com/develop/connectivity/network-ops/reading-network-state?hl=ja
ConnectivityManagerとは、Androidでネットワークの接続などを管理するクラスで、ネットワーク接続が変更されたときにアプリに通知したりする。
https://scrapbox.io/sanasana/ConnectivityManager
これがnullの時はインターネットにつながっていないので即座にチャンネルにfalseを送ってチャンネルを閉じている。
ときにConnectivityManagerがnullとはどんな状況なのだろうか

sanaosanao

ChatGPTいわく

  1. コンテキストが不適切な場合: context がアクティビティやサービスのコンテキストでない場合、システムサービスを取得できない可能性があります。たとえば、context が null である場合や、アプリケーションのライフサイクル中にコンテキストが失われる場合が考えられます。
  2. デバイスが不適切な構成を持つ場合: 一部のデバイスは、特定の機能を無効にしているか、サポートしていない場合があります。例えば、一部のエミュレーター設定では、ネットワーク接続をシミュレートする機能が無効になっている場合があります。
  3. デバイスのセキュリティ設定: ユーザーがデバイスのセキュリティ設定を変更して、特定のアプリケーションがネットワークにアクセスできないように制限している場合があります。このような制限は、Android のアプリケーション設定やデバイス管理ポリシーによって設定される場合があります。
  4. ランタイムパーミッションの不足: アプリケーションが必要なランタイムパーミッションを持っていない場合、システムサービスにアクセスできないことがあります。たとえば、ネットワークの状態を取得するためには、ACCESS_NETWORK_STATE パーミッションが必要です。パーミッションが不足している場合、getSystemService() は null を返す可能性があります。

デバイス側の問題が多そう?

sanaosanao
sanaosanao

networksSetには利用可能なネットワークが来たらどんどん追加してチャンネルにtrueを送る。
ネットワークをロストしたらSetから取り除く。
この時、networksが空だったらfalse、それ以外だったらtrueをチャンネルに送る

sanaosanao

コメントを翻訳してみる

コールバックのメソッドは、アクティブなネットワークだけでなく、[NetworkRequest]にマッチするすべてのネットワークの変更時に呼び出される。したがって、単純にそのような[Network]の存在(または不在)を追跡することができる。

NetworkRequestっていうのは使用可能な範囲にあるネットワークの探索ってことだろうか。

NetworkCallbackコールバックで新しくネットワークが追加されたり消えたりするのを追跡できるってことだと思う

sanaosanao

66~68行目
https://github.com/android/nowinandroid/blob/b85d149f0d8a9cdc855654459562ebfd47521259/core/data/src/main/kotlin/com/google/samples/apps/nowinandroid/core/data/util/ConnectivityManagerNetworkMonitor.kt#L66-L68
ここではNetworkRequestクラスを生成している。
https://developer.android.com/reference/android/net/NetworkRequest
NetworkRequestはざっくりいうとアプリが特定のネットワークを要求または監視するためのオブジェクトのこと。
addCapabilityで要求するネットワークの属性を与える。
機能はNetworkCapabilitiesから選択することができて、

NetworkCapabilities.NET_CAPABILITY_INTERNET

は単に一般のインターネットに到達できることを示す。他にもいろいろな種類があるっぽい
https://developer.android.com/reference/android/net/NetworkCapabilities

sanaosanao

79行目ではインターネットにつながっている限りtrueをチャンネルへ送信している

sanaosanao

awaitCloseはFlow Channelがクローズまたはキャンセルされるまで処理をブロックする。

https://developer.android.com/develop/connectivity/network-ops/reading-network-state?hl=ja#listening-events

注: 同時に登録できるコールバックの数には上限があります。不要になったコールバックは登録を解除して、アプリでさらに登録できるようにします。

この理由からawaitCloseブロック内で同時にcallbackを解除している

sanaosanao

最初に戻ってisOfflineが使われている箇所はここ

https://github.com/android/nowinandroid/blob/b85d149f0d8a9cdc855654459562ebfd47521259/app/src/main/kotlin/com/google/samples/apps/nowinandroid/ui/NiaApp.kt#L112

https://github.com/android/nowinandroid/blob/b85d149f0d8a9cdc855654459562ebfd47521259/app/src/main/kotlin/com/google/samples/apps/nowinandroid/ui/NiaApp.kt#L116-L123

isOfflineがtrueならば警告のスナックバーを表示させている

なんかConnectivityManagerNetworkMonitor内で定義している変数がisOnlineなのに実際に使っているのはisOfflineだからちょっと違和感ある

このスクラップは2024/02/13にクローズされました