【澳门葡京备用网址】赢得总结机的网络连接状态,获取系统的互连网状态与有线网的信号强度

一台微型总结机,有时通过无线网连接网络(调制解调器/局域网),如有网卡也可一连wifi。
那么如何取得WLAN是不是连接,和相应的信号强度呢?

 判断连网的点子介绍

将win7电脑变身WiFi热点,让手机、笔记本共享上网(虚拟有线路由)

 1.wifi的七种状态:

就以下俩点:

 1. InternetGetConnectedState

  • 此函数获取网络状态有延时,且对网卡加害较大
  • MSDN官方本身推荐不提出利用,不管是连网状态下如故断网情状下,获取的网络状态都有不标准的案例,如下:

  (BUG) InternetGetConnectedState API returns false
result

  Detecting LAN connection using InternetGetConnectedState API
doesn’t
work

  

  

在看下文以前,能够浏览MSDN:通过InternetGetConnectedState方法对互连网状态的取得.aspx)

如上InternetGetConnectedState方法介绍中

  • dwReversed必须安装为0
  • 由此输出值lpdwFlags能够拿走当前网络连接的音讯,通过拼装比较能够取妥善前一连的互连网项目,如拨号上网/局域网等

    bool InternetGetConnectedState( out LPDWORD lpdwFlags, int dwReversed);

澳门葡京备用网址 1

首先,添加非托管函数并调用,能够获取互连网是或不是联网

//声明外部的函数
[DllImport("winInet.dll ")]
private static extern bool InternetGetConnectedState(ref int flag,int dwReserved);

 

WIFI_STATE_DISABLED   WIFI网卡不可用

  • 获取计算机连网状态
  • 取得有线网络的信号强度

 2. IsNetworkAlive

内需劳务System 伊夫nt
Notification的支撑(系统私下认可自动运营该服务),且要求设置新型的SDK(如.NET)

浏览:MSDN对IsNetworkAlive的详细描述

由API中翻译:该意义可在Windows XP、3000(或Windows NT 4.0与Internet
Explorer 5或更高版本)上采取,在windows95或更高版本上运用Internet
Explorer 5或更高版本。所以,一般的系统都是永葆的

长机设置如下:

WIFI_STATE_DISABLING WIFI网卡正在关闭

 获取总括机连网状态

通过IsNetworkAlive可获取当前条件是还是不是曾经三番五次网络。详见《C#
获取计算机的互联网连接状态》

流程:网络是或不是连接->是不是有有线网连接->获取有线网状态(信号强度)->重返网络状态

 1 [DllImport("sensapi.dll", SetLastError = true)]
 2 private static extern bool IsNetworkAlive(out int connectionDescription);
 3 public NetworkStatus GetNetworkStatusByNetworkAlive()
 4 {
 5     var networkStatus = NetworkStatus.InternetWithError;
 6 
 7     int flags = 0;
 8     var isNetworkAlive = IsNetworkAlive(out flags);
 9 
10     int errCode = Marshal.GetLastWin32Error();
11     if (errCode != 0)
12     {
13         throw new InvalidOperationException($"通过{nameof(IsNetworkAlive)}非托管DLL,获取网络状态时,遇到异常");
14     }
15     if (isNetworkAlive)
16     {
17         // 获取WLAN网络状态
18         var wlanStatus = GetWlanStatus();
19         if (isNetworkAlive && wlanStatus == NetworkStatus.WifiWithErro)
20         {
21             networkStatus = NetworkStatus.Internet;
22         }
23         else
24         {
25             networkStatus = wlanStatus;
26         }
27     }
28     return networkStatus;
29 }

 

输出值lpdwFlags

具体项目标详实内容可链接澳门葡京备用网址,QOCINFO
structure.aspx)

  • NETWORK_【澳门葡京备用网址】赢得总结机的网络连接状态,获取系统的互连网状态与有线网的信号强度。ALIVE_LAN=1 局域网(此处并非指有线网)
  • NETWORK_ALIVE_WAN=2
    远程访问-拨号访问和vpn访问(此处并非只无线网,按DPI所示,指的是RAS
    connections)
  • NETWORK_ALIVE_AOL=4
    无效的值。。。因为唯有Win9x系统才有此第伍个挑选。参照链接

有线网络的判定:lpdwFlags对是或不是有线互连网,并不曾平昔的论断。

eg:比如作者的电脑环境(有线互连网只怕wifi互联网),获取的flag=1(局域网)

澳门葡京备用网址 2

 

一 、以管理人身份运营命令提醒符:

WIFI_STATE_ENABLED     WIFI网卡可用

网络状态枚举值

一时只定义了有线网和有线网的意况 

 1     /// <summary>
 2     /// 网络状态
 3     /// </summary>
 4     public enum NetworkStatus
 5     {
 6         Internet,
 7         InternetWithError,
 8         WifiWithErro,
 9         WifiWithOneBar,
10         WifiWithTwoBars,
11         WifiWithThreeBars,
12         WifiWithFourBars,
13     }

那就是说,具体是不是有线/依旧有线网络,怎么样判断?见下边~

 

返回值(bool)

  • 当重返值为true,且无不当Code时,表示网络已接二连三
  • 当重回值为false,且无不当Code时,表示互联网未连接

那么,错误Code(至极)怎么获取呢?

快捷键win+R→输入cmd→回车

WIFI_STATE_ENABLING WIFI网卡正在打开

得到有线网络的信号强度

