参考网上的很多的资料,初步实现了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,呵呵,突然想到,加上转义字符,有可能会行,然后加上了转义字符:得到自己最终的两端配置如下:
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://stackoverflow.com/questions/15813767/connect-to-wifi-programmaticly-in-google-android
C 底层源码