Firebase Auth登录前检查网络活跃连接时应用崩溃问题排查
崩溃原因分析与修复方案
看起来你的代码崩溃主要有几个核心问题,咱们一步步拆解解决:
1. 主线程执行同步网络请求(最可能的崩溃原因)
你直接在networkState()方法里调用urlc.connect(),这是同步耗时网络操作。Android严格禁止在主线程执行这类操作,会触发NetworkOnMainThreadException,直接导致应用崩溃,同时还可能引发界面卡顿或ANR(应用无响应)。
修复方式:把网络请求移到后台线程
推荐用ExecutorService(Java)或者协程(Kotlin)来处理后台任务,完成后再回到主线程更新UI。这里给你Java版本的修复示例:
private void networkState() { final ConnectivityManager conMgr = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE); assert conMgr != null; final NetworkInfo activeNetwork = conMgr.getActiveNetworkInfo(); if (activeNetwork != null && activeNetwork.isConnectedOrConnecting()) { Toast.makeText(getApplicationContext(),"Network connected",Toast.LENGTH_SHORT).show(); // 把网络请求放到后台线程执行 ExecutorService executor = Executors.newSingleThreadExecutor(); executor.execute(() -> { try { HttpURLConnection urlc = (HttpURLConnection)(new URL("http://www.google.com").openConnection()); urlc.setRequestProperty("User-Agent", "Test"); urlc.setRequestProperty("Connection", "close"); urlc.setConnectTimeout(5000); // 缩短超时时间,提升体验 urlc.setRequestMethod("HEAD"); // 用HEAD请求替代GET,更省带宽 urlc.connect(); // 回到主线程更新UI runOnUiThread(() -> { if(urlc.getResponseCode() == 200){ Toast.makeText(getApplicationContext(), "Network has active internet", Toast.LENGTH_SHORT).show(); signInUser(); } else { Toast.makeText(getApplicationContext(), "No active internet connection", Toast.LENGTH_SHORT).show(); } }); } catch (IOException e) { e.printStackTrace(); runOnUiThread(() -> { Toast.makeText(getApplicationContext(), "No active internet connection", Toast.LENGTH_SHORT).show(); }); } }); executor.shutdown(); } else { Toast.makeText(getApplicationContext(),"Network not connected",Toast.LENGTH_SHORT).show(); } }
2. 缺少必要的权限
如果你的AndroidManifest.xml里没声明网络相关权限,会因权限不足导致崩溃。请务必添加以下权限:
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.INTERNET" />
注:这两个都是正常权限,Android 6.0及以上无需动态申请,只需在Manifest中声明即可。
3. 废弃API的兼容性问题(非直接崩溃,但建议优化)
getActiveNetworkInfo()在API 29(Android 10)之后已被废弃,如果你需要适配高版本系统,建议改用NetworkCapabilities来检查网络连接状态:
private boolean isNetworkAvailable() { ConnectivityManager conMgr = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE); if (conMgr == null) return false; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { Network network = conMgr.getActiveNetwork(); if (network == null) return false; NetworkCapabilities capabilities = conMgr.getNetworkCapabilities(network); return capabilities != null && (capabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) || capabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) || capabilities.hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET)); } else { // 兼容低版本系统 NetworkInfo activeNetwork = conMgr.getActiveNetworkInfo(); return activeNetwork != null && activeNetwork.isConnectedOrConnecting(); } }
更可靠的活跃网络检查方案
除了请求Google服务器,你可以结合业务场景做以下优化:
- 请求自有后端接口:相比公共服务器,请求你自己的业务后端更贴合实际使用场景,也能同时验证服务可用性。
- 注册网络状态监听:如果需要实时感知网络变化,推荐使用
ConnectivityManager.NetworkCallback,不用每次登录前都主动检查:
private ConnectivityManager.NetworkCallback networkCallback; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // 初始化网络回调 networkCallback = new ConnectivityManager.NetworkCallback() { @Override public void onAvailable(Network network) { // 网络恢复时,主动检查活跃连接 checkActiveInternet(); } @Override public void onLost(Network network) { // 网络断开时提示用户 runOnUiThread(() -> Toast.makeText(getApplicationContext(), "Network disconnected", Toast.LENGTH_SHORT).show()); } }; // 注册网络监听 ConnectivityManager conMgr = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { conMgr.registerDefaultNetworkCallback(networkCallback); } else { NetworkRequest request = new NetworkRequest.Builder().build(); conMgr.registerNetworkCallback(request, networkCallback); } } // 检查活跃网络的方法 private void checkActiveInternet() { ExecutorService executor = Executors.newSingleThreadExecutor(); executor.execute(() -> { try { // 替换成你的后端接口地址 HttpURLConnection urlc = (HttpURLConnection)(new URL("http://your-backend-api.com").openConnection()); urlc.setRequestMethod("HEAD"); urlc.setConnectTimeout(3000); urlc.connect(); runOnUiThread(() -> { if(urlc.getResponseCode() == 200){ signInUser(); } else { Toast.makeText(getApplicationContext(), "No active internet", Toast.LENGTH_SHORT).show(); } }); } catch (IOException e) { e.printStackTrace(); runOnUiThread(() -> Toast.makeText(getApplicationContext(), "No active internet", Toast.LENGTH_SHORT).show()); } }); executor.shutdown(); } @Override protected void onDestroy() { super.onDestroy(); // 注销网络监听,避免内存泄漏 ConnectivityManager conMgr = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE); conMgr.unregisterNetworkCallback(networkCallback); }
内容的提问来源于stack exchange,提问作者Dipin K G
相关产品推荐
相关产品推荐