获取WLAN的称呼与信号强度

有线网的音讯,能够通过第1方开源ManagedWifi来获取。

ManagedWifi.Dll也足以从自己的云盘下载:
密码:2d2o

下载后引用到花色中

  1. WlanClient wlanClient = new WlanClient();

  2. 循环foreach(WlanClient.WlanInterface wlanIface in
    wlanClient.Interfaces)

  3. Wlan.WlanAvailableNetwork[] networks =
    wlanIface.GetAvailableNetworkList(0);

值得注意的是,

  • WlanClient只在有网卡的系统中能开头化–所以若是WlanClient无法伊始化,且IsNetworkAlive再次来到true,则意味当前是有线连接网线
  • WlanInterfacer的GetAvailableNetworkList方法,获取的是隔壁wifi热点列表,和职责栏下热门列表的依次无关。
  • WlanAvailableNetwork的wlanSignalQuality信号强度,100以内,如要转换到信号格数,供给整除25
  • profileName,对已连接的走俏profileName呈现完整,未连接的走俏profileName为empty.

获得有线网连接景况:

 1 private NetworkStatus GetWlanStatus()
 2 {
 3     var wlanStatus = NetworkStatus.WifiWithErro;
 4     try
 5     {
 6         WlanClient wlanClient = new WlanClient();
 7 
 8         foreach (WlanClient.WlanInterface wlanIface in wlanClient.Interfaces)
 9         {
10             if (wlanIface.InterfaceState == Wlan.WlanInterfaceState.Connected && wlanIface.CurrentConnection.isState == Wlan.WlanInterfaceState.Connected)
11             {
12                 Wlan.WlanAvailableNetwork[] networks = wlanIface.GetAvailableNetworkList(0);
13                 foreach (var network in networks)
14                 {
15                     if (network.profileName == wlanIface.CurrentConnection.profileName
16                         && (int)network.flags == (int)(Wlan.WlanAvailableNetworkFlags.Connected | Wlan.WlanAvailableNetworkFlags.HasProfile))
17                     {
18                         switch (network.wlanSignalQuality / 25)
19                         {
20                             case 0:
21                                 wlanStatus = NetworkStatus.WifiWithOneBar;
22                                 break;
23                             case 1:
24                                 wlanStatus = NetworkStatus.WifiWithTwoBars;
25                                 break;
26                             case 2:
27                                 wlanStatus = NetworkStatus.WifiWithThreeBars;
28                                 break;
29                             default:
30                                 wlanStatus = NetworkStatus.WifiWithFourBars;
31                                 break;
32                         }
33                         break;
34                     }
35                 }
36                 break;
37             }
38         }
39     }
40     catch (Exception e)
41     {
42     }
43     return wlanStatus;
44 }

 

重庆大学字:互连网连接状态NetworkStatus,有线网络强度(格数),ManagedWifi,IsNetworkAlive,GetLastError

3. 拿走上三回不行Code-GetLastError

参考链接

