狐狸的小小窝

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

关于 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. 非常好用!N4 5.0.1系统用adb命令,重启后顺利去掉了感叹号!感谢楼主分享宝贵经验!!!

    ps:我用的是g.cn 谷歌的短网址,非常快。开机几秒感叹号就消失了。

      1. 发现这个方法有一个问题,不知道是不是我个人原因。就是在应用了你修改的站点之后,始终无法登陆Google账户(之前没有等过任何Google账户)但是,恢复默认之后就好了。。

  2. 学习了!
    不过按照文中的说法
    产生感叹号的原因是clients3.google.com/generate_204被墙
    但我的手机24小时使用Shadowsocks翻墙
    理论上这个网址是可以访问的
    为什么还是有叹号呢?

    1. 确实这个貌似和Shadowsocks的相容性不是很好。。。好像用了Shadowsocks的会有不少奇怪的表现唔。。不知道原因

    2. 系统访问这个地址时貌似是强制直接连接的(毕竟访问的目的是打开登录界面,你觉得你连着VPN怎么进入登录界面。。)

  3. 这两天网上集中出现nexus5 “移动网络待机”耗电严重的问题,你的小app确实解决了感叹号的问题可耗电依然很大,主要是“移动网络待机”和“google play服务”我已经关闭了google账户里所有同步项目。似乎仍然无用。能否有解决办法?

    1. 这个只是解决了网络选择的问题,可能会稍微省一丢丢电?但是耗电问题我没有去研究啦

  4. 话说修改这个地址为什么影响shadowsocks?我也在shadowsocks。把认证的地址改成g.cn之后还能继续shadowsocks,只是感觉上速度略慢一些了?
    修改这个地址是修改的android的哪个文件。。?如果要恢复原来的话是:
    su -c “settings put global captive_portal_server clients3.google.com/generate_204″这个吗

    1. 默认是clients3.google.com,不要加后面的部分
      这个是改了android的全局设置。。具体是哪个文件我也不知道
      以及shadowsocks究竟是怎么受到影响我也没研究过因为我没用过的说

      1. 文件位置:/data/data/com.android.providers.settings/databases/settings.db,是sqlite数据库文件,可以用sqlite编辑器打开,表globle里面

        1. 恩恩。。看起来这个改动不需要root权限。

          但是安卓有设置权限。。貌似不允许普通app访问settings命令。。所以必须用root权限才可以

  5. 请问,如果采用方法一修改函数返回值的方式已经修改并解决了问题,要是再想恢复原生的如何恢复,使用方法二中的软件,点“重置为默认”吗?

  6. 楼主,为什么mac输入了这个指令没反应呢?手机上也收到了需要root权限的提示,但是同意之后就一直没反应了。。用app的话,打开是空白的,什么都没有,而且无法正常退出。
    nexus 5,原生5.0.1系统。

    1. app第一次进去会白很久,因为root权限对话框有时候会等很久才能显示。
      至于mac没反应。。。不是很清楚

      1. 非常感谢。问题解决了,是我之前的ROOT有问题,给了ROOT权限,但是实际上没有权限。
        但是貌似还是有感叹号啊。。这个需要重启吗?

  7. APP 其實可以做成系統設定項(在系統設定裡增加選項鏈接),同時在應用抽屜裡隱藏掉圖標
    又或者可以考慮加上一個好看的圖標 🙂

    1. 嘛~主要是这个app功能比较少,而且一般都是用一下就可以删掉了,就没去做这些功能啦

  8. Nexus 5 版本 5.0.1 未root,执行adbde时候有如下提示,未成功消除感叹号。
    D:\Tools\adbgjb\adb>adb shell su -c “settings put global captive_portal_detectio
    n_enabled 0”

    daemon not running. starting it now on port 5037 *
    daemon started successfully *
    error: device offline

    1. 未root 执行adb shell su -c “settings put global captive_portal_detection_enabled 0”
      提示:/system/bin/sh: su: not found

    2. 这是因为你adb连接失败的缘故。你可以升级adb以后再试,或者可以直接用咱的app来设置嘛!

  9. 我的咋不行呢 … 执行shell 提示 没有权限、、、 用这个工具也是不行…手机已经root过了…. 博主能提供一下 具体修改的那个文件吗?我看看修改一下行不行/

发表评论

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

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