本文没有涉及到连接WIFI之后进行通讯,若有这方面的想法(例如两个客户端连接至同一WIFI后进行通讯),请关注后续文章一起讨论。
其实关于WIFI的开发的文章也非常的多,但是大部分只是简单的例子,不够全面,我这里是想写一个比较完整的WIFI应用,主要功能:
1.能够打开/关闭WIFI
2.能够扫面wifi并获取扫描结果
3.能够连接wifi,无论是什么加密方式
4.能够监听连接状态,如正在连接、正在获取ip、密码错误等
5.能够锁定wifi
6.能获取wifi的加密方式
7.开启热点
8.等等,大部分wifi操作常用的功能...
至于开发中用的几个相关类我就不做过多介绍了,网上比比皆是,还不了解的可以先看一下其他博客的介绍或者官方文档。
我尽量在代码中增加了一些注释,还是那句话:我还是个安卓小白,错误在所难免,如果有错误,希望大家多多指点。
一般使用WIFI流程:
1.打开wifi
1.1 状态监听
2.扫描wifi
3.连接wifi
4.关闭wifi
其中连接需要分几种情况:
1.如果是之前已经保存,直接连接
2.如果没有保存,必须先进行配置,再连接
2.1配置需要区分三种加密方式:无密码、WEP、WPA
3.WPS连接
那么就来打造一个简单demo,按照以上的步骤来。
开发流程
我们为了以后使用方便,直接编写一个wifi管理类,然后在activity直接调用对应方法就行了。下面着手进行这个类的编写:
0.在开始开发之前我们需要先配置相应的权限,如果是Android N以上级的动态申请位置权限哦
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
<!-- 在android N 以上 需要添加位置权限 -->
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
然后先看看我们需要准备什么全局变量
private WifiManager mWifiManager;//wifi管理器
private List<ScanResult> mScanResults;//扫描结果
private Context mContext;
private WifiStateReceiver mReceiver;//广播接收器
private WifiStateChangeListener mWifiStateChangeListener;//
private WifiManager.WifiLock mWifiLock;//WIFI锁
private static WiFiAdmin mWifiAdmin;//单利模式,
1.第一步,初始化wifi管理器并打开wifi
初始化
/***
* 构造方法 - - 由于使用单例,所以设为私有
* @param context
*/
private WiFiAdmin(Context context) {
mContext = context;
//如果使用activity的context则不能访问存储空间,在版本大于Android N时,因此使用全局的Context
mWifiManager = (WifiManager) mContext.getApplicationContext().getSystemService(Context.WIFI_SERVICE);
mWifiLock = mWifiManager.createWifiLock("mlock");
}
打开wifi
public void openWifi() {
if (!mWifiManager.isWifiEnabled()) {
mWifiManager.setWifiEnabled(true);
}
}
2.注册广播,接收wifi的一些状态,例如正在连接、正在获取ip地址、断开连接等
private void registerWifiRecv() {
//注册广播
mReceiver = new WifiStateReceiver();
IntentFilter mFilter = new IntentFilter();
mFilter.addAction(WifiManager.RSSI_CHANGED_ACTION); //信号强度变化
mFilter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION); //网络状态变化
mFilter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION); //wifi状态,是否连上,密码
mFilter.addAction(WifiManager.SUPPLICANT_STATE_CHANGED_ACTION); //是不是正在获得IP地址
mFilter.addAction(WifiManager.NETWORK_IDS_CHANGED_ACTION);
mFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
mContext.registerReceiver(mReceiver, mFilter);
isRegisterRecv = true;
}
3.既然注册了广播,那么我们肯定要处理对应结果
class WifiStateReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
if (!isRegisterRecv) return;//没注册监听就没必要执行之后的逻辑
String action = intent.getAction();
switch (action) {
case WifiManager.RSSI_CHANGED_ACTION:
//信号强度变化
mWifiStateChangeListener.onSignalStrengthChanged(getStrength(context));
break;
case WifiManager.NETWORK_STATE_CHANGED_ACTION:
NetworkInfo info = intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO);
if (info.getDetailedState().equals(NetworkInfo.DetailedState.DISCONNECTED)) {
//wifi已断开
mWifiStateChangeListener.onWifiDisconnect();
} else if (info.getDetailedState().equals(NetworkInfo.DetailedState.CONNECTING)) {
//正在连接...
mWifiStateChangeListener.onWifiConnecting();
} else if (info.getDetailedState().equals(NetworkInfo.DetailedState.CONNECTED)) {
//连接到网络
mWifiStateChangeListener.onWifiConnected();
}else if(info.getDetailedState().equals(NetworkInfo.DetailedState.OBTAINING_IPADDR)){
//正在获取IP地址
mWifiStateChangeListener.onWifiGettingIP();
}else if(info.getDetailedState().equals(NetworkInfo.DetailedState.FAILED)){
//连接失败
}
break;
case WifiManager.WIFI_STATE_CHANGED_ACTION:
int wifiState = intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE, 0);
switch (wifiState) {
case WifiManager.WIFI_STATE_ENABLING:
//wifi正在启用
mWifiStateChangeListener.onWifiEnabling();
break;
case WifiManager.WIFI_STATE_ENABLED:
//Wifi已启用
mWifiStateChangeListener.onWifiEnable();
break;
}
break;
case WifiManager.SUPPLICANT_STATE_CHANGED_ACTION:
int error = intent.getIntExtra(WifiManager.EXTRA_SUPPLICANT_ERROR, -100);
LogUtil.log("密码认证错误:"+error+"\n");
if (error==WifiManager.ERROR_AUTHENTICATING){
//wifi密码认证错误!
mWifiStateChangeListener.onPasswordError();
}
break;
case WifiManager.NETWORK_IDS_CHANGED_ACTION:
//已经配置的网络的ID可能发生变化时
mWifiStateChangeListener.onWifiIDChange();
break;
case ConnectivityManager.CONNECTIVITY_ACTION:
//连接状态发生变化,暂时没用到
int type = intent.getIntExtra(ConnectivityManager.EXTRA_NETWORK_TYPE,0);
break;
default:
break;
}
}
}
/**
* 计算信号强度
*
* @param context 含有WIFI信息的资源对象
* @return 信号强度
*/
private int getStrength(Context context) {
WifiInfo info = getConnectInfo();
if (info.getBSSID() != null) {
int strength = WifiManager.calculateSignalLevel(info.getRssi(), 5);
// 链接速度
// int speed = info.getLinkSpeed();
// // 链接速度单位
// String units = WifiInfo.LINK_SPEED_UNITS;
// // Wifi源名称
// String ssid = info.getSSID();
return strength;
}
return 0;
}
4.然后发起扫描并获取扫描结果
/**
* 启动扫描,扫描前应使用 {@link #getWifiState()}判断WIFI是否可用
* 或者在回调函数 mWifiStateChangeListener.onWifiEnable() 调用
*/
public void startWifiScan() {
mWifiManager.startScan();
mScanResults = mWifiManager.getScanResults();
}
5.获取到扫描结果之后,我们就可以发起连接了。对于之前已经连接过的wifi,可以直接这样:
public boolean connectWifi(int netId) {
return mWifiManager.enableNetwork(netId, true);
}
那么netid怎么来的?这就需要以下这些操作,首先要获取已经配置过(就是之前连接过的)的wifi
public WifiInfo getConnectInfo() {
return mWifiManager.getConnectionInfo();
}
使用以下方法获取netid,如果返回-1,证明没有配置,需要配置才能发起连接请求。
public int isWifiConfig(String ssid) {
List<WifiConfiguration> lists = getConfigWifiList();
for (WifiConfiguration c : lists) {
if (c.SSID.equals("\"" + ssid + "\"")) {
return c.networkId;
}
}
return -1;
}
而如果是连接新的wifi(上面的方法返回-1)需要先配置对应的参数,例如密码之类的才能发起连接
public int configWifi(String ssid, String pwd,int security) {
int result = -1;
for (ScanResult s : mScanResults) {
if (s.SSID.equals(ssid)) {
WifiConfiguration config = new WifiConfiguration();
config.SSID = "\"" + ssid + "\"";
config.hiddenSSID = false;
config.status = WifiConfiguration.Status.ENABLED;
switch (security){
case SECURITY_NONE:
config.wepKeys[0] ="\""+pwd+"\"";
config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
config.wepTxKeyIndex = 0;
break;
case SECURITY_WEP:
config.wepKeys[0]= "\""+pwd+"\"";
config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
config.wepTxKeyIndex = 0;
break;
case SECURITY_WPA:
case SECURITY_WPA_PSK:
config.preSharedKey = "\"" + pwd + "\"";
break;
default:
break;
}
result = mWifiManager.addNetwork(config);
break;
}
}
return result;
}
配置完成再次调用获取netid的方法就可以获取netid了
6.经过步骤5,我们已经能连接上wifi,接下来就可以退出程序,愉快的上网了。当然,如果不需要wifi了,别忘了关闭哦~
public void closeWifi() {
if (mWifiManager.isWifiEnabled()) {
mWifiManager.setWifiEnabled(false);
}
}
上面是简化后的步骤,像在配置时,还需要判断有没有加密,加密方式是什么,怎么获取加密方式等都省略了。全部了解请看下方全部代码哦~
下面有关于wifi的更多操作,也有要共享wifi的法等。
总体就是这种流程,按照这个流程来调用对应的方法就差不多了。记得根据步骤来阅读,才不会觉得混乱。下面是wifi管理类的全部代码,我整合大部分需要用到的功能:
package cn.small_qi.wificonn;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.net.wifi.ScanResult;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
/**
* Created by small_qi on 2017/7/21.
*/
public class WiFiAdmin {
private WifiManager mWifiManager;
private List<ScanResult> mScanResults;
private Context mContext;
private WifiStateReceiver mReceiver;
private WifiStateChangeListener mWifiStateChangeListener;
private WifiManager.WifiLock mWifiLock;
private static WiFiAdmin mWifiAdmin;
private boolean isRegisterRecv;
private boolean isWifiLock;
public static final int SECURITY_WEP = 3;//WEP
public static final int SECURITY_WPA = 2;//WPA/WPA2
public static final int SECURITY_WPA_PSK = 1;//WPA-PSK/WPA2-PSK
public static final int SECURITY_NONE = 0;//没有密码
public static final int ORDER_SMART_SORT = 0;//智能排序,
public static final int ORDER_SIGNAL_LEVEL_SORT = 1;//信号强度排序
/***
* 构造方法 - - 由于使用单例,所以设为私有
* @param context
*/
private WiFiAdmin(Context context) {
mContext = context;
//如果使用activity的context则不能访问存储空间,在版本大于Android N时,因此使用全局的Context
mWifiManager = (WifiManager) mContext.getApplicationContext().getSystemService(Context.WIFI_SERVICE);
mWifiLock = mWifiManager.createWifiLock("mlock");
}
/**
* 对外面公开的获取实例的方法
*
* @param context
* @return 新建的
*/
public static WiFiAdmin getInstance(Context context) {
if (mWifiAdmin == null) {
mWifiAdmin = new WiFiAdmin(context);
}
return mWifiAdmin;
}
/**
* 设置网络状态监听
* 如果设置了监听,一定要在调用的Activity/Fragment
* 的生命周期结束时调用{@link #removeWifiStateChangeListener()}
* 避免内存泄漏
*/
public void addWifiStateChangeListener(WifiStateChangeListener wscListener) {
if (isRegisterRecv) return;
registerWifiRecv();
this.mWifiStateChangeListener = wscListener;
}
private void registerWifiRecv() {
//注册广播
mReceiver = new WifiStateReceiver();
IntentFilter mFilter = new IntentFilter();
mFilter.addAction(WifiManager.RSSI_CHANGED_ACTION); //信号强度变化
mFilter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION); //网络状态变化
mFilter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION); //wifi状态,是否连上,密码
mFilter.addAction(WifiManager.SUPPLICANT_STATE_CHANGED_ACTION); //是不是正在获得IP地址
mFilter.addAction(WifiManager.NETWORK_IDS_CHANGED_ACTION);
mFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
mContext.registerReceiver(mReceiver, mFilter);
isRegisterRecv = true;
}
public void removeWifiStateChangeListener() {
if (!isRegisterRecv) return;
isRegisterRecv = false;
mContext.unregisterReceiver(mReceiver);
}
public void openWifi() {
if (!mWifiManager.isWifiEnabled()) {
mWifiManager.setWifiEnabled(true);
}
}
public void closeWifi() {
if (mWifiManager.isWifiEnabled()) {
mWifiManager.setWifiEnabled(false);
}
}
public boolean lockWifi() {
if (mWifiLock == null) {
return false;
}
mWifiLock.acquire();
isWifiLock = true;
return true;
}
public boolean unLockWifi() {
if (mWifiLock == null) {
return false;
}
mWifiLock.release();
isWifiLock = false;
return true;
}
public boolean isWifiLock() {
return isWifiLock;
}
/**
* 获取网卡状态
*
* @return
*/
public int getWifiState() {
/**
* WIFI网卡的状态是由一系列的整形常量来表示的。
1.WIFI_STATE_DISABLED : WIFI网卡不可用(1)
2.WIFI_STATE_DISABLING : WIFI网卡正在关闭(0)
3.WIFI_STATE_ENABLED : WIFI网卡可用(3)
4.WIFI_STATE_ENABLING : WIFI网正在打开(2) (WIFI启动需要一段时间)
5.WIFI_STATE_UNKNOWN : 未知网卡状态
*/
if (mWifiManager.isWifiEnabled()) {
return mWifiManager.getWifiState();
}
return -1;
}
/**
* 启动扫描,扫描前应使用 {@link #getWifiState()}判断WIFI是否可用
* 或者在回调函数 mWifiStateChangeListener.onWifiEnable() 调用
*/
public void startWifiScan() {
mWifiManager.startScan();
mScanResults = mWifiManager.getScanResults();
}
/**
* 获取排序后的扫描结果
*
* @param order 排序方式
* 1.只按信号强度排序
* 2.已经保存的在前面,其他按强度排序
*/
public List<ScanResult> getOrderScanResults(int order) {
List<ScanResult> sortResult = mScanResults;
if (order == ORDER_SIGNAL_LEVEL_SORT) {
levelSort(sortResult);
} else if (order == ORDER_SMART_SORT) {
smartSort(sortResult);
}
return null;
}
private void levelSort(List<ScanResult> sortResult) {
Collections.sort(sortResult, new Comparator<ScanResult>() {
@Override
public int compare(ScanResult o1, ScanResult o2) {
return o1.level - o2.level;
}
});
}
private void smartSort(List<ScanResult> sortResult) {
Collections.sort(sortResult, new Comparator<ScanResult>() {
@Override
public int compare(ScanResult o1, ScanResult o2) {
if (isWifiConfig(o1.SSID) > 0 && isWifiConfig(o2.SSID) > 0) {
return o1.level - o2.level;
} else if (isWifiConfig(o1.SSID) > 0 || isWifiConfig(o2.SSID) > 0) {
return isWifiConfig(o1.SSID) - isWifiConfig(o2.SSID);
} else {
return o1.level - o2.level;
}
}
});
}
/**
* 获取扫描结果
*/
public List<ScanResult> getScanResults() {
return mScanResults;
}
/**
* 获取已经保存的wifi列表
*/
public List<WifiConfiguration> getConfigWifiList() {
List<WifiConfiguration> configurations = mWifiManager.getConfiguredNetworks();
return configurations;
}
/**
* 判断该wifi是否已经保存
*
* @return 返回-1表示没保存,已经保存返回网络id
*/
public int isWifiConfig(String ssid) {
List<WifiConfiguration> lists = getConfigWifiList();
for (WifiConfiguration c : lists) {
if (c.SSID.equals("\"" + ssid + "\"")) {
return c.networkId;
}
}
return -1;
}
/**
* 配置没有保存的wifi
* 一般只要配置一下几个属性就可以了,其他使用其,默认值
* @param scanResult
* @param pwd
* @return 保存成功则返回该Wifi的网络id,否则-1
*/
public int configWifi(ScanResult scanResult, String pwd,int security) {
return configWifi(scanResult.SSID,pwd,security);
}
/**
* 配置方法重载
*/
public int configWifi(String ssid, String pwd,int security) {
int result = -1;
for (ScanResult s : mScanResults) {
if (s.SSID.equals(ssid)) {
WifiConfiguration config = new WifiConfiguration();
config.SSID = "\"" + ssid + "\"";
config.hiddenSSID = false;
config.status = WifiConfiguration.Status.ENABLED;
switch (security){
case SECURITY_NONE:
config.wepKeys[0] ="\""+pwd+"\"";
config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
config.wepTxKeyIndex = 0;
break;
case SECURITY_WEP:
config.wepKeys[0]= "\""+pwd+"\"";
config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
config.wepTxKeyIndex = 0;
break;
case SECURITY_WPA:
case SECURITY_WPA_PSK:
config.preSharedKey = "\"" + pwd + "\"";
break;
default:
break;
}
result = mWifiManager.addNetwork(config);
break;
}
}
return result;
}
/**
* 配置方法重载,用于更复杂的配置
*/
public int configWifi(WifiConfiguration config) {
return mWifiManager.addNetwork(config);
}
/**
* 获取加秘方式
*/
public int getSecurity(ScanResult scanResult) {
return getSecurity(scanResult.capabilities);
}
/**
* 获取加秘方式
*
* @param capabilities
* @return 加密类型, 具体类型请查看: {@link #SECURITY_NONE}{@link #SECURITY_WEP}{@link #SECURITY_WPA}{@link #SECURITY_WPA_PSK}
*/
public int getSecurity(String capabilities) {
if (capabilities.contains("WEP")) {
return SECURITY_WEP;
} else if (capabilities.contains("WPA")) {
if (capabilities.contains("PSK"))
return SECURITY_WPA_PSK;
return SECURITY_WPA;
} else {
return SECURITY_NONE;
}
}
/**
* 删除/忘记一个wifi(也就是通常的不保存)
*
* @param ssid 要忘记网络名成
* @return 执行结果
*/
public boolean forgetWifi(String ssid) {
for (WifiConfiguration c : getConfigWifiList()) {
if (c.SSID.equals("\"" + ssid + "\"")) {
return mWifiManager.removeNetwork(c.networkId);
}
}
return false;
}
/**
* 断开连接
* @return
*/
public boolean disconnectWifi(){
return mWifiManager.disableNetwork(getConnectInfo().getNetworkId());
// mWifiManager.disconnect();//断流
}
/**
* 连接wifi
*
* @param netId wifi网络id
* @return 连接结果
*/
public boolean connectWifi(int netId) {
return mWifiManager.enableNetwork(netId, true);
}
/**
* 获取已经连接的WIFI信息
*/
public WifiInfo getConnectInfo() {
return mWifiManager.getConnectionInfo();
}
/**
* IP 地址转换
*
* @param ip 转换前的IP
* @return 转换后的IP
*/
public static String parseIPAddressToString(int ip) {
return ((ip & 0xff) + "." + (ip >> 8 & 0xff) + "." + (ip >> 16 & 0xff) + "." + (ip >> 24 & 0xff));
}
/**
* 广播监听内部类
*/
class WifiStateReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
if (!isRegisterRecv) return;//没注册监听就没必要执行之后的逻辑
String action = intent.getAction();
switch (action) {
case WifiManager.RSSI_CHANGED_ACTION:
//信号强度变化
mWifiStateChangeListener.onSignalStrengthChanged(getStrength(context));
break;
case WifiManager.NETWORK_STATE_CHANGED_ACTION:
NetworkInfo info = intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO);
if (info.getState().equals(NetworkInfo.State.DISCONNECTED)) {
//wifi已断开
mWifiStateChangeListener.onWifiDisconnect();
} else if (info.getState().equals(NetworkInfo.State.CONNECTING)) {
//正在连接...
mWifiStateChangeListener.onWifiConnecting();
} else if (info.getState().equals(NetworkInfo.State.CONNECTED)) {
//连接到网络
mWifiStateChangeListener.onWifiConnected();
}else if(info.getDetailedState().equals(NetworkInfo.DetailedState.OBTAINING_IPADDR)){
//正在获取IP地址
mWifiStateChangeListener.onWifiGettingIP();
}
break;
case WifiManager.WIFI_STATE_CHANGED_ACTION:
int wifiState = intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE, 0);
switch (wifiState) {
case WifiManager.WIFI_STATE_ENABLING:
//wifi正在启用
mWifiStateChangeListener.onWifiEnabling();
break;
case WifiManager.WIFI_STATE_ENABLED:
//Wifi已启用
mWifiStateChangeListener.onWifiEnable();
break;
}
break;
case WifiManager.SUPPLICANT_STATE_CHANGED_ACTION:
int error = intent.getIntExtra(WifiManager.EXTRA_SUPPLICANT_ERROR, 0);
switch (error) {
case WifiManager.ERROR_AUTHENTICATING:
//wifi密码认证错误!
mWifiStateChangeListener.onPasswordError();
break;
default:
break;
}
break;
case WifiManager.NETWORK_IDS_CHANGED_ACTION:
//已经配置的网络的ID可能发生变化时
mWifiStateChangeListener.onWifiIDChange();
break;
case ConnectivityManager.CONNECTIVITY_ACTION:
//连接状态发生变化,暂时没用到
break;
default:
break;
}
}
}
/**
* 计算信号强度
*
* @param context 含有WIFI信息的资源对象
* @return 信号强度
*/
private int getStrength(Context context) {
WifiInfo info = getConnectInfo();
if (info.getBSSID() != null) {
int strength = WifiManager.calculateSignalLevel(info.getRssi(), 5);
// 链接速度
// int speed = info.getLinkSpeed();
// // 链接速度单位
// String units = WifiInfo.LINK_SPEED_UNITS;
// // Wifi源名称
// String ssid = info.getSSID();
return strength;
}
return 0;
}
/**
* WIFI状态变化回调接口
*/
public interface WifiStateChangeListener {
//void onRssiChanged();
//void onNetWorkStateChanged();
//void onWifiStateChanged();
//void onSupplicantStateChanged();
// void NetWorkIDSChange();
void onSignalStrengthChanged(int level);
void onWifiConnecting();
void onWifiGettingIP();
void onWifiConnected();
void onWifiDisconnect();
void onWifiEnabling();
void onWifiEnable();
void onPasswordError();
void onWifiIDChange();
//void onWifiLock(int isLock);
}
//-------------------------------以下部分为开启热点-------------------------------------
/**
* 创建热点
*
* @param mSSID 热点名称
* @param mPasswd 热点密码
* @param isOpen 是否是开放热点
*/
public void startWifiAp(String mSSID, String mPasswd, boolean isOpen) {
Method method1 = null;
try {
method1 = mWifiManager.getClass().getMethod("setWifiApEnabled",
WifiConfiguration.class, boolean.class);
WifiConfiguration netConfig = new WifiConfiguration();
netConfig.SSID = mSSID;
netConfig.preSharedKey = mPasswd;
netConfig.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.OPEN);
netConfig.allowedProtocols.set(WifiConfiguration.Protocol.RSN);
netConfig.allowedProtocols.set(WifiConfiguration.Protocol.WPA);
if (isOpen) {
netConfig.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
} else {
netConfig.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK);
}
netConfig.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP);
netConfig.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.TKIP);
netConfig.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP);
netConfig.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.TKIP);
method1.invoke(mWifiManager, netConfig, true);
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
/**
* 获取热点名
**/
public String getApSSID() {
try {
Method localMethod = this.mWifiManager.getClass().getDeclaredMethod("getWifiApConfiguration", new Class[0]);
if (localMethod == null) return null;
Object localObject1 = localMethod.invoke(this.mWifiManager, new Object[0]);
if (localObject1 == null) return null;
WifiConfiguration localWifiConfiguration = (WifiConfiguration) localObject1;
if (localWifiConfiguration.SSID != null) return localWifiConfiguration.SSID;
Field localField1 = WifiConfiguration.class.getDeclaredField("mWifiApProfile");
if (localField1 == null) return null;
localField1.setAccessible(true);
Object localObject2 = localField1.get(localWifiConfiguration);
localField1.setAccessible(false);
if (localObject2 == null) return null;
Field localField2 = localObject2.getClass().getDeclaredField("SSID");
localField2.setAccessible(true);
Object localObject3 = localField2.get(localObject2);
if (localObject3 == null) return null;
localField2.setAccessible(false);
String str = (String) localObject3;
return str;
} catch (Exception localException) {
}
return null;
}
/**
* 检查是否开启Wifi热点
*
* @return
*/
public boolean isWifiApEnabled() {
try {
Method method = mWifiManager.getClass().getMethod("isWifiApEnabled");
method.setAccessible(true);
return (boolean) method.invoke(mWifiManager);
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
return false;
}
/**
* 关闭热点
*/
public void closeWifiAp() {
WifiManager wifiManager = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
if (isWifiApEnabled()) {
try {
Method method = wifiManager.getClass().getMethod("getWifiApConfiguration");
method.setAccessible(true);
WifiConfiguration config = (WifiConfiguration) method.invoke(wifiManager);
Method method2 = wifiManager.getClass().getMethod("setWifiApEnabled", WifiConfiguration.class, boolean.class);
method2.invoke(wifiManager, config, false);
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
/**
* 开热点手机获得其他连接手机IP的方法
*
* @return 其他手机IP 数组列表
*/
public ArrayList<String> getConnectedIP() {
ArrayList<String> connectedIp = new ArrayList<String>();
try {
BufferedReader br = new BufferedReader(new FileReader(
"/proc/net/arp"));
String line;
while ((line = br.readLine()) != null) {
String[] splitted = line.split(" +");
if (splitted != null && splitted.length >= 4) {
String ip = splitted[0];
if (!ip.equalsIgnoreCase("ip")) {
connectedIp.add(ip);
}
}
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return connectedIp;
}
}
里面还少了一种WPS连接,这个如果需要,大家在自己添加上去了。
整个流程下来代码还是挺多的,至于哪些地方需要注意的一时半会也说不完,也忘记了我开发过程遇到哪些问题了~~~间歇性失忆,啊哈哈哈
但是我还是要说一下:
1.可能会有人注意到,为什么我使用ssid时,有时是直接使用,有时又需要加上双引号"\""+ ssid + "\""这样子,
这是因为如果你是从 WifiConfiguration 中获取到的ssid的话,他默认会有双引号,但是从ScanResult等获取到ssid是没有双引号的,
所以为了匹配只好加上了。因此,在配置 WifiConfiguration时ssid和密码都需要我们手动加上双引号,他默认格式是这样,不按照这个来会出现错误。
2.关于AP方面,目前开放的方法能直接开启,所以这部分的内容全是通过反射机制进行的,我也是参考了一些博客写的,具体我自己没试过。
3.其他有疑问的话,就在评论中提问吧~这样方便大神们给你回复。
后面我写了一个测试小程序,除了AP没有测试外,其他功能正常使用,和系统的wifi功能差不多哦~
下面是几张截图:
扫描-获取扫描结果
点击连接(已经保存好的)wifi - -分别会显示正在连接...- - 正在获取ip... - - 已连接
连接没有保存的wifi --弹出输入密码框(如果是没加密不会弹出,而是直接连接),确认之后就连接
如果点击已经连接的wifi,就可以选择断开还是忘记(不保存)
大概就这样了。接下去可能会写连接上wifi之后进行区域网通讯相关的。
完整demo github地址:https://github.com/nongchengqi/WifiConn2
附上activity的代码:
package cn.small_qi.wificonn;
import android.Manifest;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.wifi.ScanResult;
import android.net.wifi.WifiInfo;
import android.os.Build;
import android.support.annotation.NonNull;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private ListView list;
private WifiAdapter adapter;
private WiFiAdmin admin;
private static final int PERMISSION_WIFI_CODE = 1001;
private static final int PERMISSION_FILE_CODE = 1002;
private int curPosition=-1;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
int code = ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE);
if (code != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, PERMISSION_FILE_CODE);
}
}
initList();
setListener();
setStateListener();
}
private void initList() {
admin = WiFiAdmin.getInstance(this);
list = (ListView) findViewById(R.id.list);
adapter = new WifiAdapter(this);
list.setAdapter(adapter);
list.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
curPosition = position;
final ScanResult result = adapter.getItem(position);
if (admin.getConnectInfo().getSSID().equals("\""+result.SSID+"\"")){
new AlertDialog.Builder(MainActivity.this)
.setTitle("是否断开连接?")
.setPositiveButton("断开", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
admin.disconnectWifi();
}
})
.setNegativeButton("不保存", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
admin.forgetWifi(result.SSID);
}
})
.create().show();
return;
}
final int security =admin.getSecurity(result) ;
int netid = admin.isWifiConfig(result.SSID);
if ( netid == -1) {
if (security != WiFiAdmin.SECURITY_NONE) {
final EditText pwdEt = new EditText(MainActivity.this);
//弹出输入密码对话框
new AlertDialog.Builder(MainActivity.this)
.setView(pwdEt)
.setTitle("请输入密码")
.setPositiveButton("确定", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
admin.configWifi(result, pwdEt.getText().toString(),security);
admin.connectWifi(admin.isWifiConfig(result.SSID));
}
})
.setNegativeButton("取消", null)
.create().show();
} else {
admin.configWifi(result, "",security);
admin.connectWifi(admin.isWifiConfig(result.SSID)) ;
}
} else {
admin.connectWifi(netid);
}
}
});
}
private void setListener() {
findViewById(R.id.close).setOnClickListener(this);
findViewById(R.id.open).setOnClickListener(this);
findViewById(R.id.scan).setOnClickListener(this);
findViewById(R.id.info).setOnClickListener(this);
findViewById(R.id.conn).setOnClickListener(this);
}
private void setStateListener() {
admin.addWifiStateChangeListener(new WiFiAdmin.WifiStateChangeListener() {
@Override
public void onSignalStrengthChanged(int level) {
}
@Override
public void onWifiConnecting() {
adapter.updateState(0,curPosition);
}
@Override
public void onWifiGettingIP() {
adapter.updateState(1,curPosition);
}
@Override
public void onWifiConnected() {
adapter.updateState(2,curPosition);
}
@Override
public void onWifiDisconnect() {
adapter.updateState(4,curPosition);
}
@Override
public void onWifiEnabling() {
}
@Override
public void onWifiEnable() {
}
@Override
public void onPasswordError() {
adapter.updateState(3,curPosition);
}
@Override
public void onWifiIDChange() {
}
});
}
private void checkPermission() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
int code = ContextCompat.checkSelfPermission(this, Manifest.permission_group.LOCATION);
if (code != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION}, PERMISSION_WIFI_CODE);
} else {
admin.startWifiScan();
adapter.addAllWifis(admin.getScanResults());
}
} else {
admin.startWifiScan();
adapter.addAllWifis(admin.getScanResults());
}
}
@Override
protected void onDestroy() {
super.onDestroy();
admin.removeWifiStateChangeListener();
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
switch (requestCode) {
case PERMISSION_WIFI_CODE:
if (grantResults[1] == PackageManager.PERMISSION_GRANTED) {
admin.startWifiScan();
adapter.addAllWifis(admin.getScanResults());
}
break;
default:
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
break;
}
}
@Override
public void onClick(View v) {
switch (v.getId()){
case R.id.close:
admin.closeWifi();
break;
case R.id.open:
admin.openWifi();
break;
case R.id.scan:
//6.0权限
checkPermission();
break;
case R.id.info:
showInfo();
break;
case R.id.conn:
if (admin!=null&&admin.getConnectInfo().getIpAddress()!=0){
startActivity(new Intent(MainActivity.this,ConnActivity.class));
}else{
Toast.makeText(this, "请先连接Wifi或者等待Wifi连接成功", Toast.LENGTH_SHORT).show();
}
break;
}
}
private void showInfo() {
WifiInfo info = admin.getConnectInfo();
if (info == null) {
Toast.makeText(MainActivity.this, "当前未连接到WIFI", Toast.LENGTH_SHORT).show();
return;
}
new AlertDialog.Builder(MainActivity.this)
.setTitle("当前连接WIFI信息:")
.setMessage(info.getSSID() + "\n" + info.getMacAddress() + "\n" + WiFiAdmin.parseIPAddressToString(info.getIpAddress()) + "\n" +
info.getLinkSpeed() + "\n" + info.getBSSID() + "\n" + info.getRssi())
.create()
.show();
}
}
xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<HorizontalScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content"
>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal">
<Button
android:id="@+id/open"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="打开" />
<Button
android:id="@+id/close"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="关闭" />
<Button
android:id="@+id/scan"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="扫描" />
<Button
android:id="@+id/info"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="信息" />
<Button
android:id="@+id/conn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="通讯" />
</LinearLayout>
</HorizontalScrollView>
<ListView
android:id="@+id/list"
android:layout_width="match_parent"
android:layout_height="match_parent"></ListView>
</LinearLayout>
--- 转载请注明本文地址---