此处推荐应用Marshal中的GetLastWin32Error,见如下源代码:

 1     /// <summary>
 2     ///   通过使用平台调用的最后一个非托管函数返回的错误代码返回调用具有 <see cref="F:System.Runtime.InteropServices.DllImportAttribute.SetLastError" /> 标志设置。
 3     /// </summary>
 4     /// <returns>最后一个错误代码设置通过调用 Win32 SetLastError 函数。</returns>
 5     [SecurityCritical]
 6     [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
 7     [MethodImpl(MethodImplOptions.InternalCall)]
 8     public static extern int GetLastWin32Error();

GetLastWin32Error可获得最终1个非托管函数的不当Code

 int errCode =
Marshal.GetLastWin32Error();

–获得 error
code的详细描述新闻,可参考

值得注意的是,非托管函数申明时,要添加SetLastError=true;如:

1 [DllImport("sensapi.dll", SetLastError = true)]
2 private static extern bool IsNetworkAlive(out int connectionDescription);

二 、启用并设定虚拟WiFi网卡:

WIFI_STATE_UNKNOWN    WIFI网卡状态不可见

 4. 使用Ping函数

1     using (var ping = new Ping())
2     {
3         //ping给定的host 如:www.baidu.com,超时时间为1s
4         var reply = ping.Send(host, 1000);
5         var pingResult= reply != null && reply.Status == IPStatus.Success;
6     }

运维命令:netsh wlan set hostednetwork mode=allow ssid=wuminPC
key=wuminWiFi(12345678)

2.要操作WiFi设备,就要采纳Context.getSystemService(Context.WIFI_SESportageVICE)来博取WifiManager对象,并通过那个指标来治本WiFi设备。

 推荐判断电脑接二连三网络的方案

如上,获取互连网状态是还是不是连接,提出通过IsNetworkAlive函数获取。那么IsNetworkAlive是还是不是可信吗?

答案是还是不是!

案例:

  1. 电脑配置了虚拟机连接–断网后,IsNetworkAlive重回的是有网true !–
    对虚拟机等网络是或不是连接不可能断定。
  2. 在少数情形下,光导纤维等坏了,上不停网络,不过走TCP协议得以聊微信QQ–IsNetworkAlive再次来到的是有网true
    !

无网络时,有可能回到有网:lpdwFlags=1
局域网时,就算当前配备了虚拟机连接之类的,本机不可能连接网络时,IsNetworkAlive函数照旧会回来true。如下:

澳门葡京备用网址 3

 
所以,假设是局域网且IsNetworkAlive重返true,则选取InternetGetConnectedState重新得到网络状态。

 1     //通过IsNetworkAlive方法,来获取电脑的联网状态
 2     [DllImport("sensapi.dll", SetLastError = true)]
 3     private static extern bool IsNetworkAlive(out int connectionDescription);
 4 
 5     //通过InternetGetConnectedState方法,来获取电脑的联网状态
 6     [DllImport("winInet.dll")]
 7     private static extern bool InternetGetConnectedState(ref IntPtr dwFlag, int dwReserved);
 8 
 9     /// <summary>
10     /// IsNetworkAlive函数输出值1-连接局域网
11     /// </summary>
12     private const int LanNetworkConnectedFlag = 1;
13     /// <summary>
14     /// 网络是否连接
15     /// </summary>
16     public static bool IsConnected
17     {
18         get
19         {
20             var isNetworkConnected = IsNetworkAlive(out int flags);
21             int errCode = Marshal.GetLastWin32Error();
22             if (errCode != 0)
23             {
24                 Console.WriteLine($"通过{nameof(IsNetworkAlive)}非托管DLL函数,获取网络状态时,遇到异常!");
25             }
26 
27             //IsNetworkAlive检测到是局域网连上网络,则使用InternetGetConnectedState重新确认是否有网
28             if (isNetworkConnected && flags == LanNetworkConnectedFlag)
29             {
30                 var dwFlag = new IntPtr();
31                 isNetworkConnected = InternetGetConnectedState(ref dwFlag, 0);
32                 errCode = Marshal.GetLastWin32Error();
33                 if (errCode != 0)
34                 {
35                     Console.WriteLine($"通过{nameof(InternetGetConnectedState)}非托管DLL函数,获取网络状态时,遇到异常!");
36                 }
37             }
38 
39             return isNetworkConnected;
40         }
41     }

 赢得系统的互连网状态与有线网的信号强度(格数)

 

addNetwork(WifiConfiguration config)

此命令有多少个参数,mode:是或不是启用虚拟WiFi网卡,改为disallow则为禁止使用。

累加三个config描述的WIFI网络,暗中认可情状下,这么些WIFI网络是DISABLE状态的。
calculateSignalLevel(int rssi , int numLevels)

ssid:有线网名称,最好用英文(以wuminPC为例)。

计量信号的阶段 compareSignalLevel(int rssiA, int rssiB)

key:无线网密码,五个以上字符(以wuminWiFi为例)。

相对而言互连网A和互联网B的信号强度 createWifiLock(int lockType, String tag)

如上五个参数能够独立选拔,例如只行使mode=disallow能够直接禁止使用虚拟Wifi网卡。

创设3个WIFI 锁,锁定当前的WIFI连接 disableNetwork(int netId)

敞开成功后,互连网连接中会多出1个网卡为“Microsoft Virtual WiFi Miniport
Adapter”的有线连接2,为便宜起见,将其重命名为虚拟WiFi。若没有,只需立异有线网卡驱动就OK了。

让二个网络连接失效 disconnect()

在微型总括机右下角“打开互连网基本与共享”->”更改适配置安装”->右键”本地宽带”->“属性”->首要:家庭互联网连接:虚拟wifi

断开当前的WIFI连接 enableNetwork(int netId, Boolean disableOthers)

 

连日来netId所指的WIFI网络,并是其余的网络都被剥夺 getConfiguredNetworks()

③ 、设置Internet连接共享:

获得互联网连接的意况 getConnectionInfo()

在“互连网连接”窗口中,右键单击已连续到Internet的互连网连接,选拔“属性”→“共享”,勾上“允许别的······连接(N)”并精选“虚拟WiFi

赢妥善前连连的音讯 getDhcpInfo()

规定之后,提供共享的网卡图标旁会并发“共享的”字样,表示“宽带连接”已共享至“虚拟WiFi

获取DHCP 的信息 getScanResulats()

 

获取扫描测试的结果 getWifiState()

④ 、开启有线互连网:

得到当前WIFI设备的气象 isWifiEnabled()

继续在指令提醒符中运营:netsh wlan start hostednetwork

看清WIFI设备是不是打开 pingSupplicant()

(将start改为stop即可关闭该有线网,以往开机后要启用该有线网只需再度运转此命令即可)

ping操作,和PC的ping操作相同效果 ressociate()

从这之后,虚拟WiFi的红叉叉消失,WiFi基站已组装好,主机设置停止。台式机、带WiFi模块的无绳电话机等子机搜索到有线网络wuminPC,输入密码wuminWiFi,就能共享上网啦!

再次连接WIFI互连网,就算该互连网是曾经被连接上的 reconnect()

附:展现有线网络音信命令:netsh wlan show hostednetwork

再一次连接1个未连接上的WIFI互连网 removeNetwork()

编造有线AP发射的WLAN是802.11g行业内部,带宽为54Mbps

移除某四个互连网 saveConfiguration()

 

封存一个布署新闻 setWifiEnabled()

2013.1.4心得

让1个老是有效 startScan()

 

开始扫描 updateNetwork(WifiConfiguration config)

5.借使在急需共享的宽带连接->属性->共享中
出现大约意思是“共享不可用,出现谬误是0x八千500”

立异二个互连网连接

缓解方式 :将防火墙打开

3.固然要想获取周围的WIFI热点列表,能够采取WifiManager.getScanResults()重临1个ScanResult列表,ScanResult对象中,包括了以下几本个性:

 

BSSID 接入点的地方 SSID 互联网的名字,唯一差异WIFI网络的名字 Capabilities
互连网相联的特性 Frequency 当前WIFI设备附近热点的频率(MHz) Level
所发现的WIFI互连网信号强度

6.假设出现你输入 netsh wlan start hostedwork 回车时出现 不可能加载

4.老是上自定义的WIFI? //依据ID值来机关三番五次WIFI互联网

消除措施 : 将你电脑的有线网络端口提醒灯打开(一般是
Fn+F飞速键【遵照你的电脑,能够查阅是怎么打开的】)

//@param index ID值

)
主机设置如下: 一 、以管理人身份运转命令提示符:
飞速键win+索罗德输入cmd回车…

