之前写过在Android上判断是否有可用的网络(流量或者wifi),这基本上都够用了。但是有一种portal wifi,虽然判定是可用的,且ping也是能ping通的,但是就是上不了网,因为wifi需要输入动态验证码。在火车站、汽车站、商场之类的地方,portal wifi比较常见。

如果app里面需要处理这种情况,那么可以根据网络请求的返回值来判断,基本上statusCode是300+的都是重定向,一般是重定向到portal wifi的获取验证码页面。

private void isWifiSetPortal() {
// 商定的请求链接
final String mWalledGardenUrl = "xxxx";
// 设置请求超时
final int WALLED_GARDEN_SOCKET_TIMEOUT_MS = 10000;

HttpURLConnection urlConnection = null;
try {
    URL url = new URL(mWalledGardenUrl);
    urlConnection = (HttpURLConnection) url.openConnection();
    StringBuffer resultData = new StringBuffer();

    InputStreamReader in = new InputStreamReader(urlConnection.getInputStream());
    // 为输出创建BufferedReader
    BufferedReader buffer = new BufferedReader(in);
    String inputLine = null;
    //使用循环来读取获得的数据
    while (((inputLine = buffer.readLine()) != null))
    {
        //我们在每一行后面加上一个"\n"来换行
        resultData.append(inputLine+"\n");
    }
    Log.d("Portal", "resultData="+resultData.toString());

    // 判断host是否相同,不相同,则跳转到相应url
	    if(url.getHost().equals(urlConnection.getURL().getHost())) {
	        
	        Message message = new Message();
	        message.what = MSG_SHOW_REQUEST_RESULT;
	        Bundle bundle = new Bundle();
	        bundle.putString("result", resultData.toString());
	        message.setData(bundle);
	        mHandler.sendMessage(message);
	
	    }else {
	        
	        Intent intent = new Intent(this, WebViewActivity.class);
	        intent.putExtra("url", urlConnection.getURL().toString());
	        this.startActivity(intent);
	    }

	} catch (Exception e) {
	    Log.d("Portal", "urlconnnection,exception = "+e.toString());
	    e.printStackTrace();
	} finally {
	    if (urlConnection != null) {
	        // 记得释放资源
	        urlConnection.disconnect();
	    }
	}
}

用来呈现重定向后的页面的Activity如下,用户进行登录验证操作之后,就可以返回其他页面进行正常的网络交互了。

// WebViewActivity.class

public class WebViewActivity extends AppCompatActivity {

    Context mContext;

    WebView webView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.webview);

        mContext = this.getApplicationContext();


        String url = getIntent().getStringExtra("url");
        webView = (WebView) findViewById(R.id.webview);
        WebSettings settings = webView.getSettings();
        settings.setJavaScriptEnabled(true);
        webView.setWebViewClient(new WebViewClient() {
            @Override
            public boolean shouldOverrideUrlLoading(WebView view, String url) {
                view.loadUrl(url);
                return super.shouldOverrideUrlLoading(view, url);
            }
        });
        webView.loadUrl(url);
    }
}


这里要说明几点,

1.如果要访问的页面里面有JavaScript,那么webview必须支持javascript。portal wifi的验证页面是有JavaScript的。

WebSettings settings = webView.getSettings();
settings.setJavaScriptEnabled(true);

2.如果页面中有链接,希望点击链接继续在当前browser中响应,而不是新开系统的browser进行响应,则必须覆盖WebView的WebViewClient对象。

webView.setWebViewClient(new WebViewClient() {
            @Override
            public boolean shouldOverrideUrlLoading(WebView view, String url) {
                view.loadUrl(url);
                return super.shouldOverrideUrlLoading(view, url);
            }
        });

关于portal wifi的原理,可以看这篇博客