Android开发实践:WIFI连接功能的封装
与WIFI扫描类似,WIFI的连接同样是一个耗时的过程,所以需要放到线程中执行,通过回调来通知调用者连接结果。该回调接口的定义如下: 1 2 3 public interface WifiConnectListener{ public void OnWifiConnectCompleted( boolean isConnected); } 从Android的WIFI Setting可以看出,一般添加一个新的WIFI连接,需要给出三个信息,一个是WIFI的SSID,一个是WIFI的密码,另一个是WIFI的加密类型,不同的加密方式,连接时程序中的配置是不同的,这里定义一个枚举,给出四种常见的加密类型: 1 2 3 public enum SecurityMode{ OPEN,WEP,WPA,WPA2 } Android的WIFI连接过程,总体上分为三步,第一步,添加网络配置,第二步,根据网络配置连接WIFI,第三步,监听系统的WIFI连接状态消息。下面就直接给出示例代码,关键的地方都在代码中注释了。 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 package com.example.testwifi; import java.util.List; import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.net.wifi.SupplicantState; import android.net.wifi.WifiConfiguration; import android.net.wifi.WifiInfo; import android.net.wifi.WifiManager; public class WifiConnector{ private static final int WIFI_CONNECT_TIMEOUT= 20 ; //连接WIFI的超时时间 private ContextmContext; private WifiManagermWifiManager; private LockmLock; private ConditionmCondition; private WiFiConncetReceivermWifiConnectReceiver; private WifiConnectListenermWifiConnectListener; private boolean mIsConnnected= false ; private int mNetworkID=- 1 ; //网络加密模式 public enum SecurityMode{ OPEN,WEP,WPA,WPA2 } //通知连接结果的监听接口 public interface WifiConnectListener{ public void OnWifiConnectCompleted( boolean isConnected); } public WifiConnector(Contextcontext,WifiConnectListenerlistener){ mContext=context; mLock= new ReentrantLock(); mCondition=mLock.newCondition(); mWifiManager=(WifiManager)mContext.getSystemService(Context.WIFI_SERVICE); mWifiConnectReceiver= new WiFiConncetReceiver(); mWifiConnectListener=listener; } public void connect( final Stringssid, final Stringpassword, final SecurityModemode){ new Thread( new Runnable(){ @Override public void run(){ //如果WIFI没有打开,则打开WIFI if (!mWifiManager.isWifiEnabled()){ mWifiManager.setWifiEnabled( true ); } //注册连接结果监听对象 mContext.registerReceiver(mWifiConnectReceiver, new IntentFilter(WifiManager.SUPPLICANT_STATE_CHANGED_ACTION)); //连接指定SSID if (!onConnect(ssid,password,mode)){ mWifiConnectListener.OnWifiConnectCompleted( false ); } else { mWifiConnectListener.OnWifiConnectCompleted( true ); } //删除注册的监听类对象 mContext.unregisterReceiver(mWifiConnectReceiver); } }).start(); } protected boolean onConnect(Stringssid,Stringpassword,SecurityModemode){ //添加新的网络配置 WifiConfigurationcfg= new WifiConfiguration(); cfg.SSID= "\"" +ssid+ "\"" ; if (password!= null &&! "" .equals(password)){ //这里比较关键,如果是WEP加密方式的网络,密码需要放到cfg.wepKeys[0]里面 if (mode==SecurityMode.WEP){ cfg.wepKeys[ 0 ]= "\"" +password+ "\"" ; cfg.wepTxKeyIndex= 0 ; } else { cfg.preSharedKey= "\"" +password+ "\"" ; } } cfg.status=WifiConfiguration.Status.ENABLED; //添加网络配置 mNetworkID=mWifiManager.addNetwork(cfg); mLock.lock(); mIsConnnected= false ; //连接该网络 if (!mWifiManager.enableNetwork(mNetworkID, true )){ mLock.unlock(); return false ; } try { //等待连接结果 mCondition.await(WIFI_CONNECT_TIMEOUT,TimeUnit.SECONDS); } catch (InterruptedExceptione){ e.printStackTrace(); } mLock.unlock(); return mIsConnnected; } //监听系统的WIFI连接消息 protected class WiFiConncetReceiver extends BroadcastReceiver{ @Override public void onReceive(Contextcontext,Intentintent){ if (!WifiManager.SUPPLICANT_STATE_CHANGED_ACTION.equals(intent.getAction())){ return ; } mLock.lock(); WifiInfoinfo=mWifiManager.getConnectionInfo(); if (info.getNetworkId()==mNetworkID&&info.getSupplicantState()==SupplicantState.COMPLETED){ mIsConnnected= true ; mCondition.signalAll(); } mLock.unlock(); } } } 与WIFI扫描的封装代码类似,这里也用到了Lock和Condition,就是为了阻塞地等待WIFI连接的结果,保证正确的registerReceiver和unregisterReceiver网络连接状态监听对象,同时,设置了WIFI连接超时,防止由于WIFI模块的问题导致界面收不到回调而长时间“卡死”。 另外,AndroidManifest.xml文件中记得添加权限支持哦: 1 2 3 <uses-permissionandroid:name= "android.permission.CHANGE_WIFI_STATE" ></uses-permission> <uses-permissionandroid:name= "android.permission.ACCESS_WIFI_STATE" ></uses-permission> <uses-permissionandroid:name= "android.permission.ACCESS_NETWORK_STATE" ></uses-permission> 本文转自 Jhuster 51CTO博客,原文链接:http://blog.51cto.com/ticktick/1410080,如需转载请自行联系原作者