public void ConnectWifiBySSID(int index) {

    // 索引大于配置好的网络索引重临

    if (index > mWifiConfiguration.size()) {

     return;

    }

    // 连接配置好的钦点ID的网络

   
mWifiManager.enableNetwork(mWifiConfiguration.get(index).networkId,true);

}

// 依据WifiConfiguration对象来机关连接WIFI网络

// @param wcg WifiConfiguration对象

public void ConnectWifiByConfig(WifiConfiguration wifiConfiguration) {

    int wcgID = mWifiManager.addNetwork(wifiConfiguration);

    mWifiManager.enableNetwork(wcgID, true);

}

5.翻看已经延续上的WIFI信息,在Android的SDK中为我们提供了一个名为WifiInfo的靶子,那一个目的足以因而WifiManager.getConnectionInfo()来收获。WifiInfo中包罗了最近一而再中的相关音信。

getBSSID()  获取BSSID属性 getDetailedStateOf()  获取客户端的连通性
getHiddenSSID()  获取SSID 是或不是被隐藏 getIpAddress()  获取IP 地址
getLinkSpeed()  获取连接的进程 getMacAddress()  获取Mac 地址 get福睿斯ssi() 
获取802.11n 互联网的信号 getSSID()  获取SSID getSupplicanState() 
获取具体客户端状态的新闻

 

wifi管理类

澳门葡京备用网址 4澳门葡京备用网址 5

package youcan.text;

import java.util.List;
import android.content.Context;
import android.net.wifi.ScanResult;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.net.wifi.WifiManager.WifiLock;

public class WifiAdmin {
 // 定义WifiManager对象
 private WifiManager mWifiManager;
 // 定义WifiInfo对象
 private WifiInfo mWifiInfo;
 // 扫描出的网络连接列表
 private List<ScanResult> mWifiList;
 // 网络连接列表
 private List<WifiConfiguration> mWifiConfiguration;
 // 定义一个WifiLock
 WifiLock mWifiLock;

// 构造器
 public WifiAdmin(Context context) {
   // 取得WifiManager对象
   mWifiManager = (WifiManager) context
     .getSystemService(Context.WIFI_SERVICE);
   // 取得WifiInfo对象
   mWifiInfo = mWifiManager.getConnectionInfo();
 }

// 得到WifiManager对象
 public WifiManager GetWifiManager() {
   return mWifiManager;
 }

// 打开WIFI
 public void OpenWifi() {
   if (!mWifiManager.isWifiEnabled()) {
    mWifiManager.setWifiEnabled(true);

   }
 }

// 关闭WIFI
 public void CloseWifi() {
   if (!mWifiManager.isWifiEnabled()) {
    mWifiManager.setWifiEnabled(false);
   }
 }

// 锁定WifiLock
 public void AcquireWifiLock() {
   mWifiLock.acquire();
 }

// 解锁WifiLock
 public void ReleaseWifiLock() {
   // 判断时候锁定
   if (mWifiLock.isHeld()) {
    mWifiLock.acquire();
   }
 }

// 创建一个WifiLock
 public void CreatWifiLock() {
   mWifiLock = mWifiManager.createWifiLock("Test");
 }

// 得到配置好的网络
 public List<WifiConfiguration> GetConfiguration() {
   return mWifiConfiguration;
 }

// 指定配置好的网络进行连接
 public void ConnectConfiguration(int index) {
   // 索引大于配置好的网络索引返回
   if (index > mWifiConfiguration.size()) {
    return;
   }
   // 连接配置好的指定ID的网络
   mWifiManager.enableNetwork(mWifiConfiguration.get(index).networkId,
     true);
 }

public void StartScan() {
   mWifiManager.startScan();
   // 得到扫描结果
   mWifiList = mWifiManager.getScanResults();
   // 得到配置好的网络连接
   mWifiConfiguration = mWifiManager.getConfiguredNetworks();
 }

// 得到网络列表
 public List<ScanResult> GetWifiList() {
   return mWifiList;
 }

// 查看扫描结果
 public StringBuilder LookUpScan() {
   StringBuilder stringBuilder = new StringBuilder();
   for (int i = 0; i < mWifiList.size(); i++) {
    stringBuilder
      .append("Index_" + new Integer(i + 1).toString() + ":");
    // 将ScanResult信息转换成一个字符串包
    // 其中把包括:BSSID、SSID、capabilities、frequency、level
    stringBuilder.append((mWifiList.get(i)).toString());
    stringBuilder.append("\n");
   }
   return stringBuilder;
 }

// 得到MAC地址
 public String GetMacAddress() {
   return (mWifiInfo == null) ? "NULL" : mWifiInfo.getMacAddress();
 }

// 得到接入点的BSSID
 public String GetBSSID() {
   return (mWifiInfo == null) ? "NULL" : mWifiInfo.getBSSID();
 }

// 得到IP地址
 public int GetIPAddress() {
   return (mWifiInfo == null) ? 0 : mWifiInfo.getIpAddress();
 }

// 得到连接的ID
 public int GetNetworkId() {
   return (mWifiInfo == null) ? 0 : mWifiInfo.getNetworkId();
 }

// 得到WifiInfo的所有信息包
 public String GetWifiInfo() {
   return (mWifiInfo == null) ? "NULL" : mWifiInfo.toString();
 }

// 添加一个网络并连接
 public void AddNetwork(WifiConfiguration wcg) {
   int wcgID = mWifiManager.addNetwork(wcg);
   mWifiManager.enableNetwork(wcgID, true);
 }

// 断开指定ID的网络
 public void DisconnectWifi(int netId) {
   mWifiManager.disableNetwork(netId);
   mWifiManager.disconnect();
 }
}

