狐狸的小小窝

我是小狐狸~欢迎来我的小窝!
就是炫

关于 android 5.0-7.1.2 网络图标上的感叹号及其解决办法

叹号杀手源码在此:https://github.com/Noisyfox/NoExclamation

最新版本下载地址:https://github.com/Noisyfox/NoExclamation/releases

7.1.2

谷歌又玩我23333

自7.1.2(开始?),”captive_portal_detection_enabled”设置已被废弃,现在改为了”captive_portal_mode”选项,该选项可设置为以下3种值:

  • 0:彻底禁用检测(Don’t attempt to detect captive portals.)
  • 1:检测到需要登录则弹窗提醒(默认值)(When detecting a captive portal, display a notification that prompts the user to sign in.)
  • 2:检测到需要登录则自动断开此热点并不再自动连接(When detecting a captive portal, immediately disconnect from the network and do not reconnect to that network in the future.)

叹号杀手已经更新以支持该版本。

但愿以后谷歌不要再乱改了233333

感谢 jingyu9575 的帮助 https://github.com/Noisyfox/NoExclamation/issues/2

7.1.1

从7.1.1开始,检测用的服务器地址储存格式发生了变化,改为了:

private static String getCaptivePortalServerHttpsUrl(Context context) {
    return getSetting(context, Settings.Global.CAPTIVE_PORTAL_HTTPS_URL, DEFAULT_HTTPS_URL);
}

以及

public static String getCaptivePortalServerHttpUrl(Context context) {
    return getSetting(context, Settings.Global.CAPTIVE_PORTAL_HTTP_URL, DEFAULT_HTTP_URL);
}

可以看到,系统不会自动加入”generate_204″的后缀了,这意味着url可以设计的更加灵活,同时也意味着在设置的时候需要填入完整的url:

adb shell "settings put global captive_portal_https_url https://www.noisyfox.cn/generate_204"

当然如果只有http的话,可以执行:

adb shell "settings put global captive_portal_use_https 0"
adb shell "settings put global captive_portal_http_url http://www.noisyfox.cn/generate_204"

复原方法见下文。


7.0-7.1.0

需要服务器支持https。

或者使用命令

adb shell "settings put global captive_portal_use_https 0"

禁用https即可。

恢复可用

adb shell "settings put global captive_portal_use_https 1"

或者

adb shell "settings delete global captive_portal_use_https"

5.0-6.0

升级了安卓5.0的同学们一定对网络图标上面的那个感叹号感到十分郁闷。安卓5.0引入了一种新的网络评估机制来评估网络状况,当你有网络请求时会自动选择网络连接条件最好的一个网络进行连接。该机制的代码实现如下:

enter image description here

简要来说就是,如果该网络是VPN,那么直接使用这个网络进行连接,否则调用 isCaptivePortal() 函数进行网络状况的判定,再根据判定结果决定是否选用此网络。 而罪魁祸首就是这个 isCaptivePortal() 函数,它会访问 clients3.google.com/generate_204 并根据返回结果来判断网络联通状况。正是这个google的网址被墙导致安卓没有办法评估网络,这样就导致了那个蛋碎的感叹号一直存在,以及wifi用着用着突然自动连回数据连接了。

本来我想直接把 isCaptivePortal() 函数给屏蔽掉,让他一直返回成功,但是看了下google的代码,发现这个函数是非常有用处的,为什么呢?这个函数有个非常重要的作用,那就是判断当前网络是否需要登录。

想必大家都连接过那些需要验证才能使用的wifi热点吧,当你们连接这些热点的时候,android会自动弹出提示询问你是否需要登录。而这个功能就是依靠了 isCaptivePortal() 这个函数才得以实现,具体原理如下:

enter image description here

安卓先访问 clients3.google.com/generate_204 这个网址,而这个网址如字面所说,会产生一个 http 204 返回值。204返回值的意思就是空内容。如果当前wifi是需要登录才可以连接,那么当试图访问google的服务器的时候,wifi的验证机制一定会自动跳转到一个登录页面,这个时候http请求的返回值就必然不是204了。就是通过这一机制,便可以区分当前wifi是否需要验证,不得不佩服想出这个办法的人来。

