android wifi热点的创建以及连接通信(华为T8951 Google GALAXY Nexus 测试通过)

来源:互联网 发布:linux oracle停止实例 编辑:程序博客网 时间:2024/05/14 18:23

               参考网上的很多的资料,初步实现了wifi热点的创建、连接以及聊天通信以下是网上广为流传的Wifi 三种配置:

public WifiConfiguration createWifiInfo(String SSID, String password, int type) {Log.v(TAG, "SSID = " + SSID + "## Password = " + password + "## Type = " + 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);}// 分为三种情况:1没有密码2用wep加密3用wpa加密if (type == TYPE_NO_PASSWD) {// WIFICIPHER_NOPASSconfig.wepKeys[0] = "";config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);config.wepTxKeyIndex = 0;} else if (type == TYPE_WEP) {  //  WIFICIPHER_WEP config.hiddenSSID = true;config.wepKeys[0] = "\"" + 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;} else if (type == TYPE_WPA) {   // WIFICIPHER_WPAconfig.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;}


            wifi热点的创建代码:


 

package com.example.andoidwifihotdemo.wifiadamin;import java.lang.reflect.InvocationTargetException;import java.lang.reflect.Method;import com.example.andoidwifihotdemo.activity.BaseActivity;import com.example.andoidwifihotdemo.activity.WifiApAdminActivity;import com.example.andoidwifihotdemo.constant.Global;import android.content.Context;import android.net.wifi.WifiConfiguration;import android.net.wifi.WifiManager;import android.util.Log;/** *  * 热点搜索,创建,关闭 *  */public class WifiApAdmin {public static final String TAG = "WifiApAdmin";private WifiManager mWifiManager = null;private Context mContext = null;private static WifiApAdmin instance;private WifiApAdminActivity wifiApAdminActivity;public void closeWifiAp() {closeWifiAp(mWifiManager);}public static WifiApAdmin newInstance(Context context){if(instance==null){instance = new  WifiApAdmin(context);}return instance;}private  WifiApAdmin(Context context) {mContext = context;wifiApAdminActivity = (WifiApAdminActivity)context;mWifiManager = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);  closeWifiAp(mWifiManager);}public void startWifiAp() {Log.i(TAG, "into startWifiAp()");//創建Wifi熱點需要關閉Wifiif (mWifiManager.isWifiEnabled()) {mWifiManager.setWifiEnabled(false);} stratWifiAp();}//啟動一個Wifi 熱點private boolean stratWifiAp() {Log.i(TAG, "into startWifiAp() 启动一个Wifi 热点!");Method method1 = null;boolean ret = false;try {method1 = mWifiManager.getClass().getMethod("setWifiApEnabled",WifiConfiguration.class, boolean.class);//          WifiConfiguration netConfig =WifiApConfigurationAdmin.getInstance(mContext).CreateWifiInfo(Global.SSID, Global.SSID, 2);            //热点的配置类           WifiConfiguration apConfig = createPassHotWifiConfig(Global.SSID,Global.PASSWORD);ret = (Boolean) method1.invoke(mWifiManager, apConfig, true);} catch (IllegalArgumentException e) {e.printStackTrace();Log.d(TAG, "stratWifiAp() IllegalArgumentException e");} catch (IllegalAccessException e) {e.printStackTrace();Log.d(TAG, "stratWifiAp() IllegalAccessException e");} catch (InvocationTargetException e) {e.printStackTrace();Log.d(TAG, "stratWifiAp() InvocationTargetException e");} catch (SecurityException e) {e.printStackTrace();Log.d(TAG, "stratWifiAp() SecurityException e");} catch (NoSuchMethodException e) {e.printStackTrace();Log.d(TAG, "stratWifiAp() NoSuchMethodException e");}Log.i(TAG, "out startWifiAp() 启动一个Wifi 热点!");return ret;}//關閉Wifi熱點private  boolean closeWifiAp(WifiManager wifiManager) {Log.i(TAG, "into closeWifiAp() 关闭一个Wifi 热点!");boolean ret =false;if (isWifiApEnabled(wifiManager)) {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);ret = (Boolean) method2.invoke(wifiManager, config, false);} catch (NoSuchMethodException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (IllegalArgumentException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (IllegalAccessException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (InvocationTargetException e) {// TODO Auto-generated catch blocke.printStackTrace();}}Log.i(TAG, "out closeWifiAp() 关闭一个Wifi 热点!");return ret;}//检测Wifi 热点是否可用public  boolean isWifiApEnabled(WifiManager wifiManager) {try {Method method = wifiManager.getClass().getMethod("isWifiApEnabled");method.setAccessible(true);return (Boolean) method.invoke(wifiManager);} catch (NoSuchMethodException e) {e.printStackTrace();} catch (Exception e) {e.printStackTrace();}return false;}//扫描附近可用网络public void startScan(){//wifi 关闭的情况下,取消wifi状态广播监听if(BaseActivity.wifiStatebRoadCast){BaseActivity.wifiStatebRoadCast =false;wifiApAdminActivity.unregisterReceiver(wifiApAdminActivity.connectReceiver);}//搜索热点mWifiManager.startScan();}}

            以上代码就是网上收集的wifi热点的创建,关闭,检测是否可用,值得说明的是,参照部分大牛的代码,利用android的广播来监听附近wifi热点的扫描:


            IntentFilter intentWifiApoints = new IntentFilter(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION); 加入附近热点的扫描结果,热点扫描代码:

        

          

mWifimanager =(WifiManager)getSystemService(Context.WIFI_SERVICE);mWifiManager.startScan();

                   广播监听处理,根据SSID来判断附近热点有没有自己需要的连接的热点,然后配置相应的WifiConfiguration 连接Wifi热点:

                      

package com.example.andoidwifihotdemo.receiver;import java.util.ArrayList;import java.util.List;import com.example.andoidwifihotdemo.activity.BaseActivity;import com.example.andoidwifihotdemo.activity.WifiApAdminActivity;import com.example.andoidwifihotdemo.constant.Global;import com.example.andoidwifihotdemo.wifiadamin.WifiApConfigurationAdmin;import android.content.BroadcastReceiver;import android.content.Context;import android.content.Intent;import android.net.wifi.ScanResult;import android.net.wifi.WifiConfiguration;import android.net.wifi.WifiManager;import android.util.Log;/** * 扫描热点,找到符合规格的热点并连接 *  */public class WifiScanRsultBroadCast extends BroadcastReceiver {private Context mContext;private WifiApAdminActivity wifiApAdminActivity;private WifiManager mWifimanager;private String ssID;private List<WifiConfiguration> configurations = new ArrayList<WifiConfiguration>(); // 网络连接列表      private List<WifiConfiguration> mWifiConfiguration; private List<ScanResult> wifiList;    public WifiScanRsultBroadCast(Context context){this.mContext = context;wifiApAdminActivity = (WifiApAdminActivity)context;}@Overridepublic void onReceive(Context context, Intent intent) {Log.i("WifiBroadCast", "into onReceive(Context context, Intent intent)");if(intent.getAction().equalsIgnoreCase(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION)){mWifimanager = BaseActivity.mWifimanager;wifiList = mWifimanager.getScanResults();Log.i("WifiBroadCast", "into onReceive(Context context, Intent intent) wifiList= "+wifiList);if (wifiList == null || wifiList.size() == 0||WifiApAdminActivity.isConnecting){return;}configurations = BaseActivity.mWifimanager.getConfiguredNetworks();for(WifiConfiguration config :configurations){                Log.i("WifiBroadCast config pro 优先级", "  "+config.priority+"  config SSID="+config.SSID);                Log.i("WifiBroadCast config statu =", "  "+config.status); }   onReceiveNewNetworks(wifiList);Log.i("WifiBroadCast", "out onReceive(Context context, Intent intent)");  }   }/*当搜索到新的wifi热点时判断该热点是否符合规格*/public void onReceiveNewNetworks(List<ScanResult> wifiList){Log.i("WifiBroadCast", "into onReceiveNewNetworks(List<ScanResult> wifiList)");    for(ScanResult result:wifiList){       System.out.println(result.SSID);       if((result.SSID).contains(Global.SSID)){       synchronized (this) {        ssID =result.SSID;        new Thread(new Runnable() {@Overridepublic void run() {    connectToHotpot();}}).start();      }     } }  }/*连接到热点*/public void connectToHotpot(){Log.i("WifiBroadCast", "into  connectToHotpot()");if(ssID==null||ssID.equals("")){return;}WifiConfiguration config = WifiApConfigurationAdmin.getInstance(mContext).CreateWifiInfo(ssID,Global.PASSWORD,1);//WifiConfiguration config = createConnectWifiConfig();wifiApAdminActivity.enableNetwork(config);Log.i("WifiBroadCast", "out  connectToHotpot()");}} 


               值得提醒的一点是,通过Activity注册wifi热点广播监听时,记得注销掉,个人认为,在出发搜索事件的时候注册,在搜索结束之后应该注销掉,不然后台会一直在跑,自己测试的时候,一直在不停地打log日志,感觉很不好。

wifi热点的连接代码,其实很简单:

                int wcgID = mWifimanager.addNetwork(wifiConfig); Log.i(TAG, "into enableNetwork(WifiConfiguration wifiConfig) wcID = "+ wcgID);if (wcgID < 0) {Log.i(TAG,"into enableNetwork(WifiConfiguration wifiConfig) addNetWork fail!"); statu.setText("Wifi 热点连接失败!");isConnected = false; return;} boolean flag = mWifimanager.enableNetwork(wcgID, true);

       个人测试的部分所得是:如果需要连接某一个Wifi热点,必须得先添加网络,根据自己的华为手机测试结果知,一下添加代码的效果就只是将你所指定的热点网络加入到信任区
   addNetwork(wifiConfig);

           恩,以上所说的绝大部分都是根据网上大牛的代码所得,之下就是自己的一些个人收获:

        其实,wifi热点的创建、关闭了这些东西网上都有现成的代码很是简单,热点能否连接成功才是最关键的地方,而热点连接成功与否的关键应该在于热点创建的WifiConfiguration对象与连接热点时所创建的WifiConfiguration 对象是否匹配上。

            个人对计算机网络很是菜鸟,仅仅就是根据文章最前说的三种配置方式进行对应配置进行测试,过程中发现一些问题,与大家分享一下,希望大家多多指点:

            1.没有密码的配置方式

            A.热点创建端

          

               //1.没有任何密码保护       private WifiConfiguration createHotWifiConfig(String mSSID,String mPasswd){WifiConfiguration config = new WifiConfiguration();   config.allowedAuthAlgorithms.clear();config.allowedGroupCiphers.clear(); config.allowedKeyManagement.clear();config.allowedPairwiseCiphers.clear(); config.allowedProtocols.clear(); config.SSID = "" + mSSID + "";         config.wepKeys[0] = "";  config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);        config.wepTxKeyIndex = 0;config.priority=0;return config;}

             B.连接热点端配置

          

        WifiConfiguration config = new WifiConfiguration();config.allowedAuthAlgorithms.clear();config.allowedGroupCiphers.clear();config.allowedKeyManagement.clear();config.allowedPairwiseCiphers.clear();config.allowedProtocols.clear();config.SSID = "\"" + SSID + "\"";config.priority=0;IsExsits(SSID);// 分为三种情况:1没有密码2用wep加密3用wpa加密if (type == 1) {// WIFICIPHER_NOPASSconfig.wepKeys[0] = "\""+""+"\"";config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);config.wepTxKeyIndex = 0;}

              仔细一看,其实两端的代码基本上是一样的,唯一的差别就是在于
      config.SSID = "\"" + SSID + "\"";
   

             所以这是个人所得的第一点,在创建热点,以及连接热点时,转义字符千万别搞错了,否则在 addNetWork(wifiConfig)时,返回的NwtWorkID 会一直都是-1,也就是添加网络失败。

 

        说明ISExsists(String SSID)

     public void IsExsits(String SSID)      {          mWifiManager = WifiApAdminActivity.mWifimanager;        String destStr = "\""+SSID+"\"";        Log.i(TAG, "existingConfig destStr = "+destStr);        Log.d(TAG, "mWifiManager ="+mWifiManager);//      获取已配置wifi热点网络,通过 addNetwork(wifiConfig)会将连接端自己配置的WifiConfiguration加入到其中;        List<WifiConfiguration> existingConfigs = mWifiManager.getConfiguredNetworks();          if(existingConfigs==null){            return;        }           for (WifiConfiguration existingConfig : existingConfigs)              {                   Log.i(TAG, "existingConfig ssid = "+existingConfig.SSID);             if (existingConfig.SSID.equalsIgnoreCase(destStr))               {                   Log.i(TAG, "existingConfig contain ssid = "+existingConfig.SSID);                 mWifiManager.removeNetwork(existingConfig.networkId); //                 return existingConfig;               }             }  //        return null;       }

             因为

     addNetwork(wifiConfig)
   会将wifi热点连接端配置的WifiConfiguration 对象加入信任区中,在每一次连接自己指点的 WifiConfiguration 配置对象之前,需要根据SSID 将信任区中的 WifiConfiguration 对象移除,否侧的话网络会连接不上,这也就是个人所得的第二点,记得移除配置中已经存在的相同wifi热点配置。


     根据第一种配置方式进行测试,我的华为手机作为客户端连接到 GALAXY  热点是OK的,也可以进行聊天通信,但是如果换过来的话,即我的华为手机作为热点Server端,GALAXY  作为 连接热点客户端的话,就一直失败。

     addNetwork(wifiConfig) 方法会一直返回-1,当时自己就很诧异,难道是手机版本的问题,华为手机4.0系统,GALAXY 4.2的系统,自己就换了第二种配置方式:


        2.wep 配置方式

   

      A 热点创建端:

   

          WifiConfiguration config = new WifiConfiguration();        config.allowedAuthAlgorithms.clear();        config.allowedGroupCiphers.clear();        config.allowedKeyManagement.clear();        config.allowedPairwiseCiphers.clear();        config.allowedProtocols.clear();        config.SSID = "" + SSID + "";        config.priority=0;        config.hiddenSSID = true;        config.wepKeys[0] = "" + 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;


       B 热点连接端:

     

          WifiConfiguration config = new WifiConfiguration();        config.allowedAuthAlgorithms.clear();        config.allowedGroupCiphers.clear();        config.allowedKeyManagement.clear();        config.allowedPairwiseCiphers.clear();        config.allowedProtocols.clear();        config.SSID = "\"" + SSID + "\"";        config.priority=0;        config.hiddenSSID = true;        config.wepKeys[0] = "\"" + 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;


            使用第二种方式,连接端,GALAXY 在添加网络的时候,不再返回-1,表示网络添加成功,但是连接网络时一直失败。后来仔细看了一下,按照这样的对应配置,热点创建段提示的安全性是 无,然而连接端提示的是 Wep 方式加密,而且出现两个相同SSID的热点网络,一个是热点创建端的,一个是连接端的,很明显两端的配置虽然一样但是,两端根本就是两个不同的热点配置,当然无法连接,哎,没办法了,自己对网络也是那种菜鸟的,自己根本就不会配置,后来自己想到一个问题,按照第二种方式创建的热点时不加密的,那么我可以用第一种的连接端的配置去连接啊,但是GALAXY 添加网络会一直返回-1,呵呵,突然想到,加上转义字符,有可能会行,然后加上了转义字符:得到自己最终的两端配置如下:

      A 热点创建段


    

         WifiConfiguration config = new WifiConfiguration();        config.allowedAuthAlgorithms.clear();        config.allowedGroupCiphers.clear();        config.allowedKeyManagement.clear();        config.allowedPairwiseCiphers.clear();        config.allowedProtocols.clear();        config.SSID = "" + SSID + "";        config.priority=0;        config.hiddenSSID = true;        config.wepKeys[0] = "" + 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;

      

     B 热点连接端配置

    

    

     WifiConfiguration config = new WifiConfiguration();    config.allowedAuthAlgorithms.clear();    config.allowedGroupCiphers.clear();    config.allowedKeyManagement.clear();    config.allowedPairwiseCiphers.clear();    config.allowedProtocols.clear();    config.SSID = "\"" + SSID + "\"";    config.priority=0;    IsExsits(SSID);    config.wepKeys[0] = "\""+""+"\"";    config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);    config.wepTxKeyIndex = 0;    config.status = WifiConfiguration.Status.ENABLED;

       然后居然就连接成功了,呵呵,连接也很稳定。

       文章开头说到的三种配置方式,1,2种到此,第三种按照1,2中的反向思维进行配置,但是不知道为什么热点还么有创建成功,手机自动重启,而且不是一次两次,只要调用热点创建的代码就会手机重启,是在搞不住。 

至此,我wifi热点的创建连接说到此,后面一些连接成功否检测,Socket通信的内容,等小弟整理好再加进来。希望大家多多指教,才能好好进步


 


             

 

   参考文章:

   Wifi 热点

  http://www.oschina.net/question/207975_79027

 http://bbs.csdn.net/topics/360190048

 http://blog.csdn.net/sasoritattoo/article/details/8285926


 http://stackoverflow.com/questions/15813767/connect-to-wifi-programmaticly-in-google-android

 C 底层源码
  http://www.oschina.net/code/explore/freebsd/contrib/wpa/wpa_supplicant/wps_supplicant.c

 百度空间
  http://hi.baidu.com/backwang/item/1f6df08b9cf936ded1f8cd99




项目下载地址(小弟赚一点积分)


          

          

 



 

原创粉丝点击