参考网上的很多的资料,初步实现了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_NOPASS
- config.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_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;
- }
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熱點需要關閉Wifi
- if (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 block
- e.printStackTrace();
- } catch (IllegalArgumentException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- } catch (IllegalAccessException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- } catch (InvocationTargetException e) {
- // TODO Auto-generated catch block
- e.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;
-
- }
-
- @Override
- public 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() {
- @Override
- public 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_NOPASS
-
- config.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