【定制Android系统】Android(安卓)7.1 实现连接 Captive Portal WiFi 时自动弹出登录页面
16lz
2021-01-26
需求:系统连接WiFi时,若连接到需要登录的WiFi,则弹出登录页面。
说明:像 MIUI 等系统,现在的表现是弹出一个专门的页面(虽然我也不知道这个页面从哪儿能再次打开,以至于每次想更换账号都很费劲)。但是本文实现的是弹出一个普通的浏览器页面。
解决方案:在 NetworkMonitor.java 的 processMessage 中,当 Android 原生系统判断到需要登录时,发送 intent 打开任意网页,以使之自动重定向到登录页面。
NetworkMonitor.java 中这部分源码为:
508 @Override509 public boolean processMessage(Message message) {510 switch (message.what) {511 case CMD_REEVALUATE:512 if (message.arg1 != mReevaluateToken || mUserDoesNotWant)513 return HANDLED;514 // Don't bother validating networks that don't satisify the default request.515 // This includes:516 // - VPNs which can be considered explicitly desired by the user and the517 // user's desire trumps whether the network validates.518 // - Networks that don't provide internet access. It's unclear how to519 // validate such networks.520 // - Untrusted networks. It's unsafe to prompt the user to sign-in to521 // such networks and the user didn't express interest in connecting to522 // such networks (an app did) so the user may be unhappily surprised when523 // asked to sign-in to a network they didn't want to connect to in the524 // first place. Validation could be done to adjust the network scores525 // however these networks are app-requested and may not be intended for526 // general usage, in which case general validation may not be an accurate527 // measure of the network's quality. Only the app knows how to evaluate528 // the network so don't bother validating here. Furthermore sending HTTP529 // packets over the network may be undesirable, for example an extremely530 // expensive metered network, or unwanted leaking of the User Agent string.531 if (!mDefaultRequest.networkCapabilities.satisfiedByNetworkCapabilities(532 mNetworkAgentInfo.networkCapabilities)) {533 validationLog("Network would not satisfy default request, not validating");534 transitionTo(mValidatedState);535 return HANDLED;536 }537 mAttempts++;538 // Note: This call to isCaptivePortal() could take up to a minute. Resolving the539 // server's IP addresses could hit the DNS timeout, and attempting connections540 // to each of the server's several IP addresses (currently one IPv4 and one541 // IPv6) could each take SOCKET_TIMEOUT_MS. During this time this StateMachine542 // will be unresponsive. isCaptivePortal() could be executed on another Thread543 // if this is found to cause problems.544 CaptivePortalProbeResult probeResult = isCaptivePortal();545 if (probeResult.isSuccessful()) {546 transitionTo(mValidatedState);547 } else if (probeResult.isPortal()) {548 mConnectivityServiceHandler.sendMessage(obtainMessage(EVENT_NETWORK_TESTED,549 NETWORK_TEST_RESULT_INVALID, mNetId, probeResult.redirectUrl));550 mLastPortalProbeResult = probeResult;551 transitionTo(mCaptivePortalState);552 } else {553 final Message msg = obtainMessage(CMD_REEVALUATE, ++mReevaluateToken, 0);554 sendMessageDelayed(msg, mReevaluateDelayMs);555 logNetworkEvent(NetworkEvent.NETWORK_VALIDATION_FAILED);556 mConnectivityServiceHandler.sendMessage(obtainMessage(557 EVENT_NETWORK_TESTED, NETWORK_TEST_RESULT_INVALID, mNetId,558 probeResult.redirectUrl));559 if (mAttempts >= BLAME_FOR_EVALUATION_ATTEMPTS) {560 // Don't continue to blame UID forever.561 TrafficStats.clearThreadStatsUid();562 }563 mReevaluateDelayMs *= 2;564 if (mReevaluateDelayMs > MAX_REEVALUATE_DELAY_MS) {565 mReevaluateDelayMs = MAX_REEVALUATE_DELAY_MS;566 }567 }568 return HANDLED;569 case CMD_FORCE_REEVALUATION:570 // Before IGNORE_REEVALUATE_ATTEMPTS attempts are made,571 // ignore any re-evaluation requests. After, restart the572 // evaluation process via EvaluatingState#enter.573 return (mAttempts < IGNORE_REEVALUATE_ATTEMPTS) ? HANDLED : NOT_HANDLED;574 default:575 return NOT_HANDLED;576 }577 }
原理可见下方链接。大概意思是,当WiFi成功连接后,NetworkMonitor 会用一个 CaptivePortalProbeResult=isCaptivePortal()
来判断当前的网络是否是 需要登录验证的。并且给出了各种结果,第一种(probeResult.isSuccessful()
)是连接了需验证的WiFi,但已成功验证。第二种(probeResult.isPortal()
)正是我们需要的,需要验证的。因此,这段代码可以修改为如下内容:
CaptivePortalProbeResult probeResult = isCaptivePortal(); if (probeResult.isSuccessful()) { transitionTo(mValidatedState); } else if (probeResult.isPortal()) { // Add by Enoch : Pop up window to log in portal wifi Log.d(TAG, "ENOCH:::the wifi is CaptivePortal. start a browser with google.com"); Intent logIntent = new Intent(); logIntent.setAction("android.intent.action.VIEW"); logIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); Uri urlDefault = Uri.parse("http://www.google.com"); logIntent.setData(urlDefault); mContext.startActivityAsUser(logIntent, UserHandle.CURRENT_OR_SELF); // Add by Enoch mConnectivityServiceHandler.sendMessage(obtainMessage(EVENT_NETWORK_TESTED, NETWORK_TEST_RESULT_INVALID, mNetId, probeResult.redirectUrl)); mLastPortalProbeResult = probeResult; transitionTo(mCaptivePortalState); } else {
关于 Android 网络连接评分机制 NetworkMonitor 的介绍,见: https://blog.csdn.net/u010961631/article/details/48971823
如果是通过应用实现此功能,而非在Android系统源码中进行修改,则见:https://blog.csdn.net/u012382509/article/details/53219991
更多相关文章
- 腾讯微博Android客户端开发——自动获取验证码
- Android(安卓)通过URL scheme 实现点击浏览器中的URL链接,启动特
- Android中使用webservice验证用户登录的示例
- Android中使用双层ViewPager2+Fragment+TabLayout 实现顶部Tab和
- 【Android】Animation之震动效果动画在登录Activity上的应用
- Android(安卓)QQ第三方登录 分享
- Android向导页面的实现
- Android实现仿QQ登录可编辑下拉菜单
- Android(安卓)UI入门(开篇:写作目的)