1 需求
通過用戶名和密碼連接指定wifi熱點,網上的代碼亂七八糟,沒幾個可以用,我這邊整理了下,測試了華爲Android9.0和小米Android9.0和10.0和OPPO Android9.0 都沒問題,直接回調結果就行。
2 問題
在Android10.0手機上
mWifiManager.addNetwork(wifiNewConfiguration);
返回-1
說明不能用這種方式了,
android Q或者更高的版本,這個方法始終返回-1,去看下官網:Android 10 的新方案如下連接:https://developer.android.google.cn/guide/topics/connectivity/wifi-bootstrap
3 代碼實現
/**
* 創建 WifiConfiguration,這裏創建的是wpa2加密方式的wifi
*
* @param ssid wifi賬號
* @param password wifi密碼
* @return
*/
public static WifiConfiguration createWifiInfo(String ssid, String password) {
WifiConfiguration config = new WifiConfiguration();
config.allowedAuthAlgorithms.clear();
config.allowedGroupCiphers.clear();
config.allowedKeyManagement.clear();
config.allowedPairwiseCiphers.clear();
config.allowedProtocols.clear();
config.SSID = "\"" + ssid + "\"";
config.preSharedKey = "\"" + password + "\"";
config.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.OPEN);
config.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.TKIP);
config.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP);
config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK);
config.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.TKIP);
config.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP);
config.allowedProtocols.set(WifiConfiguration.Protocol.RSN);
config.allowedProtocols.set(WifiConfiguration.Protocol.WPA);
config.status = WifiConfiguration.Status.ENABLED;
return config;
}
public static boolean connectWifiApByName(Context context, String wifiApName, String password) {
WifiManager mWifiManager = (WifiManager) context.getSystemService(WIFI_SERVICE);
WifiConfiguration wifiNewConfiguration = createWifiInfo(wifiApName, password);//使用wpa2的wifi加密方式
int newNetworkId = mWifiManager.addNetwork(wifiNewConfiguration);
if (newNetworkId == -1) {
Log.e(TAG, "操作失敗,需要您到手機wifi列表中取消對設備連接的保存");
return false;
}
Log.i(TAG, "newNetworkId is:" + newNetworkId);
// 如果wifi權限沒打開(1、先打開wifi,2,使用指定的wifi
if(!mWifiManager.isWifiEnabled()){
mWifiManager.setWifiEnabled(true);
}
boolean enableNetwork = mWifiManager.enableNetwork(newNetworkId, true);
if (!enableNetwork) {
Log.e(TAG, "切換到指定wifi失敗");
return false;
} else {
Log.e(TAG, "切換到指定wifi成功");
return true;
}
}
public interface CallBack {
void connnectResult(boolean connectResult);
}
/**
* 通過熱點用戶名和密碼連接熱點
* @param context
* @param wifiApName
* @param password
* @param handler
*/
public static void connectWifiApByNameAndPwd(Context context, String wifiApName, String password, CallBack callBack) {
if (context == null || callBack == null) {
Log.i(TAG, "context == null || callBack == null");
return;
}
WifiManager mWifiManager = (WifiManager) context.getSystemService(WIFI_SERVICE);
//Andorid10.以下
if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.Q) {
WifiConfiguration wifiNewConfiguration = createWifiInfo(wifiApName, password);//使用wpa2的wifi加密方式
int newNetworkId = mWifiManager.addNetwork(wifiNewConfiguration);
if (newNetworkId == -1) {
Log.i(TAG, "操作失敗,需要您到手機wifi列表中取消對設備連接的保存");
callBack.connnectResult(false);
return;
}
Log.i(TAG, "newNetworkId is:" + newNetworkId);
// 如果wifi權限沒打開(1、先打開wifi,2,使用指定的wifi
if (!mWifiManager.isWifiEnabled()) {
mWifiManager.setWifiEnabled(true);
}
boolean enableNetwork = mWifiManager.enableNetwork(newNetworkId, true);
if (!enableNetwork) {
Log.i(TAG, "切換到指定wifi失敗");
callBack.connnectResult(false);
return;
}
Log.i(TAG, "切換到指定wifi成功");
callBack.connnectResult(true);
} else {
boolean isOpenWifi = mWifiManager.isWifiEnabled();
if (!isOpenWifi) {
Log.i(TAG, "用戶需要打開wifi開關");
context.startActivity(new Intent(Settings.Panel.ACTION_INTERNET_CONNECTIVITY));
callBack.connnectResult(false);
return;
}
NetworkSpecifier specifier =
new WifiNetworkSpecifier.Builder()
.setSsidPattern(new PatternMatcher(wifiApName, PatternMatcher.PATTERN_PREFIX))
.setWpa2Passphrase(password)
.build();
NetworkRequest request =
new NetworkRequest.Builder()
.addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
.removeCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
.setNetworkSpecifier(specifier)
.build();
ConnectivityManager connectivityManager = (ConnectivityManager)
context.getSystemService(Context.CONNECTIVITY_SERVICE);
ConnectivityManager.NetworkCallback networkCallback = new ConnectivityManager.NetworkCallback() {
@Override
public void onAvailable(Network network) {
// do success processing here..
Log.i(TAG, "onAvailable success");
Log.i(TAG, "network" + network.toString());
callBack.connnectResult(true);
}
@Override
public void onUnavailable() {
// do failure processing here..
Log.i(TAG, "onUnavailable fail");
callBack.connnectResult(false);
}
};
connectivityManager.requestNetwork(request, networkCallback);
}
}
connectWifiApByName函數只針對小於等於android 9.0,不能兼容android 10.0,所以connectWifiApByNameAndPwd這個函數支持所有版本類型
調用如下
WifiApUtil.connectWifiApByNameAndPwd(this, name, password, object : WifiApUtil.CallBack {
override fun connnectResult(connectResult: Boolean) {
Log.i(TAG, "connectResult is:" + connectResult)
}
});//
4 需要注意的地方
Andorid 10.0連接指定熱點,需要先把wifi需要打開,不然沒反應,沒有回調,我們上面的代碼在Android9.0以下連接指定熱點之前,我們是通過下面的函數打開wifi
if (!mWifiManager.isWifiEnabled()) {
mWifiManager.setWifiEnabled(true);
}
在10.版本,isWifiEnabled()這個函數是生效的,但是setWifiEnabled(true)這個函數是失敗的,沒有效果,我們如果發現沒有打開wifi,我們可以再連接之前進行引導用戶打開,我們可以跳到設置面板提示用戶啓用和禁用 Wi-Fi
startActivity(Intent(Settings.Panel.ACTION_INTERNET_CONNECTIVITY))