View Code

 

 android wifi运行进度

澳门葡京备用网址 6澳门葡京备用网址 7

初始化
在 SystemServer 启动的时候,会生成一个 ConnectivityService 的实例,
  try {
        Log.i(TAG, "Starting Connectivity Service.");
        ServiceManager.addService(Context.CONNECTIVITY_SERVICE, new ConnectivityService(context));
  } catch (Throwable e) {
        Log.e(TAG, "Failure starting Connectivity Service", e);
}
ConnectivityService 的构造函数会创建 WifiService,
  if (DBG) Log.v(TAG, "Starting Wifi Service.");
  mWifiStateTracker = new WifiStateTracker(context, handler);
  WifiService wifiService = new WifiService(context, mWifiStateTracker);
  ServiceManager.addService(Context.WIFI_SERVICE, wifiService);

WifiStateTracker 会创建 WifiMonitor 接收来自底层的事件,
WifiService 和 WifiMonitor 是整个模块的核心。
WifiService 负责启动关闭 wpa_supplicant、启动关闭 WifiMonitor 监视线程和把命令下发给 wpa_supplicant,
而 WifiMonitor 则负责从 wpa_supplicant 接收事件通知。
连接 AP
1. 使能 WIFI
WirelessSettings 在初始化的时候配置了由 WifiEnabler 来处理 Wifi 按钮,
 private void initToggles() {
      mWifiEnabler = new WifiEnabler(
   this,
            (WifiManager) getSystemService(WIFI_SERVICE),
            (CheckBoxPreference) findPreference(KEY_TOGGLE_WIFI)
   );
 }
当用户按下 Wifi 按钮后,Android 会调用 WifiEnabler 的 onPreferenceChange,
再由 WifiEnabler调用 WifiManager 的 setWifiEnabled 接口函数,
通过 AIDL,实际调用的是 WifiService 的setWifiEnabled 函数,
WifiService 接着向自身发送一条 MESSAGE_ENABLE_WIFI 消息,
在处理该消息的代码中做真正的使能工作:
首先装载 WIFI 内核模块(该模块的位置硬编码为"/system/lib/modules/wlan.ko" ),
然 后 启 动 wpa_supplicant ( 配 置 文 件 硬 编 码为"/data/misc/wifi/wpa_supplicant.conf")
再通过 WifiStateTracker 来启动 WifiMonitor 中的监视线程。
     private boolean setWifiEnabledBlocking(boolean enable) {
          final int eventualWifiState = enable ? WIFI_STATE_ENABLED : WIFI_STATE_DISABLED;
          updateWifiState(enable ? WIFI_STATE_ENABLING : WIFI_STATE_DISABLING);
          if (enable) {
                if (!WifiNative.loadDriver()) {
                       Log.e(TAG, "Failed to load Wi-Fi driver.");
                       updateWifiState(WIFI_STATE_UNKNOWN);
                       return false;
                }
                if (!WifiNative.startSupplicant()) {
                       WifiNative.unloadDriver();
                       Log.e(TAG, "Failed to start supplicant daemon.");
                       updateWifiState(WIFI_STATE_UNKNOWN);
                       return false;
                }
                mWifiStateTracker.startEventLoop();
          }
             // Success!
             persistWifiEnabled(enable);
             updateWifiState(eventualWifiState);
             return true;
      }
