package cn.sinata.rxnetty.netStatus;
|
|
import android.content.BroadcastReceiver;
|
import android.content.Context;
|
import android.content.Intent;
|
import android.content.IntentFilter;
|
import android.net.ConnectivityManager;
|
import android.net.Network;
|
import android.net.NetworkCapabilities;
|
import android.net.NetworkRequest;
|
import android.os.Build;
|
import android.os.Handler;
|
import android.os.Looper;
|
|
import androidx.annotation.RequiresApi;
|
|
import java.util.ArrayList;
|
import java.util.List;
|
|
/**
|
*网络状态监听
|
*/
|
public class NetStateReceiver extends BroadcastReceiver {
|
|
public final static String CUSTOM_ANDROID_NET_CHANGE_ACTION = "cn.sinata.net.conn.CONNECTIVITY_CHANGE";
|
private final static String ANDROID_NET_CHANGE_ACTION = "android.net.conn.CONNECTIVITY_CHANGE";
|
private static boolean isNetAvailable = false;
|
private static NetUtils.NetType mNetType;
|
private static ArrayList<NetChangeObserver> mNetChangeObservers = new ArrayList<>();
|
private static BroadcastReceiver mBroadcastReceiver;
|
// 保存应用级上下文,避免服务上下文被静态监听器长期持有 由AI生成
|
private static Context mAppContext;
|
// 记录注册次数,防止重复启动服务时重复注册网络监听 由AI生成
|
private static int mRegisterCount = 0;
|
// 网络回调对象用于 Android 5.0 及以上系统监听网络变化 由AI生成
|
private static ConnectivityManager.NetworkCallback mNetworkCallback;
|
// 主线程 Handler 用于把网络回调分发回稳定线程 由AI生成
|
private static final Handler MAIN_HANDLER = new Handler(Looper.getMainLooper());
|
|
private static BroadcastReceiver getReceiver() {
|
if (null == mBroadcastReceiver) {
|
synchronized (NetStateReceiver.class) {
|
if (null == mBroadcastReceiver) {
|
mBroadcastReceiver = new NetStateReceiver();
|
}
|
}
|
}
|
return mBroadcastReceiver;
|
}
|
|
@Override
|
public void onReceive(Context context, Intent intent) {
|
mBroadcastReceiver = NetStateReceiver.this;
|
if (intent.getAction().equalsIgnoreCase(ANDROID_NET_CHANGE_ACTION) || intent.getAction().equalsIgnoreCase(CUSTOM_ANDROID_NET_CHANGE_ACTION)) {
|
// Utils.systemErr("111111111");
|
updateNetworkState(context);
|
notifyObserver();
|
}
|
}
|
|
public static void registerNetworkStateReceiver(Context mContext) {
|
if (mContext == null) {
|
return;
|
}
|
mAppContext = mContext.getApplicationContext();
|
if (mRegisterCount++ > 0) {
|
updateNetworkState(mAppContext);
|
return;
|
}
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
registerNetworkCallback(mAppContext);
|
} else {
|
IntentFilter filter = new IntentFilter();
|
filter.addAction(CUSTOM_ANDROID_NET_CHANGE_ACTION);
|
filter.addAction(ANDROID_NET_CHANGE_ACTION);
|
mAppContext.registerReceiver(getReceiver(), filter);
|
}
|
updateNetworkState(mAppContext);
|
}
|
|
public static void checkNetworkState(Context mContext) {
|
if (mContext == null) {
|
return;
|
}
|
updateNetworkState(mContext);
|
notifyObserver();
|
}
|
|
public static void unRegisterNetworkStateReceiver(Context mContext) {
|
if (mContext == null || mRegisterCount <= 0) {
|
return;
|
}
|
mRegisterCount--;
|
if (mRegisterCount > 0) {
|
return;
|
}
|
Context appContext = mContext.getApplicationContext();
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && mNetworkCallback != null) {
|
try {
|
ConnectivityManager connectivityManager = (ConnectivityManager) appContext.getSystemService(Context.CONNECTIVITY_SERVICE);
|
if (connectivityManager != null) {
|
connectivityManager.unregisterNetworkCallback(mNetworkCallback);
|
}
|
} catch (Exception e) {
|
e.printStackTrace();
|
} finally {
|
mNetworkCallback = null;
|
}
|
return;
|
}
|
if (mBroadcastReceiver != null) {
|
try {
|
appContext.unregisterReceiver(mBroadcastReceiver);
|
} catch (Exception e) {
|
e.printStackTrace();
|
}
|
}
|
|
}
|
|
public static boolean isNetworkAvailable() {
|
return isNetAvailable;
|
}
|
|
public static NetUtils.NetType getNetType() {
|
return mNetType;
|
}
|
|
private static void notifyObserver() {
|
if (!mNetChangeObservers.isEmpty()) {
|
List<NetChangeObserver> observers = new ArrayList<>(mNetChangeObservers);
|
for (NetChangeObserver observer : observers) {
|
if (observer != null) {
|
if (isNetworkAvailable()) {
|
observer.onNetConnected(mNetType);
|
} else {
|
observer.onNetDisConnect();
|
}
|
}
|
}
|
}
|
}
|
|
public static void registerObserver(NetChangeObserver observer) {
|
if (mNetChangeObservers == null) {
|
mNetChangeObservers = new ArrayList<>();
|
}
|
if (observer != null && !mNetChangeObservers.contains(observer)) {
|
mNetChangeObservers.add(observer);
|
}
|
}
|
|
public static void removeRegisterObserver(NetChangeObserver observer) {
|
if (mNetChangeObservers != null) {
|
if (mNetChangeObservers.contains(observer)) {
|
mNetChangeObservers.remove(observer);
|
}
|
}
|
}
|
|
// 注册系统网络回调以替代高版本系统上不可靠的 CONNECTIVITY_CHANGE 广播 由AI生成
|
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
|
private static void registerNetworkCallback(final Context context) {
|
// 获取系统网络服务用于注册 NetworkCallback 由AI生成
|
ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
|
// 网络服务为空时保持原有状态并直接返回 由AI生成
|
if (connectivityManager == null) {
|
return;
|
}
|
// 避免重复创建网络回调对象 由AI生成
|
if (mNetworkCallback != null) {
|
return;
|
}
|
// 创建网络变化回调对象 由AI生成
|
mNetworkCallback = new ConnectivityManager.NetworkCallback() {
|
// 网络可用时刷新当前网络状态 由AI生成
|
@Override
|
public void onAvailable(Network network) {
|
// 切回主线程分发,避免回调线程不一致 由AI生成
|
dispatchNetworkChanged(context);
|
}
|
|
// 网络能力变化时刷新当前网络状态 由AI生成
|
@Override
|
public void onCapabilitiesChanged(Network network, NetworkCapabilities networkCapabilities) {
|
// 切回主线程分发最新联网能力 由AI生成
|
dispatchNetworkChanged(context);
|
}
|
|
// 网络丢失时重新查询当前活动网络,兼容 Wi-Fi 与移动网络切换 由AI生成
|
@Override
|
public void onLost(Network network) {
|
// 切回主线程后再通知观察者 由AI生成
|
dispatchNetworkChanged(context);
|
}
|
};
|
try {
|
// 只监听具备互联网能力的网络,减少无效网络状态回调 由AI生成
|
NetworkRequest request = new NetworkRequest.Builder().addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET).build();
|
// 向系统注册网络变化回调 由AI生成
|
connectivityManager.registerNetworkCallback(request, mNetworkCallback);
|
} catch (Exception e) {
|
// 注册失败时打印异常并回退到旧广播路径 由AI生成
|
e.printStackTrace();
|
// 清空失败的回调对象,避免后续注销不存在的系统回调 由AI生成
|
mNetworkCallback = null;
|
// 使用旧广播监听作为兜底方案 由AI生成
|
registerLegacyReceiver(context);
|
}
|
}
|
|
// 注册旧版网络广播监听作为低版本或异常兜底 由AI生成
|
private static void registerLegacyReceiver(Context context) {
|
// 创建网络广播过滤器 由AI生成
|
IntentFilter filter = new IntentFilter();
|
// 监听应用内部主动检查网络的广播 由AI生成
|
filter.addAction(CUSTOM_ANDROID_NET_CHANGE_ACTION);
|
// 监听系统网络变化广播 由AI生成
|
filter.addAction(ANDROID_NET_CHANGE_ACTION);
|
try {
|
// 使用应用上下文注册广播,避免持有服务实例 由AI生成
|
context.getApplicationContext().registerReceiver(getReceiver(), filter);
|
} catch (Exception e) {
|
// 注册失败时输出异常,避免影响长连接服务启动 由AI生成
|
e.printStackTrace();
|
}
|
}
|
|
// 刷新网络状态并通知所有观察者 由AI生成
|
private static void dispatchNetworkChanged(final Context context) {
|
// 主线程执行状态更新,保证观察者回调线程一致 由AI生成
|
MAIN_HANDLER.post(new Runnable() {
|
// 执行网络状态查询和分发 由AI生成
|
@Override
|
public void run() {
|
// 根据系统当前网络刷新缓存状态 由AI生成
|
updateNetworkState(context);
|
// 把最新状态通知业务观察者 由AI生成
|
notifyObserver();
|
}
|
});
|
}
|
|
// 根据当前系统网络刷新缓存状态 由AI生成
|
private static void updateNetworkState(Context context) {
|
// 上下文为空时标记为无网络 由AI生成
|
if (context == null) {
|
isNetAvailable = false;
|
mNetType = NetUtils.NetType.NONE;
|
return;
|
}
|
// Android 6.0 及以上优先用 NetworkCapabilities 判断真实互联网能力 由AI生成
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
ConnectivityManager connectivityManager = (ConnectivityManager) context.getApplicationContext().getSystemService(Context.CONNECTIVITY_SERVICE);
|
if (connectivityManager == null) {
|
isNetAvailable = false;
|
mNetType = NetUtils.NetType.NONE;
|
return;
|
}
|
Network activeNetwork = connectivityManager.getActiveNetwork();
|
NetworkCapabilities capabilities = connectivityManager.getNetworkCapabilities(activeNetwork);
|
isNetAvailable = capabilities != null
|
&& capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
|
mNetType = isNetAvailable ? NetUtils.getAPNType(context) : NetUtils.NetType.NONE;
|
return;
|
}
|
// 旧系统保持原有 NetworkInfo 判断逻辑 由AI生成
|
if (!NetUtils.isNetworkAvailable(context)) {
|
isNetAvailable = false;
|
mNetType = NetUtils.NetType.NONE;
|
} else {
|
isNetAvailable = true;
|
mNetType = NetUtils.getAPNType(context);
|
}
|
}
|
}
|