现在的位置: 首页 > 综合 > 正文

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

2013年10月30日 ⁄ 综合 ⁄ 共 15804字 ⁄ 字号 评论关闭

               参考网上的很多的资料,初步实现了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

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

          

          

 

 

抱歉!评论已关闭.