然而这就导致了如果简单的屏蔽掉这个函数的功能,那么就没有办法自动提示登录了,但是如果不屏蔽掉那么这个网址被墙掉了,因此会有一个难看的感叹号。想来想去我想到了一个曲线救国的办法,那就是我们把这个网址改成国内的网址不就可以了?我们自己搭一个服务器,来产生这个204返回值给它,问题不就迎刃而解了吗?


那么下面就给出解决方法(无需root):

1.完全屏蔽网络检查功能,最简单快速,但是就没有办法提示wifi登录:

adb shell "settings put global captive_portal_detection_enabled 0"

2.用国内的服务器替换掉google的服务器:

adb shell "settings put global captive_portal_server noisyfox.cn"

这个服务器是我自己建的,也就是本站:http://noisyfox.cn/ 我在服务器上写了个简单的204页面,网址是 http://noisyfox.cn/generate_204 只要用这个网址替换掉google的网址,就可以正常访问并检测网络状态了。不过由于本人的服务器速度并不快,所以感叹号还是会显示一小会儿的,不过应该很快就会消失。

3.恢复默认值

对于第一条指令,恢复默认只需要执行:

adb shell "settings put global captive_portal_detection_enabled 1"

或者

adb shell "settings delete global captive_portal_detection_enabled"

第二条指令的恢复直接delete即可:

adb shell "settings delete global captive_portal_server"

如果你对本站提供的服务速度不满意,可以在文末找到网友提供的其它服务地址。

enter image description here

是不是看着很舒服呢?烦人的感叹号没有了~

经过靠谱的确认,该修改方式具有持久性,重启依旧有效,除非刷机或者清除数据。


如何建立自己的服务器

1. 对于apache服务器,如果你的服务器安装了rewrite模块,那么只需要在网站的.htaccess中加入以下代码:

<IfModule mod_rewrite.c>;
  RewriteEngine On
  RewriteCond %{REQUEST_URI} /generate_204$
  RewriteRule $ / [R=204]
</IfModule>;

2. 对于nginx,直接加入以下设置即可:

location /generate_204 { return 204; }

3. 如果以上方法都无效,那么就要利用代码中的一个小trick来完成,直接在网站的根目录下建立一个叫做“generate_204”的空文件即可,因为安卓的源码中写了如果返回的内容为空那么也会当成204(毕竟一个空的页面怎么想都不可能是登录页面嘛!)。


一键设置工具(需要root)

锵锵锵!由于有些人不太熟悉adb之类的操作,因此就做了一个小工具方便大家直接在手机上设置!

  • 下载地址

最新版请移步:https://github.com/Noisyfox/NoExclamation/releases

NoExclamation Portal Server 修改器 1.2
NoExclamation Portal Server 修改器 2.0

叹号杀手 2.0

  • 支持 Android 7.1.1

1.5

  • 修正了应用崩溃的问题

1.4

  • 增加图标
  • 替换网址为英文网址
  • 优化了重置网址功能
  • 优化界面,在修改网址时不会导致界面卡顿

一些其它服务网址

我会尽我所能提供长期有效的服务,但是由于本站服务器不是很快,而且网络状况有时候会不稳定,因此无法保证100%可靠的服务。不过有一些热心网友提供了其它服务网址,速度和稳定性或许会比本站要好。故在此特别列出供大家选用。如果给提供者带来不便之处请回复告知,我会及时删除。

by fengz: captive.v2ex.co V2EX建立的服务,速度不错,稳定性也很不错,具体信息请查看 https://www.v2ex.com/t/303889

by lkebin: liukebin.avosapps.com 架设于LeanCloud服务器,据lkebin称是永久有效

by Zohar: www.iwch.me 热心网友的个人站点

