Android WiFi开发教程(二)——WiFi的搜索和连接

在上一篇中我们介绍了WiFi热点的创建和关闭,如果你还没阅读过,建议先阅读上一篇文章Android WiFi开发教程(一)——WiFi热点的创建与关闭。 本章节主要继续介绍WiFi的搜索和连接。

WiFi的搜索

  /* 搜索wifi热点*/private void search() {if (!wifiManager.isWifiEnabled()) {//开启wifiwifiManager.setWifiEnabled(true);}wifiManager.startScan();}

我们在开始搜索WiFi之前确保当前WiFi功能是处于开启状态。如果未开启,通过调用WifiManager的setWifiEnabled(boolean enable)去开启。之后调用startScan()就开始扫描附近的WiFi了。而获取扫描的结果我们就需要创建一个广播接收者来处理。

private BroadcastReceiver receiver = new BroadcastReceiver() {@Overridepublic void onReceive(Context context, Intent intent) {final String action = intent.getAction();if (action.equals(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION)) {// wifi已成功扫描到可用wifi。List scanResults = wifiManager.getScanResults();wifiListAdapter.clear();wifiListAdapter.addAll(scanResults);} };

系统在扫描结束后,会发出WifiManager.SCAN_RESULTS_AVAILABLE_ACTION的广播,当我们的接收者接收到这个广播的时候,通过WifiManager的getScanResults()就能获取到扫描结果的集合了。ScanResult保存着每一个WiFi的信息。这里我将这个集合设置到Adapter中,并在列表中展示出来。下面是Apater中主要的代码:

 @Overridepublic View getView(int position, View convertView, ViewGroup parent) {if (convertView == null) {convertView = mInflater.inflate(mResource, parent, false);}TextView name = (TextView) convertView.findViewById(R.id.wifi_name);TextView signl = (TextView) convertView.findViewById(R.id.wifi_signal);ScanResult scanResult = getItem(position);name.setText(scanResult.SSID);int level = scanResult.level;if (level <= 0 && level >= -50) {signl.setText("信号很好");} else if (level < -50 && level >= -70) {signl.setText("信号较好");} else if (level < -70 && level >= -80) {signl.setText("信号一般");} else if (level < -80 && level >= -100) {signl.setText("信号较差");} else {signl.setText("信号很差");}return convertView;}

可以看出列表展示的数据也是比较简单,只有WiFi的名称和信号强度,这两个数据也是平时用得比较多的。获取到扫描结果后,我们就可以处理连接的逻辑了。

WiFi的连接

WiFi的连接相当于搜索就要复杂一些。首先给列表项设置点击事件,获取对应的ScanResult。

   listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {@Overridepublic void onItemClick(AdapterView parent, View view, int position, long id) {wifiManager.disconnect();final ScanResult scanResult = wifiListAdapter.getItem(position);String capabilities = scanResult.capabilities;int type = WIFICIPHER_WPA;if (!TextUtils.isEmpty(capabilities)) {if (capabilities.contains("WPA") || capabilities.contains("wpa")) {type = WIFICIPHER_WPA;} else if (capabilities.contains("WEP") || capabilities.contains("wep")) {type = WIFICIPHER_WEP;} else {type = WIFICIPHER_NOPASS;}}config = isExsits(scanResult.SSID);});

获取到ScanResult后我们通过他的capabilities属性判断WiFi的加密方式。接着通过isExsits(String SSID)方法判断系统是否保存着当前WiFi的信息。

private WifiConfiguration isExsits(String SSID) {List existingConfigs = wifiManager.getConfiguredNetworks();for (WifiConfiguration existingConfig : existingConfigs) {if (existingConfig.SSID.equals("\"" + SSID + "\"")) {return existingConfig;}}return null;}

如果之前连接过,则返回WiFi的配置信息,否则返回空对象。然后接着处理连接的逻辑

if (config == null) {if (type != WIFICIPHER_NOPASS) {//需要密码final EditText editText = new EditText(MainActivity.this);final int finalType = type;new AlertDialog.Builder(MainActivity.this).setTitle("请输入Wifi密码").setIcon(android.R.drawable.ic_dialog_info).setView(editText).setPositiveButton("确定", new DialogInterface.OnClickListener() {@Overridepublic void onClick(DialogInterface dialog, int which) {Log.w("AAA", "editText.getText():" + editText.getText());config = createWifiInfo(scanResult.SSID, editText.getText().toString(), finalType);connect(config);}}).setNegativeButton("取消", null).show();return;} else {config = createWifiInfo(scanResult.SSID, "", type);connect(config);}} else {connect(config);}

当没有获取到所要连接WiFi的配置信息时,我们就需要用到前面获取到的加密方式判断是否需要输入密码。如果加密方式为WAP或WEP时,则弹出提示框提示用户输入WiFi密码。用户输入密码后再调用connect(WifiConfiguration config)方法

如果可以获取到所要连接WiFi的配置信息,则直接调用connect(WifiConfiguration config)。

private void connect(WifiConfiguration config) {int wcgID = wifiManager.addNetwork(config);wifiManager.enableNetwork(wcgID, true);}

直接调用WifiManger的addNetwork方法,将配置信息传进去后,会创建一个新的网络描述的身份并返回回来,如果返回来是-1,则表示创建失败。获取到身份后,调用enableNetwork方法就能开始连接WiFi了。到了这里,我们连接部分就完成了一半,接下来需要继续处理WiFi连接过程中返回来的状态。这里同样我们是需要用到广播接收者来处理。

if (action.equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) {NetworkInfo info = intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO);if (info.getState().equals(NetworkInfo.State.DISCONNECTED)) {text_state.setText("连接已断开");} else if (info.getState().equals(NetworkInfo.State.CONNECTED)) {WifiManager wifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);final WifiInfo wifiInfo = wifiManager.getConnectionInfo();text_state.setText("已连接到网络:" + wifiInfo.getSSID());}} else {NetworkInfo.DetailedState state = info.getDetailedState();if (state == state.CONNECTING) {text_state.setText("连接中...");} else if (state == state.AUTHENTICATING) {text_state.setText("正在验证身份信息...");} else if (state == state.OBTAINING_IPADDR) {text_state.setText("正在获取IP地址...");} else if (state == state.FAILED) {text_state.setText("连接失败");}}}

上面是广播接收者中的关键代码。WiFi在连接的过程中系统会发出WifiManager.NETWORK_STATE_CHANGED_ACTION的广播,当接收者接收到这条广播时,获取NetworkInfo的state来判断当前的连接状态。状态值分别代表如下

NetworkInfo.State.DISCONNECTED //连接已断开
NetworkInfo.State.CONNECTED //已成功连接

除了这两个状态之外,这里还判断了其他状态

NetworkInfo.DetailedState state = info.getDetailedState();if (state == state.CONNECTING) {text_state.setText("连接中...");} else if (state == state.AUTHENTICATING) {text_state.setText("正在验证身份信息...");} else if (state == state.OBTAINING_IPADDR) {text_state.setText("正在获取IP地址...");} else if (state == state.FAILED) {text_state.setText("连接失败");}

DetailedState中包含了很多连接状态的信息,这里只对部分状态进行处理,其他状态值解析具体如下

IDLE:空闲
SCANNING:正在扫描
CONNECTING:连接中
AUTHENTICATING:正在进行身份验证
OBTAINING_IPADDR:正在获取Ip地址
CONNECTED:已连接
SUSPENDED:已暂停
DISCONNECTING:正在断开连接
DISCONNECTED:已断开
FAILED:失败
BLOCKED:已阻止
VERIFYING_POOR_LINK:暂时关闭(网络状况不佳)
CAPTIVE_PORTAL_CHECK:判断是否需要浏览器二次登录

到这里WiFi连接的逻辑就处理完成了,相对于WiFi热点的创建和关闭,搜索和连接确实要复杂一些。欢迎阅读下一篇Android WiFi开发教程(三)——WiFi热点数据传输


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部