需求:系统连接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

更多相关文章

  1. 腾讯微博Android客户端开发——自动获取验证码
  2. Android(安卓)通过URL scheme 实现点击浏览器中的URL链接,启动特
  3. Android中使用webservice验证用户登录的示例
  4. Android中使用双层ViewPager2+Fragment+TabLayout 实现顶部Tab和
  5. 【Android】Animation之震动效果动画在登录Activity上的应用
  6. Android(安卓)QQ第三方登录 分享
  7. Android向导页面的实现
  8. Android实现仿QQ登录可编辑下拉菜单
  9. Android(安卓)UI入门(开篇:写作目的)

随机推荐

  1. Android(安卓)中文 API (102)—— CursorAd
  2. Android网络应用接口
  3. 系出名门Android(5) - 控件(View)
  4. Android(安卓)Studio加速
  5. Android(安卓)创建android Splash界面以
  6. Android(安卓)属性动画简介
  7. Android(安卓)View添加 Listener 小技巧
  8. android:theme="@android:style/Theme.Li
  9. Android(安卓)Jni示例
  10. Flutter 与 Android