在上一篇文章《Android开发实践:WIFI扫描功能的封装》介绍了如何利用Andriod的API实现WIFI的扫描,本文则重点讲述一下如何连接WIFI吧,在此,也给出一个封装WIFI连接过程的类,提供简单的接口以供在各个代码工程中复用。
与WIFI扫描类似,WIFI的连接同样是一个耗时的过程,所以需要放到线程中执行,通过回调来通知调用者连接结果。该回调接口的定义如下:
public interface WifiConnectListener { public void OnWifiConnectCompleted( boolean isConnected ); }
从Android的WIFI Setting可以看出,一般添加一个新的WIFI连接,需要给出三个信息,一个是WIFI的SSID,一个是WIFI的密码,另一个是WIFI的加密类型,不同的加密方式,连接时程序中的配置是不同的,这里定义一个枚举,给出四种常见的加密类型:
public enum SecurityMode { OPEN, WEP, WPA, WPA2 }
Android的WIFI连接过程,总体上分为三步,第一步,添加网络配置,第二步,根据网络配置连接WIFI,第三步,监听系统的WIFI连接状态消息。下面就直接给出示例代码,关键的地方都在代码中注释了。
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 Context mContext; private WifiManager mWifiManager; private Lock mLock; private Condition mCondition; private WiFiConncetReceiver mWifiConnectReceiver; private WifiConnectListener mWifiConnectListener; 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( Context context , WifiConnectListener listener ) { mContext = context; mLock = new ReentrantLock(); mCondition = mLock.newCondition(); mWifiManager=(WifiManager)mContext.getSystemService(Context.WIFI_SERVICE); mWifiConnectReceiver = new WiFiConncetReceiver(); mWifiConnectListener = listener; } public void connect( final String ssid, final String password, final SecurityMode mode ) { 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( String ssid, String password, SecurityMode mode ) { //添加新的网络配置 WifiConfiguration cfg = 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 (InterruptedException e) { e.printStackTrace(); } mLock.unlock(); return mIsConnnected; } //监听系统的WIFI连接消息 protected class WiFiConncetReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { if (!WifiManager.SUPPLICANT_STATE_CHANGED_ACTION.equals(intent.getAction())) { return; } mLock.lock(); WifiInfo info = 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文件中记得添加权限支持哦:
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE"></uses-permission> <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"></uses-permission> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"></uses-permission>
这个WIFI连接类的封装就分享到这里啦,希望对初学者有帮助,java文件见博文后面的附件,有任何疑问欢迎留言或者来信lujun.hust@gmail.com交流。
本文出自 “对影成三人” 博客,请务必保留此出处http://ticktick.blog.51cto.com/823160/1410080