当使能成功后,会广播发送 WIFI_STATE_CHANGED_ACTION 这个 Intent 通知外界 WIFI 已经成功使能了。
WifiEnabler 创建的时候就会向 Android 注册接收WIFI_STATE_CHANGED_ACTION,
因此它会收到该 Intent,从而开始扫描。
          private void handleWifiStateChanged(int wifiState) {
             if (wifiState == WIFI_STATE_ENABLED) {
                  loadConfiguredAccessPoints();
                  attemptScan();
             }
2. 查找 AP
扫描的入口函数是 WifiService 的 startScan,它其实也就是往 wpa_supplicant 发送 SCAN 命令。
static jboolean android_net_wifi_scanCommand(JNIEnv* env, jobject clazz)
{
      jboolean result;
      // Ignore any error from setting the scan mode.
      // The scan will still work.
      (void)doBooleanCommand("DRIVER SCAN-ACTIVE", "OK");
      result = doBooleanCommand("SCAN", "OK");
      (void)doBooleanCommand("DRIVER SCAN-PASSIVE", "OK");
      return result;
}
当 wpa_supplicant 处理完 SCAN 命令后,它会向控制通道发送事件通知扫描完成,
从而wifi_wait_for_event 函数会接收到该事件,
由此 WifiMonitor 中的 MonitorThread 会被执行来出来这个事件,
             void handleEvent(int event, String remainder) {
                        case SCAN_RESULTS:
                             mWifiStateTracker.notifyScanResultsAvailable();
                             break;
WifiStateTracker 则接着广播发送 SCAN_RESULTS_AVAILABLE_ACTION 这个 Intent
                  case EVENT_SCAN_RESULTS_AVAILABLE:
                        mContext.sendBroadcast(new Intent(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION));
WifiLayer 注册了接收 SCAN_RESULTS_AVAILABLE_ACTION 这个 Intent,所以它的相关
处理函数 handleScanResultsAvailable 会被调用,在该函数中,先会去拿到 SCAN 的结果(最
终是往 wpa_supplicant 发送 SCAN_RESULT 命令并读取返回值来实现的)                             ,
                List<ScanResult> list = mWifiManager.getScanResults();
对每一个扫描返回的 AP,WifiLayer 会调用 WifiSettings 的 onAccessPointSetChanged 函数,
从而最终把该 AP 加到 GUI 显示列表中。
     public void onAccessPointSetChanged(AccessPointState ap, boolean added) {
          AccessPointPreference pref = mAps.get(ap);
          if (added) {
                if (pref == null) {
                      pref = new AccessPointPreference(this, ap);
                      mAps.put(ap, pref);
                } else {
                      pref.setEnabled(true);
                }
                mApCategory.addPreference(pref);
          }
     }
3. 配置 AP 参数
当用户在 WifiSettings 界面上选择了一个 AP 后,会显示配置 AP 参数的一个对话框,
     public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference) {
          if (preference instanceof AccessPointPreference) {
                AccessPointState state = ((AccessPointPreference) preference).getAccessPointState();
                showAccessPointDialog(state, AccessPointDialog.MODE_INFO);
          }
     }
4. 连接
当用户在 AcessPointDialog 中选择好加密方式和输入密钥之后,再点击连接按钮,Android
就会去连接这个 AP。
     private void handleConnect() {
          String password = getEnteredPassword();
          if (!TextUtils.isEmpty(password)) {
                mState.setPassword(password);
          }
          mWifiLayer.connectToNetwork(mState);
     }
WifiLayer 会先检测这个 AP 是不是之前被配置过,这个是通过向 wpa_supplicant 发送
LIST_NETWORK 命令并且比较返回值来实现的,
          // Need WifiConfiguration for the AP
          WifiConfiguration config = findConfiguredNetwork(state);
如果 wpa_supplicant 没有这个 AP 的配置信息,则会向 wpa_supplicant 发送 ADD_NETWORK 命令来添加该 AP,
          if (config == null) {
                // Connecting for the first time, need to create it
                config = addConfiguration(state, ADD_CONFIGURATION_ENABLE|ADD_CONFIGURATION_SAVE);
          }
ADD_NETWORK 命 令 会 返 回 一 个 ID , WifiLayer 再用这个返回的ID作为参数向
wpa_supplicant 发送 ENABLE_NETWORK 命令,从而让 wpa_supplicant 去连接该 AP。
          // Make sure that network is enabled, and disable others
          mReenableApsOnNetworkStateChange = true;
          if (!mWifiManager.enableNetwork(state.networkId, true)) {
                Log.e(TAG, "Could not enable network ID " + state.networkId);
                error(R.string.error_connecting);
                return false;
          }
5. 配置 IP 地址
当 wpa_supplicant 成功连接上 AP 之后,它会向控制通道发送事件通知连接上 AP 了,从而
wifi_wait_for_event 函数会接收到该事件,由此 WifiMonitor 中的 MonitorThread 会被执行来
出来这个事件,
          void handleEvent(int event, String remainder) {
                     case CONNECTED:
                           handleNetworkStateChange(NetworkInfo.DetailedState.CONNECTED,remainder);
                           break;
WifiMonitor 再调用 WifiStateTracker 的 notifyStateChange,WifiStateTracker 则接着会往自身
发送 EVENT_DHCP_START 消息来启动 DHCP 去获取 IP 地址,
     private void handleConnectedState() {
          setPollTimer();
          mLastSignalLevel = -1;
          if (!mHaveIPAddress && !mObtainingIPAddress) {
                mObtainingIPAddress = true;
                mDhcpTarget.obtainMessage(EVENT_DHCP_START).sendToTarget();
          }
     }
然后再广播发送 NETWORK_STATE_CHANGED_ACTION 这个 Intent
                case EVENT_NETWORK_STATE_CHANGED:
                     if (result.state != DetailedState.DISCONNECTED || !mDisconnectPending) {
                           intent = new Intent(WifiManager.NETWORK_STATE_CHANGED_ACTION);
                           intent.putExtra(WifiManager.EXTRA_NETWORK_INFO, mNetworkInfo);
                          if (result.BSSID != null)
                                intent.putExtra(WifiManager.EXTRA_BSSID, result.BSSID);
                          mContext.sendStickyBroadcast(intent);
                     }
                     break;
WifiLayer 注册了接收 NETWORK_STATE_CHANGED_ACTION 这个 Intent,所以它的相关
处理函数 handleNetworkStateChanged 会被调用,
当 DHCP 拿到 IP 地址之后,会再发送 EVENT_DHCP_SUCCEEDED 消息,
     private class DhcpHandler extends Handler {
          public void handleMessage(Message msg) {
                switch (msg.what) {
                     case EVENT_DHCP_START:
                          if (NetworkUtils.runDhcp(mInterfaceName, mDhcpInfo)) {
                                event = EVENT_DHCP_SUCCEEDED;
                                                      }
WifiLayer 处理 EVENT_DHCP_SUCCEEDED 消息 , 会再次广播发送
NETWORK_STATE_CHANGED_ACTION 这个 Intent,这次带上完整的 IP 地址信息。
                case EVENT_DHCP_SUCCEEDED:
                     mWifiInfo.setIpAddress(mDhcpInfo.ipAddress);
                     setDetailedState(DetailedState.CONNECTED);
                     intent = new Intent(WifiManager.NETWORK_STATE_CHANGED_ACTION);
                     intent.putExtra(WifiManager.EXTRA_NETWORK_INFO, mNetworkInfo);
                     mContext.sendStickyBroadcast(intent);
                     break;

至此为止,整个连接过程完成


  WifiManager wifi = (WifiManager)getSystemService(Context.WIFI_SERVICE);
  WifiConfiguration wc = new WifiConfiguration();
  wc.SSID = ""test"";//ssid
  wc.preSharedKey = ""12345678"";//ssid密码
  wc.hiddenSSID = true;
  wc.status = WifiConfiguration.Status.ENABLED;
  wc.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.TKIP);
  wc.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP);
  wc.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK);
  wc.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.TKIP);
  wc.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP);
  wc.allowedProtocols.set(WifiConfiguration.Protocol.RSN);
  int res = wifi.addNetwork(wc);
  Log.e("WifiPreference", "add Network returned " + res );
  boolean b = wifi.enableNetwork(res, true);
  Log.e("WifiPreference", "enableNetwork returned " + b );

