Android isNetworkConnected如何判断APP连接到了无网络热点

news/2024/5/5 1:24:43

在开发移动应用时,处理网络状态是一项基础且关键的任务。尤其是辨别出设备是否连接到了一个实际上没有互联网接入的WiFi热点(比如需要登录或者付费才能上网的公共Wi-Fi),对于保持良好用户体验非常重要。

第一步:基本网络连接检测

我们从最基础的开始——检查设备是否连接到了网络。这个方法适用于所有Android设备,可以通过ConnectivityManager服务来实现。下面是如何进行基本检查的代码示例:

    public static boolean isNetworkConnected(Context context) {if (context == null) {return false;}ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);if (Build.VERSION.SDK_INT < 23) {NetworkInfo networkInfo = cm.getActiveNetworkInfo();//return null != networkInfo && networkInfo.isConnected();if (networkInfo != null) {if (networkInfo.getType() == ConnectivityManager.TYPE_WIFI) {//WIFIreturn true;} else if (networkInfo.getType() == ConnectivityManager.TYPE_MOBILE) {//移动数据return true;}}} else {Network network = cm.getActiveNetwork();if (network != null) {NetworkCapabilities nc = cm.getNetworkCapabilities(network);if (nc != null) {if (nc.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)) {//WIFIreturn true;} else if (nc.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)) {//移动数据return true;}}}}return false;}

这段代码帮助我们确认设备至少连接到了某种类型的网络,但它并不能告诉我们这个网络是否真正连通互联网。即使该方法返回true,也并不意味着设备实际上可以访问互联网。比如,在您的场景中,如果手机连接到了一个没有互联网连接的Wi-Fi热点,getActiveNetworkInfo().isConnected()仍然会返回true,因为设备确实成功建立了网络连接,只是这个网络自身没有接入互联网。

因此,如果您需要判断设备是否能够访问互联网(而不仅是连接到了某个网络),那么仅仅依靠isNetworkConnected方法是不够的。
一种简单但有效的方法是尝试发送一个网络请求到一个可靠的外部服务器(例如Google的公共DNS服务器8.8.8.8或者某个稳定的HTTP服务),并检查是否能收到响应:

public boolean isInternetAvailable() {try {InetAddress address = InetAddress.getByName("google.com");return !address.equals("");} catch (UnknownHostException e) {// Log error}return false;
}

这种方法可能会增加应用的网络使用量,并且对于每次检查都会有一定的延迟,所以不应频繁调用。

当遇到“伪联网”热点时的补救方案

要准确地检测设备是否真正能够访问互联网,特别是在网络环境复杂、某些服务可能被限制访问的情况下,我们需要一种更灵活且响应更快的方法。可以采用以下几种策略之一:

1. 使用HTTP HEAD请求检测

相比于下载完整的网页或文件,发送一个HTTP HEAD请求到一个可靠的网站通常更快。HEAD请求只会请求资源的头部信息,并不返回实际的内容,因此响应时间更短。您可以选择一个在目标用户群体中访问速度较快且稳定的网站,例如国内用户可以使用www.baidu.com

public static boolean isInternetAvailable() {try {HttpURLConnection urlc = (HttpURLConnection) (new URL("http://www.baidu.com").openConnection());urlc.setRequestProperty("User-Agent", "Android");urlc.setRequestProperty("Connection", "close");urlc.setConnectTimeout(1500); // 设置超时时间urlc.connect();return (urlc.getResponseCode() == 200);} catch (IOException e) {Log.e("Connectivity", "Error checking internet connection", e);}return false;
}

2. 使用ICMP Ping

尽管这种方法在某些设备上可能需要root权限,或者根本不支持,但它是另一种检测网络连通性的方法。您可以尝试ping一个公共服务器(例如阿里云或腾讯云的公共DNS)。

public static boolean isInternetAvailable() {Runtime runtime = Runtime.getRuntime();try {Process ipProcess = runtime.exec("/system/bin/ping -c 1 223.5.5.5"); // 阿里云公共DNSint exitValue = ipProcess.waitFor();return (exitValue == 0);} catch (IOException | InterruptedException e) {e.printStackTrace();}return false;
}

3. 使用DNS解析

直接使用InetAddress.getByName()进行DNS解析可能比直接ping命令更加高效和通用。您可以选择一个稳定的域名进行解析:

public static boolean isInternetAvailable() {try {InetAddress inetAddress = InetAddress.getByName("www.baidu.com");// 如果地址有效,且不是回送地址,则认为有外网连接return !inetAddress.equals("") && !inetAddress.isLoopbackAddress();} catch (UnknownHostException e) {// DNS解析失败}return false;
}
方法速度稳定性
HTTP HEAD请求通常情况下相当快高。通过选择适合目标用户群的网站提高稳定性(如www.baidu.comwww.cloudflare.com)。
ICMP Ping通常较快,但受多因素影响取决于目标服务器可达性。某些网络配置可能导致ping失败。
DNS解析通常非常快高。稳定性依赖于DNS服务的可靠性。建议选择全球性或大型DNS服务。

总结与建议

在考虑网络检测方法时,速度稳定性是两个重要的考量因素。开发者需要基于应用的具体需求和目标用户所在地的网络环境来选择最适合的方案。

  • 对于需要快速反馈且目标用户遍布全球的应用,使用DNS解析可能是最优的选择,尤其是当选择如Google DNS或Cloudflare DNS这样的全球性服务时。然而,在特定地区(例如中国大陆),为了确保最佳的访问速度和稳定性,选择本地DNS服务可能更加合适。
  • 对于主要面向特定地区用户的应用,例如中国大陆,采用HTTP HEAD请求并选择本地流行且稳定的网站(如www.baidu.com)作为检测目标能够提供更好的用户体验。

在实际应用中,还可以根据具体情况组合使用这些方法,以实现更准确和灵活的网络可达性检测。无论选择哪种方法,请确保这些检测操作在异步执行,避免阻塞主线程,从而维持应用的流畅运行。

注意事项

  • 在实际应用中,应该异步执行这些检查操作,避免阻塞主线程并影响用户体验。
  • 网络状态可以随时变化,所以即使当前判断为可访问互联网,也不能保证未来一直如此。因此,在进行重要的网络交互时,最好还是捕获并处理好相关的异常情况。

3. 使用DNS方式的具体实现

如果你的项目中集成了OkHttp,那么可以利用OkHttp进行异步网络请求来检查网络连接。不过,由于OkHttp主要是用于HTTP请求,并且我们这里讨论的是使用DNS解析来检测网络可达性,我们将稍微变通一下,通过尝试发起一个实际的HTTP请求到一个全球性可靠的域名,以此来间接验证DNS解析及网络连通性。

示例代码

下面是如何使用OkHttp库来异步检查网络连接的示例代码:

import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;import java.io.IOException;public class NetworkCheckUtil {private static final OkHttpClient client = new OkHttpClient();public interface ConnectionCallback {void onResult(boolean isConnected);}public static void checkInternetConnection(final ConnectionCallback callback) {// 使用HEAD请求减少数据传输Request request = new Request.Builder().url("http://www.google.com").head() // 使用HEAD而非GET来减少响应体大小.build();client.newCall(request).enqueue(new Callback() {@Overridepublic void onFailure(Call call, IOException e) {// 请求失败,可能是网络问题e.printStackTrace();callback.onResult(false);}@Overridepublic void onResponse(Call call, Response response) throws IOException {if (response.isSuccessful()) {// HTTP状态码为200-299表示成功响应callback.onResult(true);} else {// 其他情况,如404等,视为无法访问互联网callback.onResult(false);}}});}
}

如何使用

在你的Activity或任何需要检查网络连接的地方,调用checkInternetConnection方法:

NetworkCheckUtil.checkInternetConnection(new NetworkCheckUtil.ConnectionCallback() {@Overridepublic void onResult(boolean isConnected) {if (isConnected) {// 网络连接可用System.out.println("Internet is available");} else {// 网络连接不可用System.out.println("No internet connection");}}
});

注意事项

  • 该方法使用了OkHttp的异步回调机制,避免阻塞主线程。
  • 这里采用http://www.google.com作为测试URL。根据你的用户群体和业务需求,你可能需要选择另一个更适合的URL进行检测。例如,对于在中国大陆的用户,可能需要选择一个在当地访问速度快且稳定的网站。
  • 尽管这种方法通过HTTP请求来检测网络,但实际上也间接利用了DNS解析过程,因为HTTP请求的发起会先触发DNS解析。

用网络连接变化的监听优化判断次数

不再赘述


http://www.mrgr.cn/p/68310374

相关文章

QFD赋能人工智能:打造智能化需求分析与优化新纪元

在科技飞速发展的今天&#xff0c;人工智能(AI)已经渗透到我们生活的方方面面。然而&#xff0c;如何让AI更加贴合用户需求&#xff0c;提供更加精准和个性化的服务&#xff1f;这成为了一个亟待解决的问题。质量功能展开&#xff08;Quality Function Deployment&#xff0c;简…

kubernetes安装ingress-nginx

下载安装文件 首先&#xff0c;需要匹配Ingress-nginx版本和kubernetes版本。 在https://github.com/kubernetes/ingress-nginx可以找到&#xff0c;如下图所示&#xff1a; 这里一定要选择kubernetes对应的ingress-nginx版本 要不会报一些奇怪的错误&#xff01; 博主k8s版本…

oracle连接数据库报错ORA-12541:TNS:无监听程序

最近闲来无事修改了电脑的用户名,本来以为不会影响什么,后来发现oracle数据库连接不上了,报错如下图:查看服务发现确实停止了,启动也启动不起来了搜索Net Manager查看配置, 发现配置里面是我修改前的电脑名,才发现问题所在,随后我又把电脑名称改回来了数据库才能正常连…

Pandas 2.2 中文官方教程和指南(二十二)

原文:pandas.pydata.org/docs/时间增量原文:pandas.pydata.org/docs/user_guide/timedeltas.html时间增量是时间之间的差异,以不同的单位表示,例如天、小时、分钟、秒。它们可以是正数也可以是负数。 Timedelta是datetime.timedelta的子类,并且行为类似,但也允许与np.tim…

钉钉OA审批评论接口,如何@ 人并发送通知

钉钉OA审批评论接口&#xff0c;如何 人并发送通 问题描述&#xff1a; 相关接口&#xff1a;https://oapi.dingtalk.com/topapi/process/instance/comment/add 我希望在钉钉oa审批流程中&#xff0c;添加评论的同时通过“”或者其他方式提醒流程发起人去跟进审批工作。 但我…

Pandas 2.2 中文官方教程和指南(二)

原文:pandas.pydata.org/docs/如何在 pandas 中创建图表?原文:pandas.pydata.org/docs/getting_started/intro_tutorials/04_plotting.htmlIn [1]: import pandas as pdIn [2]: import matplotlib.pyplot as plt 本教程使用的数据:空气质量数据 本教程使用关于(NO_2)的空气…

ROS轻松入门(一)—— 基本概念:node节点、topic通信、service通信

node节点 ROS 中的每个节点都应该负责单一的、模块化的目的&#xff0c;例如控制车轮马达或发布来自激光测距仪的传感器数据。每个节点都可以通过主题、服务、操作或参数从其他节点发送和接收数据。 一个完整的机器人系统由许多协同工作的节点组成。在 ROS 2 中&#xff0c;单…

数据库之数据库恢复技术思维导图+大纲笔记

大纲笔记&#xff1a; 事务的基本概念 事务 定义 用户定义的一个数据库操作系列&#xff0c;这些操作要么全做&#xff0c;要么全不做&#xff0c;是一个不可分割的基本单位 语句 BEGIN TRANSACTION 开始 COMMIT 提交&#xff0c;提交事务的所有操作 ROLLBACK 回滚&#xff0c…

什么是敏捷发布规划

敏捷发布规划基于项目路线图和产品发展愿景,提供了高度概括的发布进度时间轴(通常是 3 到 6个月)。同时,敏捷发布规划还确定了发布的迭代或冲刺次数,使产品负责人和团队能够决定需要开发的内容,并基于业务目标、依赖关系和障碍因素确定达到产品放行所需的时间。 对客户而…

李沐57_长短期记忆网络LSTM——自学笔记

LSTM 1.忘记门&#xff1a;将值朝着0减少 2.输入门&#xff1a;决定不是忽略掉输入数据 3.输出门&#xff1a;决定是不是使用隐状态 !pip install --upgrade d2l0.17.5 #d2l需要更新首先加载时光机器数据集。 import torch from torch import nn from d2l import torch a…

GaussDB SQL查询语句执行过程解析

今天我们就从GaussDB SQL引擎入手,了解一下GaussDB SQL 查询语句的执行过程,包括GaussDB SQL引擎原理和关键技术点。本文分享自华为云社区《【GaussTech第2期】GaussDB SQL查询语句执行过程解析》,作者: GaussDB 数据库。SQL于关系型数据库而言,重要性不言而喻。就像一个乐…

P3667 Bovine Genomics Hash+二分题解

P3667 Bovine Genomics Hash+二分题解砂金听说了你在学字符串,于是在CLOI里出了道题给你P3667 Bovine Genomics 题链:洛谷 hzoi提高 \(hash\)基础题。 思路是二分答案,\(check\)中比较每一个区间字串的\(hash\)值是否相等。 比较的时候可以用\(set\)或\(map\)。 \(set\)的好…

使用SSH从公网服务器简易使用内网任意机器服务,比如从外部下载代码

如果有一个台外部的机器waibu-host, 位于阿里云, 腾讯云, 亚马逊, azure云等等; 假设你想从这个waibu-host上访问公司任意服务,下载代码, 访问http服务,等等, 或者你机器上的服务, 不需要额外工具, 只要ssh 反向就可以实现;借个图, 如下: 举个例子, 如果你想从公司内部通过gi…

泰山派RK3566学习记录

一.烧录环境1.rkdeveloptool SPL烧录命令格式 For with SPL: rkdeveloptool db rkxx_loader_vx.xx.bin rkdeveloptool gpt parameter_gpt.txt rkdeveloptool db rkxx_loader_vx.xx.bin rkdeveloptool wl 0x40 idbloader.img rkdeveloptool wl 0x4000 u-boot.itb rkdeveloptool …

倾斜摄影三维模型数据在立面出图应用分析

三维工厂K3DMaker是一款三维模型浏览、分析、轻量化、顶层合并构建、几何校正、格式转换、调色裁切等功能专业处理软件。可以进行三维模型的网格简化、纹理压缩、层级优化等操作,从而实现三维模型轻量化。轻量化压缩比大,模型轻量化效率高,自动化处理能力高;采用多种算法对…

CIO都应该知道的供应商协同平台是这样的!

供应商协同指的是在供应链管理中,企业与其供应商之间建立的一种紧密的合作关系。这种合作关系超越了传统的买卖关系,通过供应商协同平台,实现信息共享、流程对接和共同规划,提升效率。 供应商协同的主要特点包括: 1、信息共享:供应商和企业之间共享关键信息,如库存水平、…

Linux使用Libevent库实现一个网页服务器---C语言程序

Web服务器 这一个库的实现 其他的知识都是这一个专栏里面的文章 实际使用 编译的时候需要有一个libevent库 gcc httpserv.c -o httpserv -levent实际使用的时候需要指定端口以及共享的目录 ./httpserv 80 .这一个函数会吧这一个文件夹下面的所有文件共享出去 实际的效果, 这…

统一SQL 支持Oracle unpivot列转行

统一SQL介绍 https://www.light-pg.com/docs/LTSQL/current/index.html 源和目标 源数据库&#xff1a;Oracle 目标数据库&#xff1a;TDSQL-MySQL 操作目标 在Oracle中&#xff0c;可以使用unpivot将列转换成行&#xff0c;在TDSQL-MySQL中没有对应的功能&#xff0c;由…

开源贡献代码之​探索一下Cython

探索一下Cython 本篇文章将会围绕最近给Apache提的一个feature为背景&#xff0c;展开讲讲Cython遇到的问题&#xff0c;以及尝试自己从0写一个库出来&#xff0c;代码也已经放星球了&#xff0c;感兴趣的同学可以去下载学习。 0.背景 最近在给apache arrow提的一个feature因为…

【深度学习】DDoS-Detection-Challenge aitrans2024 入侵检测,基于机器学习(深度学习)判断网络入侵

当了次教练&#xff0c;做了个比赛的Stage1&#xff0c;https://github.com/AItransCompetition/DDoS-Detection-Challenge&#xff0c;得了100分。 一些记录&#xff1a; 1、提交的flowid不能重复&#xff0c;提交的是非入侵的数量和数据flowid,看check.cpp可知。 2、Stage…