接着上一篇wifi的掃描連接等,這一篇主要說一下手機開啓Wifi熱點。
demo的下載地址會在最下面貼出來。
圖片:
1 創建WIFI熱點
經測試開啓wifi熱點(無祕密,wpa安全類型,wpa2安全類型)都可以正常開啓並使用。
需要注意的是wifi和wifi熱點不能同時打開,也就是連接wifi的時候,開啓熱點需要先將wifi關閉纔可以。
用到的主要代碼:
package com.vn.wifitest.utils;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiConfiguration.KeyMgmt;
import android.net.wifi.WifiManager;
import android.os.Handler;
import android.util.Log;
public class WifiAPUtil {
private static final String TAG = "WifiAPUtil";
public final static boolean DEBUG = true;
public static final int MESSAGE_AP_STATE_ENABLED = 1;
public static final int MESSAGE_AP_STATE_FAILED = 2;
//默認wifi祕密
private static final String DEFAULT_AP_PASSWORD = "12345678";
private static WifiAPUtil sInstance;
private static Handler mHandler;
private static Context mContext;
private WifiManager mWifiManager;
//監聽wifi熱點的狀態變化
public static final String WIFI_AP_STATE_CHANGED_ACTION = "android.net.wifi.WIFI_AP_STATE_CHANGED";
public static final String EXTRA_WIFI_AP_STATE = "wifi_state";
public static int WIFI_AP_STATE_DISABLING = 10;
public static int WIFI_AP_STATE_DISABLED = 11;
public static int WIFI_AP_STATE_ENABLING = 12;
public static int WIFI_AP_STATE_ENABLED = 13;
public static int WIFI_AP_STATE_FAILED = 14;
public enum WifiSecurityType {
WIFICIPHER_NOPASS, WIFICIPHER_WPA, WIFICIPHER_WEP, WIFICIPHER_INVALID, WIFICIPHER_WPA2
}
private WifiAPUtil(Context context) {
if(DEBUG) Log.d(TAG,"WifiAPUtils construct");
mContext = context;
mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
IntentFilter filter = new IntentFilter();
filter.addAction(WIFI_AP_STATE_CHANGED_ACTION);
context.registerReceiver(mWifiStateBroadcastReceiver, filter);
}
protected void finalize() {
if(DEBUG) Log.d(TAG,"finalize");
mContext.unregisterReceiver(mWifiStateBroadcastReceiver);
}
public static WifiAPUtil getInstance(Context c) {
if (null == sInstance)
sInstance = new WifiAPUtil(c);
return sInstance;
}
public boolean turnOnWifiAp(String str, String password,WifiSecurityType Type) {
String ssid = str;
//配置熱點信息。
WifiConfiguration wcfg = new WifiConfiguration();
wcfg.SSID = new String(ssid);
wcfg.networkId = 1;
wcfg.allowedAuthAlgorithms.clear();
wcfg.allowedGroupCiphers.clear();
wcfg.allowedKeyManagement.clear();
wcfg.allowedPairwiseCiphers.clear();
wcfg.allowedProtocols.clear();
if(Type == WifiSecurityType.WIFICIPHER_NOPASS) {
if(DEBUG)Log.d(TAG, "wifi ap----no password");
wcfg.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.OPEN, true);
wcfg.wepKeys[0] = "";
wcfg.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
wcfg.wepTxKeyIndex = 0;
} else if(Type == WifiSecurityType.WIFICIPHER_WPA) {
if(DEBUG)Log.d(TAG, "wifi ap----wpa");
//密碼至少8位,否則使用默認密碼
if(null != password && password.length() >= 8){
wcfg.preSharedKey = password;
} else {
wcfg.preSharedKey = DEFAULT_AP_PASSWORD;
}
wcfg.hiddenSSID = false;
wcfg.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.OPEN);
wcfg.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.TKIP);
wcfg.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK);
//wcfg.allowedKeyManagement.set(4);
wcfg.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.TKIP);
wcfg.allowedProtocols.set(WifiConfiguration.Protocol.WPA);
wcfg.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP);
wcfg.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP);
} else if(Type == WifiSecurityType.WIFICIPHER_WPA2) {
if(DEBUG)Log.d(TAG, "wifi ap---- wpa2");
//密碼至少8位,否則使用默認密碼
if(null != password && password.length() >= 8){
wcfg.preSharedKey = password;
} else {
wcfg.preSharedKey = DEFAULT_AP_PASSWORD;
}
wcfg.hiddenSSID = true;
wcfg.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.OPEN);
wcfg.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.TKIP);
wcfg.allowedKeyManagement.set(4);
//wcfg.allowedKeyManagement.set(4);
wcfg.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.TKIP);
wcfg.allowedProtocols.set(WifiConfiguration.Protocol.WPA);
wcfg.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP);
wcfg.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP);
}
try {
Method method = mWifiManager.getClass().getMethod("setWifiApConfiguration",
wcfg.getClass());
Boolean rt = (Boolean)method.invoke(mWifiManager, wcfg);
if(DEBUG) Log.d(TAG, " rt = " + rt);
} catch (NoSuchMethodException e) {
Log.e(TAG, e.getMessage());
} catch (IllegalArgumentException e) {
Log.e(TAG, e.getMessage());
} catch (IllegalAccessException e) {
Log.e(TAG, e.getMessage());
} catch (InvocationTargetException e) {
Log.e(TAG, e.getMessage());
}
return setWifiApEnabled();
}
//獲取熱點狀態
public int getWifiAPState() {
int state = -1;
try {
Method method2 = mWifiManager.getClass().getMethod("getWifiApState");
state = (Integer) method2.invoke(mWifiManager);
} catch (Exception e) {
Log.e(TAG, e.getMessage());
}
if(DEBUG)Log.i("WifiAP", "getWifiAPState.state " + state);
return state;
}
private boolean setWifiApEnabled() {
//開啓wifi熱點需要關閉wifi
while(mWifiManager.getWifiState() != WifiManager.WIFI_STATE_DISABLED){
mWifiManager.setWifiEnabled(false);
try {
Thread.sleep(200);
} catch (Exception e) {
Log.e(TAG, e.getMessage());
return false;
}
}
// 確保wifi 熱點關閉。
while(getWifiAPState() != WIFI_AP_STATE_DISABLED){
try {
Method method1 = mWifiManager.getClass().getMethod("setWifiApEnabled",
WifiConfiguration.class, boolean.class);
method1.invoke(mWifiManager, null, false);
Thread.sleep(200);
} catch (Exception e) {
Log.e(TAG, e.getMessage());
return false;
}
}
//開啓wifi熱點
try {
Method method1 = mWifiManager.getClass().getMethod("setWifiApEnabled",
WifiConfiguration.class, boolean.class);
method1.invoke(mWifiManager, null, true);
Thread.sleep(200);
} catch (Exception e) {
Log.e(TAG, e.getMessage());
return false;
}
return true;
}
//關閉WiFi熱點
public void closeWifiAp() {
if (getWifiAPState() != WIFI_AP_STATE_DISABLED) {
try {
Method method = mWifiManager.getClass().getMethod("getWifiApConfiguration");
method.setAccessible(true);
WifiConfiguration config = (WifiConfiguration) method.invoke(mWifiManager);
Method method2 = mWifiManager.getClass().getMethod("setWifiApEnabled", WifiConfiguration.class, boolean.class);
method2.invoke(mWifiManager, config, false);
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
}
public void regitsterHandler(Handler handler){
mHandler = handler;
}
public void unregitsterHandler(){
mHandler = null;
}
//監聽wifi熱點狀態變化
private BroadcastReceiver mWifiStateBroadcastReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
if(DEBUG)Log.i(TAG,"WifiAPUtils onReceive: "+intent.getAction());
if(WIFI_AP_STATE_CHANGED_ACTION.equals(intent.getAction())) {
int cstate = intent.getIntExtra(EXTRA_WIFI_AP_STATE, -1);
if(cstate == WIFI_AP_STATE_ENABLED) {
if(mHandler != null){
mHandler.sendEmptyMessage(MESSAGE_AP_STATE_ENABLED);
}
}if(cstate == WIFI_AP_STATE_DISABLED || cstate == WIFI_AP_STATE_FAILED) {
if(mHandler != null)
mHandler.sendEmptyMessage(MESSAGE_AP_STATE_FAILED);
}
}
}
};
//獲取熱點ssid
public String getValidApSsid() {
try {
Method method = mWifiManager.getClass().getMethod("getWifiApConfiguration");
WifiConfiguration configuration = (WifiConfiguration)method.invoke(mWifiManager);
return configuration.SSID;
} catch (Exception e) {
Log.e(TAG, e.getMessage());
return null;
}
}
//獲取熱點密碼
public String getValidPassword(){
try {
Method method = mWifiManager.getClass().getMethod("getWifiApConfiguration");
WifiConfiguration configuration = (WifiConfiguration)method.invoke(mWifiManager);
return configuration.preSharedKey;
} catch (Exception e) {
Log.e(TAG, e.getMessage());
return null;
}
}
//獲取熱點安全類型
public int getValidSecurity(){
WifiConfiguration configuration;
try {
Method method = mWifiManager.getClass().getMethod("getWifiApConfiguration");
configuration = (WifiConfiguration)method.invoke(mWifiManager);
} catch (Exception e) {
Log.e(TAG, e.getMessage());
return WifiSecurityType.WIFICIPHER_INVALID.ordinal();
}
if(DEBUG)Log.i(TAG,"getSecurity security="+configuration.allowedKeyManagement);
if(configuration.allowedKeyManagement.get(KeyMgmt.NONE)) {
return WifiSecurityType.WIFICIPHER_NOPASS.ordinal();
}else if(configuration.allowedKeyManagement.get(KeyMgmt.WPA_PSK)) {
return WifiSecurityType.WIFICIPHER_WPA.ordinal();
}else if(configuration.allowedKeyManagement.get(4)) { //4 means WPA2_PSK
return WifiSecurityType.WIFICIPHER_WPA2.ordinal();
}
return WifiSecurityType.WIFICIPHER_INVALID.ordinal();
}
}
使用方法:
Activity生命週期中
//初始化WifiAPUtil類
WifiAPUtil.getInstance(getApplicationContext())
//註冊handler
WifiAPUtil.getInstance(this).regitsterHandler(mHandler);
//接收message,做處理
private Handler mHandler = new Handler(){
public void handleMessage(Message msg) {
switch (msg.what) {
case WifiAPUtil.MESSAGE_AP_STATE_ENABLED:
String ssid = WifiAPUtil.getInstance(WifiApActivity.this).getValidApSsid();
String pw = WifiAPUtil.getInstance(WifiApActivity.this).getValidPassword();
int security = WifiAPUtil.getInstance(WifiApActivity.this).getValidSecurity();
mWifiApState.setText("wifi熱點開啓成功"+"\n"
+"SSID = "+ssid+"\n"
+"Password = "+pw +"\n"
+"Security = "+security);
break;
case WifiAPUtil.MESSAGE_AP_STATE_FAILED:
mWifiApState.setText("wifi熱點關閉");
break;
default:
break;
}
}
};
在activity銷燬的時候@Override
protected void onDestroy() {
super.onDestroy();
WifiAPUtil.getInstance(this).unregitsterHandler();
}
添加點擊事件//開啓wifi熱點
WifiAPUtil.getInstance(WifiApActivity.this).turnOnWifiAp(ssid, password, mWifiType);
//關閉wifi熱點
WifiAPUtil.getInstance(WifiApActivity.this).closeWifiAp();
2 監聽熱點的狀態
當wifi熱點狀態發送變化,系統會發送廣播 android.net.wifi.WIFI_AP_STATE_CHANGED,所以我們只要註冊監聽這個廣播就可以了。
wifi ap狀態值。
public static final String EXTRA_WIFI_AP_STATE = "wifi_state";
public static int WIFI_AP_STATE_DISABLING = 10;
public static int WIFI_AP_STATE_DISABLED = 11;
public static int WIFI_AP_STATE_ENABLING = 12;
public static int WIFI_AP_STATE_ENABLED = 13;
public static int WIFI_AP_STATE_FAILED = 14;
動態註冊public static final String WIFI_AP_STATE_CHANGED_ACTION = "android.net.wifi.WIFI_AP_STATE_CHANGED";
//註冊廣播接收者
IntentFilter filter = new IntentFilter();
filter.addAction(WIFI_AP_STATE_CHANGED_ACTION);
context.registerReceiver(mWifiStateBroadcastReceiver, filter);
廣播接收者通過監聽wifiap狀態的變化,發送消息給相關activity
//監聽wifi熱點狀態變化
private BroadcastReceiver mWifiStateBroadcastReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
if(DEBUG)Log.i(TAG,"WifiAPUtils onReceive: "+intent.getAction());
if(WIFI_AP_STATE_CHANGED_ACTION.equals(intent.getAction())) {
int cstate = intent.getIntExtra(EXTRA_WIFI_AP_STATE, -1);
if(cstate == WIFI_AP_STATE_ENABLED) {
if(mHandler != null){
mHandler.sendEmptyMessage(MESSAGE_AP_STATE_ENABLED);
}
}if(cstate == WIFI_AP_STATE_DISABLED || cstate == WIFI_AP_STATE_FAILED) {
if(mHandler != null)
mHandler.sendEmptyMessage(MESSAGE_AP_STATE_FAILED);
}
}
}
};
3 遺留問題
在配置wificonfiguration的時候有過屬性是hiddenSSID,這個是設置wifi熱點AP是否隱藏的,
但是設置wcfg.hiddenSSID = true或false並沒有發現有什麼不同,按理說設置爲true,ssid隱藏應該搜索不到這個熱點,
但是都可以搜索到。還請知道的可以留言指教,十分感謝。
之前有朋友說5.0系統的開啓熱點有問題,我這裏沒有5.0的手機,使用華爲p9Android6.0手機測試確實開啓不了熱點,需要添加write_settings,添加上此權限就可以成功開啓了。
DEMO下載