Android 7.0+中android.net.conn.CONNECTIVITY_CHANGE适配及注册问题
Android Pie中
CONNECTIVITY_CHANGE广播失效的解决方案 这个问题我之前也碰到过,核心原因是Android 7.0(API 24)开始系统对隐式广播做了严格限制,直接导致你在Manifest里静态注册的接收器收不到android.net.conn.CONNECTIVITY_CHANGE广播了。下面给你详细拆解规则、兼容方案和处理细节:
一、Android 7.0+ 关于android.net.conn.CONNECTIVITY_CHANGE的注册规则
- 从**API 24(Android 7.0)**起,系统禁止通过
AndroidManifest.xml静态注册接收CONNECTIVITY_CHANGE这类隐式广播,仅有的例外场景是:- 你的应用是系统应用
- 应用处于前台运行状态(但静态注册依然不稳定,官方完全不推荐)
- 官方指定的正确方式是动态注册BroadcastReceiver,要在组件(Activity/Fragment/Service)的生命周期方法中完成注册与注销,避免内存泄漏。
二、兼容的Action与替代方案
1. WiFi状态监听的替代Action
如果你的需求只是检测WiFi连接状态,除了原有的android.net.wifi.WIFI_STATE_CHANGED(静态注册仍有效),还可以使用:
android.net.wifi.STATE_CHANGE:当WiFi连接到热点、断开热点时触发,静态注册也能接收,但同样推荐动态注册更可靠。
2. 全网络状态监听的官方替代方案
如果需要监听所有网络类型的连接变化,推荐使用**ConnectivityManager.NetworkCallback**(API 21引入),这是官方替代广播的方案,效率更高且不受隐式广播限制。
三、修改后的代码示例
1. 动态注册BroadcastReceiver示例
在你的Activity中添加以下代码,同时删除Manifest里对应的静态注册:
private ExampleBroadcast mWifiReceiver; @Override protected void onResume() { super.onResume(); // 初始化接收器并注册 mWifiReceiver = new ExampleBroadcast(); IntentFilter filter = new IntentFilter(); filter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION); filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION); registerReceiver(mWifiReceiver, filter); } @Override protected void onPause() { super.onPause(); // 注销接收器,避免内存泄漏 if (mWifiReceiver != null) { unregisterReceiver(mWifiReceiver); mWifiReceiver = null; } }
2. 使用NetworkCallback的优化示例(推荐)
private ConnectivityManager.NetworkCallback mNetworkCallback; private ConnectivityManager mConnectivityManager; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mConnectivityManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE); // 定义网络状态回调 mNetworkCallback = new ConnectivityManager.NetworkCallback() { @Override public void onAvailable(Network network) { super.onAvailable(network); // 网络可用时,判断是否为WiFi NetworkCapabilities capabilities = mConnectivityManager.getNetworkCapabilities(network); if (capabilities != null && capabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)) { Toast.makeText(MainActivity.this, "WiFi已连接", Toast.LENGTH_SHORT).show(); } } @Override public void onLost(Network network) { super.onLost(network); // 网络断开时的处理 Toast.makeText(MainActivity.this, "网络已断开", Toast.LENGTH_SHORT).show(); } }; // 注册回调,指定监听WiFi网络 NetworkRequest request = new NetworkRequest.Builder() .addTransportType(NetworkCapabilities.TRANSPORT_WIFI) .build(); mConnectivityManager.registerNetworkCallback(request, mNetworkCallback); } @Override protected void onDestroy() { super.onDestroy(); // 注销回调 if (mNetworkCallback != null) { mConnectivityManager.unregisterNetworkCallback(mNetworkCallback); } }
四、CONNECTIVITY_CHANGE处理动作的注意事项
- 动态注册后,
onReceive()方法运行在主线程,绝对不能执行耗时操作,否则会引发ANR。建议通过IntentService或者Handler.post()来处理复杂逻辑。 - Android 10(API 29)及以上,
NetworkInfo被标记为过时,推荐用NetworkCapabilities判断网络类型:
// 在BroadcastReceiver的onReceive方法中(API29+) ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); NetworkCapabilities capabilities = cm.getNetworkCapabilities(cm.getActiveNetwork()); if (capabilities != null) { if (capabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)) { // 当前是WiFi网络 } else if (capabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)) { // 当前是移动网络 } }
内容的提问来源于stack exchange,提问作者Hilton
相关产品推荐
相关产品推荐