=====================================================================

package src.hero.com;

import java.util.ArrayList;
import java.util.List;

import android.app.ListActivity;
import android.net.wifi.ScanResult;
import android.net.wifi.WifiConfiguration;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.AdapterView.OnItemClickListener;

public class ListOk extends ListActivity implements OnItemClickListener
{

 private ListView lv;

 private WifiTester wifiTester;

 // -----------------------连接WIFI
 private ScanResult scanRet;

 private WifiConfiguration wc;

 public void onCreate(Bundle savedInstanceState)
 {
  super.onCreate(savedInstanceState);
  this.setTitle("当前可用的WIFI列表");

  WifiTesterApp _TestActivityApp = (WifiTesterApp) this.getApplication();
  wifiTester = (_TestActivityApp).getWifiTester();

  wc = new WifiConfiguration();

  ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
    android.R.layout.simple_list_item_1,
    getString(wifiTester.getWifiList()));
  setListAdapter(adapter);
  lv = getListView();
  lv.setAdapter(adapter);
  lv.setOnItemClickListener(this);
 }

 public String[] getString(List<ScanResult> wifiList)
 {
  ArrayList<String> listStr = new ArrayList<String>();

  for (int i = 0; i < wifiList.size(); i++)
  {
   listStr.add(wifiList.get(i).toString());
  }
  return listStr.toArray(new String[0]);
 }

 @Override
 public void onItemClick(AdapterView<?> parent, View view, int position,
   long id)
 {

  scanRet = wifiTester.getWifiList().get(position);
  wc.SSID = """ + scanRet.SSID + """; // 配置wifi的SSID,即该热点的名称,如:TP-link_xxx
  wc.preSharedKey = ""7675781777""; // 该热点的密码
  wc.hiddenSSID = true;
  wc.status = WifiConfiguration.Status.ENABLED;
  wc.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.TKIP);
  wc.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP);
  wc.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK);
  wc.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.TKIP);
  wc.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP);
  wc.allowedProtocols.set(WifiConfiguration.Protocol.RSN);
  // int res = wifiTester.getMainWifi().addNetwork(wc);
  // Log.d("Wif iPreference", "1111111add Network returned " + res);
  // boolean b = wifiTester.getMainWifi().enableNetwork(res, true);
  // Log.d("WifiPreference", "2222222222enableNetwork returned " + b);

 }
}

============================================================

package jmu84xu.all;

import java.net.Inet4Address;
import java.util.List;
import android.app.Activity;
import android.content.Context;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.os.Bundle;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.TextView;
import android.widget.CompoundButton.OnCheckedChangeListener;

public class WifiSet extends Activity implements OnCheckedChangeListener {

 private WifiManager wifiManager;
 private WifiInfo wifiInfo;
 private CheckBox chkOpenCloseWifiBox;
 private List<WifiConfiguration> wifiConfigurations;

