** 前言:早在去年,我曾寫過一個針對android6.0連接配接指定WiFi的文章。雖然能成功連接配接,但有好多不合理甚至錯誤的地方,是以現在對那篇文章進行重新編輯釋出**。
最近項目中有通過已知WiFi名稱和密碼連接配接傳感器WiFi,實作資料交換的需求。在網上找了許多資料發現都是複制黏貼,也有好多bug,現在我将其整理封裝并在項目中使用。
github位址:https://github.com/tangjiang24/WifiConnector
用法
step1
在根build.gradle中添加:
allprojects {
repositories {
maven { url "https://jitpack.io" }
}
}
在使用的子產品build.gradle中添加:
dependencies {
implementation 'com.github.tangjiang24:WifiConnector:Tag'
}
(請替換 Tag 為最新的版本号: img)
Step2
分兩種方法:
第一種:
1.将需要連接配接的activity繼承 庫中的 WifiActivity :
public class WifiConnectActivity extends WifiActivity{}
2.直接調用父類中的 connectWifi(String ssid, String pwd, int type) 方法:
connectWifi(String ssid,String pwd,int type);
3.重寫連接配接失敗成功的抽象方法即可:
@Override
public void onConnectWifiSucess() {
ToastUtil.showShortToast(this,"連接配接成功!!");
}
@Override
public void onConnectWifiFail(String failMsg) {
ToastUtil.showShortToast(this,failMsg);
}
第二種:
1.建構WifiConnector對象
WifiConnector connector = new WifiConnector(context);
2.調用其connectWifi () 方法,并在回調中寫成功或者失敗後的邏輯
connector.connectWifi(ssid, pwd, WifiUtil.TYPE_WPA, new WifiConnector.WifiConnectCallBack() {
@Override
public void onConnectSucess() {
Toast.makeText(WifiConnectActivity.this,"連接配接成功!!",Toast.LENGTH_SHORT).show();
}
@Override
public void onConnectFail(String msg) {
Toast.makeText(WifiConnectActivity.this,msg,Toast.LENGTH_SHORT).show();
}
});
參數說明:
參數名 類型 意義
ssid String WiFi名稱
pwd String WiFi 密碼
type int 密碼類型
wifiConnectCallBack WifiConnectCallBack 連接配接回調
三種密碼類型:
WifiUtil.TYPE_NO_PWD(無密碼)
WifiUtil.TYPE_WEB (WEB)
WifiUtil.TYPE_WPA(WPA)
注意:由于Java的單繼承性,第一種方法有很大的局限,建議使用第二種方法。
原理:
1.判斷目前手機wifi網絡是否開啟可用;
開啟WiFi代碼:
public boolean openWifi() {
boolean sucess = true;
if(!this.mWifiManager.isWifiEnabled()) {
sucess = this.mWifiManager.setWifiEnabled(true);
}
return sucess;
}
開啟WiFi一般需要一定的時間,是以不能立馬去連接配接,需要等WiFi穩定可用,經測試一般2.5秒即可完成,是以我們每隔100毫秒就去判斷WiFi是否可用,代碼如下:
if(!this.openWifi()) {
return false;
} else {
long timeMills = System.currentTimeMillis();
while(this.mWifiManager.getWifiState() != 3) {
try {
if(System.currentTimeMillis() - timeMills > 2500L) {
break;
}
Thread.sleep(100L);
} catch (InterruptedException var8) {
var8.printStackTrace();
}
}
2.根據WiFi名稱,擷取/建立WifiConfiguration;
首先我們需要判斷是否包含有目前WiFi名稱的WifiConfiguration,若包含則試着将其删除再添加。1.為什麼是試着删除?因為在android6.0以上,隻允許删除由本應用建立的wificonfiguratin,不能改變删除其他應用所建立的。 2.為什麼不直接連接配接而要删除再添加?因為wificonfiguratin不一定是連接配接成功後的wificonfiguratin,也有可能是手殘輸錯了密碼,這樣直接去連接配接會導緻一輩子也連接配接不上。
具體代碼如下:
private WifiConfiguration createWifiInfo(String SSID, String Password, int 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);
List<WifiConfiguration> beforeConfig = this.mWifiManager.getConfiguredNetworks();
if(tempConfig != null) {
this.removeWifi(tempConfig.networkId);
}
List<WifiConfiguration> afterConfig = this.mWifiManager.getConfiguredNetworks();
if(tempConfig != null && beforeConfig.size() == afterConfig.size()) {
return tempConfig;
} else {
if(Type == 1) {
config.allowedKeyManagement.set(0);
}
if(Type == 2) {
config.hiddenSSID = true;
config.wepKeys[0] = "\"" + Password + "\"";
config.allowedAuthAlgorithms.set(1);
config.allowedGroupCiphers.set(3);
config.allowedGroupCiphers.set(2);
config.allowedGroupCiphers.set(0);
config.allowedGroupCiphers.set(1);
config.allowedKeyManagement.set(0);
config.wepTxKeyIndex = 0;
}
if(Type == 3) {
config.preSharedKey = "\"" + Password + "\"";
config.hiddenSSID = true;
config.allowedAuthAlgorithms.set(0);
config.allowedGroupCiphers.set(2);
config.allowedKeyManagement.set(1);
config.allowedPairwiseCiphers.set(1);
config.allowedGroupCiphers.set(3);
config.allowedPairwiseCiphers.set(2);
config.status = 2;
}
return config;
}
}
3.注冊網絡變化的廣播,當監聽到網絡連接配接上時,判斷目前WiFi網絡的名稱是否和目标WiFi的一緻;
廣播中主要代碼:
NetworkInfo info = (NetworkInfo)intent.getParcelableExtra("networkInfo");
Log.i("wifi:", "接受到網絡連接配接變化的廣播,目前網絡狀态為:" + info.getState());
if(info.getState().equals(State.CONNECTED)) {
WifiManager wifiManager = (WifiManager)context.getSystemService("wifi");
WifiInfo wifiInfo = wifiManager.getConnectionInfo();
String ssid = wifiInfo.getSSID();
Log.i("wifi:", "接受到網絡連接配接變化的廣播,已連接配接的網絡的ssid=" + ssid);
this.mListner.isConnectMyWifi(ssid);
}
public void setOnWifiConnetListner(WifiConnectReceiver.onWifiConnectListner listner) {
this.mListner = listner;
}
public interface onWifiConnectListner {
void isConnectMyWifi(String var1);
}
activity中實作receiver中聲明的接口onWifiConnectListner,主要代碼:
public void isConnectMyWifi(String s) {
if(!TextUtils.isEmpty(this.ssid)) {
if(s.equals("\"" + this.ssid + "\"")) {
this.handler.removeMessages(1);
this.handler.removeMessages(2);
this.handler.sendEmptyMessageDelayed(1, 1000L);
} else {
Log.i("wifi:", "未連接配接到指定網絡!");
this.sendFailMessage("未連接配接到指定網絡!", 1L);
}
}
}
private void registWifiConnectReceiver() {
if(!this.mReceiverTag) {
this.wifiConnectReceiver = new WifiConnectReceiver();
this.mReceiverTag = true;
this.wifiConnectReceiver.setOnWifiConnetListner(this);
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction("android.net.wifi.STATE_CHANGE");
this.registerReceiver(this.wifiConnectReceiver, intentFilter);
}
總結及注意點:
1.開啟WiFi時需要時間的,必須等穩定後再去連接配接;
2.手機中儲存的wificonfiguratin不一定可用,連接配接時需要先删除再添加;
3.在6.0以後調用mWifiManager.removeNetwork(netId)隻對本應用添加的有效;
config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);