huazhi 发表于 2015-10-1 12:21:58

Android开发——自动连接指定SSID的wifi热点(不加密/加密)

  最近在做一个项目,其中涉及到一块“自动连接已存在的wifi热点”的功能,在网上查阅了大量资料,五花八门,但其中一些说的很简单,即不能实现傻瓜式的拿来就用,有些说的很详细,但其中不乏些许错误造成功能无法实现,经过浣熊多方努力,终于成功将功能实现,遂将一点点小成就拿出来与大家分享。
  
  首先需要感谢这篇文章的作者:http://blog.chinaunix.net/uid-22342564-id-3228565.html
  在这篇文章中,作者定义了一个wifi工具类,其中存在着操作wifi的各种方法,其中有一些错误我以改正,正确的代码如下(创建一个名为WifiAdmin.java的文件,以下代码中没有包声明和import,请自行添加):
  



view plaincopy

[*]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();
[*]    }
[*]
[*]    // 打开WIFI   
[*]    public void openWifi() {   
[*]      if (!mWifiManager.isWifiEnabled()) {   
[*]            mWifiManager.setWifiEnabled(true);   
[*]      }
[*]    }
[*]
[*]    // 关闭WIFI   
[*]    public void closeWifi() {   
[*]      if (mWifiManager.isWifiEnabled()) {   
[*]            mWifiManager.setWifiEnabled(false);   
[*]      }
[*]    }
[*]
[*]    // 检查当前WIFI状态   
[*]    public int checkState() {   
[*]      return mWifiManager.getWifiState();   
[*]    }
[*]
[*]    // 锁定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);   
[*]   boolean b =mWifiManager.enableNetwork(wcgID, true);   
[*]   System.out.println("a--" + wcgID);
[*]   System.out.println("b--" + b);
[*]    }
[*]
[*]    // 断开指定ID的网络   
[*]    public void disconnectWifi(int netId) {   
[*]      mWifiManager.disableNetwork(netId);
[*]      mWifiManager.disconnect();
[*]    }
[*]
[*]//然后是一个实际应用方法,只验证过没有密码的情况:
[*]
[*]    public WifiConfiguration CreateWifiInfo(String SSID, String Password, int Type)   
[*]    {
[*]          WifiConfiguration config = new WifiConfiguration();   
[*]         config.allowedAuthAlgorithms.clear();
[*]         config.allowedGroupCiphers.clear();
[*]         config.allowedKeyManagement.clear();
[*]         config.allowedPairwiseCiphers.clear();
[*]         config.allowedProtocols.clear();
[*]          config.SSID = "\"" + SSID + "\"";   
[*]
[*]          WifiConfiguration tempConfig = this.IsExsits(SSID);            
[*]          if(tempConfig != null) {   
[*]            mWifiManager.removeNetwork(tempConfig.networkId);
[*]          }
[*]
[*]          if(Type == 1) //WIFICIPHER_NOPASS
[*]          {
[*]               config.wepKeys = "";   
[*]               config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
[*]               config.wepTxKeyIndex = 0;   
[*]          }
[*]          if(Type == 2) //WIFICIPHER_WEP
[*]          {
[*]            config.hiddenSSID = true;
[*]            config.wepKeys= "\""+Password+"\"";   
[*]            config.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.SHARED);
[*]            config.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP);
[*]            config.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.TKIP);
[*]            config.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP40);
[*]            config.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP104);
[*]            config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
[*]            config.wepTxKeyIndex = 0;   
[*]          }
[*]          if(Type == 3) //WIFICIPHER_WPA
[*]          {
[*]          config.preSharedKey = "\""+Password+"\"";   
[*]          config.hiddenSSID = true;   
[*]          config.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.OPEN);
[*]          config.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.TKIP);
[*]          config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK);
[*]          config.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.TKIP);
[*]          //config.allowedProtocols.set(WifiConfiguration.Protocol.WPA);   
[*]          config.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP);
[*]          config.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP);
[*]          config.status = WifiConfiguration.Status.ENABLED;
[*]          }
[*]         return config;   
[*]    }
[*]
[*]    private WifiConfiguration IsExsits(String SSID)   
[*]    {
[*]      List<WifiConfiguration> existingConfigs = mWifiManager.getConfiguredNetworks();
[*]         for (WifiConfiguration existingConfig : existingConfigs)   
[*]         {
[*]             if (existingConfig.SSID.equals("\""+SSID+"\""))   
[*]             {
[*]               return existingConfig;   
[*]             }
[*]         }
[*]      return null;   
[*]    }
[*]
[*]}
[*]//分为三种情况:1没有密码2用wep加密3用wpa加密
  
  
  改动主要集中在CreateWifiInfo这个方法中,并且添加了一个私有方法:
  (1)将与方法的第三个参数有关的变量都改成int型,或者使用原作者的枚举型(存在bug需要改正),但枚举会在后续的开发中遇到些困难;
  (2)在if(type == 3)中注释掉“config.allowedProtocols.set(WifiConfiguration.Protocol.WPA);”,并添加“