 @Override
 public void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.main);

  wifiManager = (WifiManager) getSystemService(Context.WIFI_SERVICE);// 获得WifiManager对象
  wifiInfo = wifiManager.getConnectionInfo();// 获得连接信息对象

  chkOpenCloseWifiBox = (CheckBox)findViewById(R.id.chkOpenCloseWifi);
  TextView tvWifiConfigurations = (TextView) findViewById(R.id.tvWifiConfigurations);
  TextView tvWifiInfo = (TextView) findViewById(R.id.tvWifiInfo);

  chkOpenCloseWifiBox.setOnCheckedChangeListener(this);
  // 根据当前WIFI的状态(是否被打开)设置复选框的选中状态
  if (wifiManager.isWifiEnabled()) {
   chkOpenCloseWifiBox.setText("Wifi已开启");
   chkOpenCloseWifiBox.setChecked(true);
  }
  else {
   chkOpenCloseWifiBox.setText("Wifi已关闭");
   chkOpenCloseWifiBox.setChecked(false);
  }
  // 获得WIFI信息
  StringBuffer sb = new StringBuffer();
  sb.append("Wifi信息n");
  sb.append("MAC地址:" + wifiInfo.getMacAddress() + "n");
  sb.append("接入点的BSSID:" + wifiInfo.getBSSID() + "n");
  sb.append("IP地址(int):" + wifiInfo.getIpAddress() + "n");
  sb.append("IP地址(Hex):" + Integer.toHexString(wifiInfo.getIpAddress()) + "n");
  sb.append("IP地址:" + ipIntToString(wifiInfo.getIpAddress()) + "n");

  sb.append("网络ID:" + wifiInfo.getNetworkId() + "n");
  tvWifiInfo.setText(sb.toString());
 // 得到配置好的网络
  wifiConfigurations = wifiManager.getConfiguredNetworks();
  tvWifiConfigurations.setText("已连接的无线网络n");
  for (WifiConfiguration wifiConfiguration : wifiConfigurations) {
   tvWifiConfigurations.setText(tvWifiConfigurations.getText() + wifiConfiguration.SSID + "n"
   );
  }
 }
 // 将int类型的IP转换成字符串形式的IP
 private String ipIntToString(int ip) {
  try {
   byte[] bytes = new byte[4];
   bytes[0] = (byte) (0xff & ip);
   bytes[1] = (byte) ((0xff00 & ip) >> 8);
   bytes[2] = (byte) ((0xff0000 & ip)>> 16);
   bytes[3] = (byte) ((0xff000000 & ip)>> 24);
   return Inet4Address.getByAddress(bytes).getHostAddress();
  } catch (Exception e) {
   return"";
  }
 }
 @Override
 public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
  // 当选中复选框时打开WIFI
  if (isChecked) {
   wifiManager.setWifiEnabled(true);
   chkOpenCloseWifiBox.setText("Wifi已开启");
  }
  // 当取消复选框选中状态时关闭WIFI
  else {
   wifiManager.setWifiEnabled(false);
   chkOpenCloseWifiBox.setText("Wifi已关闭");
  }
 }
}
   在AndroidManifest.xml文件中要使用如下的代码打开相应的权限。
   Java代码:
XML/HTML代码
<uses-permissionandroid:name="android.permission.ACCESS_WIFI_STATE"></uses-permission>
<uses-permissionandroid:name="android.permission.WAKE_LOCK"></uses-permission>
<uses-permissionandroid:name="android.permission.CHANGE_WIFI_STATE"></uses-permission>

================================================================

package com.eoeandroid.demo.testcode;

import java.util.List;

import android.app.Activity;

import android.content.BroadcastReceiver;

import android.content.Context;

import android.content.Intent;

import android.content.IntentFilter;

import android.net.wifi.ScanResult;

import android.net.wifi.WifiManager;

import android.os.Bundle;

import android.view.Menu;

import android.view.MenuItem;

import android.widget.TextView;

public class WifiTester extends Activity {

        TextView mainText;

        WifiManager mainWifi;

        WifiReceiver receiverWifi;

        List<ScanResult> wifiList;

        StringBuilder sb = new StringBuilder();

        public void onCreate(Bundle savedInstanceState) {

                super.onCreate(savedInstanceState);

                setContentView(R.layout.WifiTester);

                setTitle("eoe教程: Wifi Test.  -by:IceskYsl");

                mainText = (TextView) findViewById(R.id.wifi);

                mainWifi = (WifiManager) getSystemService(Context.WIFI_SERVICE);

                receiverWifi = new WifiReceiver();

                registerReceiver(receiverWifi, new IntentFilter(

                                WifiManager.SCAN_RESULTS_AVAILABLE_ACTION));

                mainWifi.startScan();

                mainText.setText("nStarting Scan...n");

        }

        public boolean onCreateOptionsMenu(Menu menu) {

                menu.add(0, 0, 0, "Refresh");

                return super.onCreateOptionsMenu(menu);

        }

        public boolean onMenuItemSelected(int featureId, MenuItem item) {
                  mainWifi.startScan();

                mainText.setText("Starting Scan");

                return super.onMenuItemSelected(featureId, item);

        }

        protected void onPause() {

                unregisterReceiver(receiverWifi);

                super.onPause();

        }

        protected void onResume() {

                registerReceiver(receiverWifi, new IntentFilter(

                                WifiManager.SCAN_RESULTS_AVAILABLE_ACTION));

                super.onResume();

        }

        class WifiReceiver extends BroadcastReceiver {

                public void onReceive(Context c, Intent intent) {

                        sb = new StringBuilder();

                        wifiList = mainWifi.getScanResults();

                        for (int i = 0; i < wifiList.size(); i++) {

                                sb.append(new Integer(i + 1).toString() + ".");

                                sb.append((wifiList.get(i)).toString());

                                sb.append("nn");

                        }

                        mainText.setText(sb);

                }

        }

}

View Code

 

相关文章

发表评论

电子邮件地址不会被公开。 必填项已用*标注

*
*
Website