Android中规避StrictMode检查网络连接状态的方法
解决方案
你的问题根源是在主线程执行了耗时的网络请求,Android从API 11开始就禁止主线程处理网络操作,StrictMode只是临时绕过的违规手段,正确的做法是把网络操作移到后台线程,同时保证多类调用的便利性,下面是具体改造方案:
1. 替换过时的网络状态判断API
原代码里的NetworkInfo已被标记为过时,改用ConnectivityManager.NetworkCapabilities来判断网络连通性:
private static boolean isNetworkAvailable(Context context) { ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); if (cm == null) return false; Network network = cm.getActiveNetwork(); if (network == null) return false; NetworkCapabilities capabilities = cm.getNetworkCapabilities(network); return capabilities != null && (capabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) || capabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) || capabilities.hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET)); }
2. 将同步网络请求改为异步执行
网络请求属于耗时操作,不能在主线程同步返回结果,我们通过回调接口返回结果,同时用ExecutorService管理后台线程,封装成可复用的工具类:
第一步:定义回调接口
public interface ConnectionCheckCallback { void onConnectionChecked(boolean isConnected); }
第二步:改造为异步工具类
public class NetworkUtils { // 单例线程池,复用线程避免频繁创建销毁 private static final ExecutorService EXECUTOR = Executors.newSingleThreadExecutor(); public static void checkConnectionAsync(Context context, ConnectionCheckCallback callback) { EXECUTOR.execute(() -> { boolean isConnected = false; try { if (isNetworkAvailable(context)) { String checkUrl = databaseManagement.getSettingValue("urlCheckConnection", context); URL url = new URL(checkUrl); HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection(); httpURLConnection.setConnectTimeout(3000); httpURLConnection.setReadTimeout(3000); // getResponseCode会自动触发连接,无需显式调用connect() isConnected = httpURLConnection.getResponseCode() == HttpURLConnection.HTTP_OK; // 用try-with-resources自动关闭输入流,避免资源泄漏 try (InputStream ignored = httpURLConnection.getInputStream()) { // 仅需关闭资源,无需读取内容 } httpURLConnection.disconnect(); } } catch (Exception e) { isConnected = false; wil.WriteFile("checkConnection - Exception: " + e.getMessage(), context); } finally { // 切回主线程回调结果,避免后台线程操作UI new Handler(Looper.getMainLooper()).post(() -> callback.onConnectionChecked(isConnected)); } }); } // 上面的isNetworkAvailable方法放在这里 private static boolean isNetworkAvailable(Context context) { ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); if (cm == null) return false; Network network = cm.getActiveNetwork(); if (network == null) return false; NetworkCapabilities capabilities = cm.getNetworkCapabilities(network); return capabilities != null && (capabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) || capabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) || capabilities.hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET)); } }
3. 多类调用方式
任何需要检查网络的类,只需调用异步方法并传入回调:
NetworkUtils.checkConnectionAsync(context, new ConnectionCheckCallback() { @Override public void onConnectionChecked(boolean isConnected) { // 在这里处理检查结果,比如更新UI或执行业务逻辑 if (isConnected) { // 网络可用,执行对应操作 } else { // 网络不可用,提示用户或做降级处理 } } });
额外优化点
- 避免重复请求:可在工具类中添加请求锁,同一时间只发起一次网络请求,结果复用给所有调用者
- 权限声明:确保在
AndroidManifest.xml中添加必要权限:<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.INTERNET" />
内容的提问来源于stack exchange,提问作者Mattia
相关产品推荐
相关产品推荐