config.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP); config.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP);“这两句,否则当wifi热点需要输入密码时,无法加入网络。
(3)在代码末尾添加了方法IsExsits,原因在于如果按照网上介绍的方法成功加入指定的wifi后,都会在终端的wifi列表中新添加一个以该指定ssid的网络,所以每运行一次程序,列表中就会多一个相同名字的ssid。而该方法就是检查wifi列表中是否有以输入参数为名的wifi热点,如果存在,则在CreateWifiInfo方法开始配置wifi网络之前将其移除,以避免ssid的重复:
WifiConfiguration tempConfig = this.IsExsits(SSID);         
          if(tempConfig != null) {
          mWifiManager.removeNetwork(tempConfig.networkId);
          }
以上便是wifi工具类的建立,之后就可以在其他部分实例化这个类,调用其中的方法完成加入指定ssid的wifi热点,还是先上代码吧,建立一个名为Test_wifiActivity.java的文件(同上,没有包含包声明和import语句):




view plaincopy

[*]public class Test_wifiActivity extends Activity {
[*]    /** Called when the activity is first created. */
[*]    @Override
[*]    public void onCreate(Bundle savedInstanceState) {
[*]      super.onCreate(savedInstanceState);
[*]      setContentView(R.layout.main);
[*]
[*]      WifiAdmin wifiAdmin = new WifiAdmin(this);
[*]      wifiAdmin.openWifi();
[*]      wifiAdmin.addNetwork(wifiAdmin.CreateWifiInfo("XXX", "XXX", 3));
[*]    }
[*]}
  
很简单,如果是接入wifi,大体上只涉及到openWifi(打开wifi)、CreateWifiInfo(配置wifi网络信息)和addNetwork(添加配置好的网络并连接),对CreateWifiInfo进行简单的说明:第一参数是SSID的名称;第二个参数是指定SSID网络的密码,当不需要密码是置空(”“);第三个参数是热点类型:1-无密码 / 2-WEP密码验证(未测试)/ 3-WAP或WAP2 PSK密码验证。
  
最后就是在Manifest中添加相应的权限了:




view plaincopy

[*]<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" ></uses-permission>
[*]    <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" ></uses-permission>
[*]    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" ></uses-permission>
[*]    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" ></uses-permission>
  
如果按照上述的方法进行开发,就可以很傻瓜的通过改变Test_wifiActivity.java中的CreateWifiInfo方法的三个入口参数实现加入指定SSID的wifi热点了,无论该热点是否需要密码认证。
  
以上就是我对于自动连接指定SSID的wifi热点的学习心得,由于水平有限有些地方可能介绍错误,希望大家多多批评指正!
页: [1]
查看完整版本: Android开发——自动连接指定SSID的wifi热点(不加密/加密)