単にネットワークの接続状態を監視したかったのですが、Android 7 Nougat以降では方法が異なり十数分ほど無駄にしたのでメモしておきます。Nougatでの変更点としてまとめられている記事はいくつかありますがこの点が他の情報に埋もれているように思いました。
<manifest ...>
<application ...>
<receiver android:name=".NetworkWatcher">
<intent-filter>
<action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
</intent-filter>
</receiver>
</application>
</manifest>
Nougatをターゲットにしているプロジェクトでは、上記のようにAndroidManifest.xml
に記述すると次のようなWarningが出ます。
Declaring a broadcastreceiver for android.net.conn.CONNECTIVITY_CHANGE is deprecated for apps targeting N and higher. In general, apps should not rely on this broadcast and instead use JobScheduler or GCMNetworkManager.
Nougat以降ではAndroidManifest.xml
にandroid.net.conn.CONNECTIVITY_CHANGE
を設定しても無視されます。
Monitor for Changes in Connectivity
Apps targeting Android 7.0 (API level 24) and higher do not receive CONNECTIVITY_ACTION broadcasts if they declare the broadcast receiver in their manifest. Apps will still receive CONNECTIVITY_ACTION broadcasts if they register their BroadcastReceiver with Context.registerReceiver() and that context is still valid.
Determining and Monitoring the Connectivity Status
しかし、公式ページに書かれているようにコードで指定するとOKということです。
上記AndroidManifest.xml
の記述とともにApplication
サブクラスにNougat以降を指定した処理を記述することで動作を確認できました。
class MainApplication : Application() {
override fun onCreate() {
super.onCreate()
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
registerReceiver(NetworkWatcher(), IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION))
}
}
}
// MainApplicationはAndroidManifest.xmlで登録済み
// <manifest ...>
// <application android:name=".MainApplication">
// ...
// </application>
// </manifest>
class NetworkWatcher : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
if (intent == null || context == null) return
val action = intent.action
if (action != ConnectivityManager.CONNECTIVITY_ACTION) return
// do something
}
}
Nougatより前のバージョンではアプリを終了してもBroadcastReceiver
が実行されますが、Nougat以降では実行されません。バッテリー節約のためこのような仕様変更を行ったそうです。