663 Comment

  1. 有个问题想请教一下
    我现在一般是出门挂shadowsocks,在家/公司是ipv6直连,那时候会关shadowsocks
    我shadowsocks设置是bypass lan & china,pre-app setting里面是bypass mode,即只有我选定的app是直连其他是走proxy,我的portal server设置是小狐狸,然后似乎会出现挂着shadowsocks的时候有时候会连不上小狐狸(或者慢,或者抽,毕竟跨两次太平洋了),导致耗电。
    那么问题来了,这个detection的行为是哪个系统app实现的?如果不是由Google Play那堆服务实现的话,我可以把这个app加到shadowsocks的bypass里面,那用起来就更方便了。谢谢

      1. 我是近期才出现这样的问题,大概是屌丝工最近经常抽吧(4刀一年的东西还想怎样
        你的意思是说这个detection行为是Google Service Framework负责的?那就比较麻烦了……

  2. 小狐狸你好,非常感谢你提供的方法,有一点不明白的地方问一下:
    adb shell “settings put global captive_portal_server xn--yet824cpd.xn--fiqs8s”
    我运行后什么都没提示,是不是就重启手机ok了,但是昨晚到现在,网络待机耗电还是50%+
    请问这个代码到底该如何运行,应该先进入adb shell,然后再运行:settings put global captive_portal_server xn--yet824cpd.xn--fiqs8s 同时去掉双引号吗?这样分开运行?还是输入命令后会返回什么字段,比如提示成功啦等等,如果的确是下面的方法,还是可以在上面写明白点,毕竟有的同学没有root用不了软件,同时对adb命令也不是太懂(比如我啦)。。。

    1. 一般来说没有出现错误提示就是对的了。另外待机耗电问题原因也不止这一个。最保险的还是晚上睡觉的时候关数据或者开飞行模式吧

      1. 移动无线装置运行时间过长导致耗电居多,也是这方面的原因还是其他原因?可是我已经完全屏蔽网络检查功能了呀

  3. 请问是直接运行代码:
    adb shell “settings put global captive_portal_server xn--yet824cpd.xn--fiqs8s”
    我运行后什么都没提示,是不是就重启手机ok了,但是昨晚到现在,网络待机耗电还是50%+
    请问这个代码到底该如何运行,应该先进入adb shell,然后再运行:settings put global captive_portal_server xn--yet824cpd.xn--fiqs8s 不能带双引号吗?这样分开运行?

  4. 请问是不是把GOOGLE服务全部删除就没问题了?
    或者用梭影架梯子??
    如果都不行,你1.完全屏蔽网络检查功能,最简单快速,但是就没有办法提示wifi登录:
    adb shell “settings put global captive_portal_detection_en
    这个代码的唯一后果是没有WIFI通知?但是还是能连WIFI?

    1. 删谷歌服务没有用,因为这是安卓系统自身的设计。影梭用nat模式的话可以消。关掉网络检查并不影响wifi的连接,只是不会有通知罢了。

  5. 那个 不太懂代码什么的 非root的话替换非您建立服务器是不是把adb shell命令中的xn--yet824cpd.xn--fiqs8s部分替换为其他地址就行了呢

  6. 另外比如说我要替换成V2EX建的站,是改为http://www.v2ex.com/generate_204 还是www.v2ex.com就行了呢?

      1. nginx用户自建generate_204的话建议还是增加add_header “Content-Length” 0;
        否则浏览器会等待包体下载,否则知道等待超时。建议还是增加包体长度。让客户端直接断开!

  7. 你好,

    nexus6欧版未root,已升android5.1.1,因为未root,因此,昨天尝试用网上流传的那个未root去感叹号方法。

    通知栏右上角,add user,切换到new user,然后,按屏幕提示操作,到了checking connection时,强制关机,重启手机,把新建的user删除,然后,切换一下网络,如WIFI关了再开。这时发现,感叹号消失了。

    尝试重启手机,感叹号依然不见踪影,尝试开启飞行模式再关闭上,网络重新连接上,感叹号依然不见出现。而且,之前WIFI是提示no internet connection,不自动连接的,去掉感叹号后,可以自动连接上了。

    我估计是这个方法,是中断了google网络检查机制的过程,导致google网络检查这个机制shut down呢?

    但是,虽然感叹号是没有了,信号待机耗电确实下降到了只有4%-5%的水平,不过,整体的耗电仍然没感觉有改进。

    连着WIFI,4G卡,应用只开了QQ,微信,企业邮箱,屏幕保持关闭状态,google的应用都取消了同步的。一个小时大概会消耗10%的电量。

    这个耗电量,实在太惊人了。基本上不怎么点亮屏幕玩,电量就自己哗哗地跑了。

    到底是怎样回事呢?

    1. 并不是很确定。。。因为我都是root之后删掉很多不必要的内置软件,并且开了绿色守护,所以耗电量并不是很大。

      1. nexus6内置的软件都是google的服务产品,虽然有些不常用,但感觉也算是精品软件了。

        何况,暂时不打算解锁Root,或许在升级了android M之后吧。

        这几天会继续观察耗电情况,然后,再来反馈一下。

        感觉去掉感叹号这个未root的方法,相当于就是adb去掉google网络检测机制的作用一样的。

        不知道实际上是否真的是这样呢?

        1. 我认为不是。。虽然我现在还没弄明白这种办法的原理。另外其实越早解锁越好啦。。不然以后东西多了也就懒得解锁了

  8. 刷机小白求教,是不是用了这个之后只是联网后感叹号会消失,不联网还是会有,不联网的状况下使用有类似掉电的影响吗

  9. 大家好,我之前是采用添加新用户,然后在检查网络连接时强制关机来去除感叹号的,但是,经过几天的观察,我发现WIFI连接着的时候,耗电正常,较为省电。但是,当WIFI无连接时,4G网络连接上的时候,移动信号待机和SS就开始变得较为耗电了,通常会排到第一,二位。因此,我昨天一狠心,factory reset了N6,然后,改为采用ADB Shell的方式来去除感叹号。经过一整晚的正常待机,WIFI开着但无连接,4G一直保持连接,后台保持正常连接,什么QQ,微信,邮箱之类的。一晚8小时只耗电10%,WIFI 1%,Cell standby 1%,这样的耗电量就比较正常啦。

    因此,在此以个人的体验告诉大家,添加新用户,然后检查网络时强制关机的方法,最好不要尝试。因为,此方法的原理机制未明,且不能reverse,这是最为头痛的,除了factory reset手机。用ADB Shell的方法,还可以逆向恢复原状。不会影响之后的OTA。

  10. 话说小狐狸大大,你这工具必须要root模式,但是看你的文章介绍不root也是可以去除的,可否更新一下加入不root去除感叹号的支持?

    1. 不是已经列举了用ADB SHELL的方式就可以不用Root手机去掉感叹号了吗?

      如果你是指用那个app不用Root权限,这貌似是不可能的,因为,它是通过读取并修改system setting里的global value来达到去感叹号的。这必须得取得Root权限。

  11. noisyfox你好,我的nexus5线刷了官方5.0镜像后,打开很多自带应用(比如日历)时,提示“与google服务器通信时出现问题”,导致该应用不能正常使用,请问有什么解决方法吗?或者有没有什么办法能在打开应用时不自动访问google服务器呢?

  12. 早就看到这篇文章,虽说手机上也有SS翻蔷但是有时候还是会在已连接wifi的时候自动切换到移动网络,于是就过来找了下,这篇文章居然是谷歌搜索结果第一个。
    ps谢谢小狐狸你的天翼ppp mod ~

  13. 楼主,请问用你提供的 adb shell 命令会影响OTA升级么?

    系统5.0.1,无root,没有刷过recovery,没有修改过系统文件。

  14. 我也在sea上架设了一个,挺简单,只需要新建个文件名,里面啥也不用填,目前挺正常!
    直接建立一个叫做“generate_204”的空文件
    不知道对了没!

  15. 你好,有一个问题,为什么我用这句命令 adb shell “settings put global captive_portal_detection_enabled 0”

    完全关闭网络监测之后还是会有感叹号呀?

发表评论

您的电子邮箱地址不会被公开。 必填项已用*标注

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据