最近在開發手機短距離傳輸有關的產品,由於藍牙傳輸速率有限,採用的是wifi熱點的方式。
1.WIFI熱點的操作需要以下權限:
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/>
<uses-permission android:name="android.permission.WRITE_SETTINGS"/>
2.WIFI熱點的打開
分爲三個階段:1 android 7.0及以前 可以用動態代碼的方法設置wifi熱點並打開。
2. android7.1~android8.0以前 用之前的方法打開後,打開wifi熱點端的IP地址卻無法分配,導致無法連接到該wifi熱點,即打開無效。看某些應用的處理方法爲跳轉到設置界面提示用戶自己進行手動打開。 但因此無法獲得wifi熱點的密碼。
網上有通過startTethering方法動態打開wifi熱點的方法,但該方法爲系統方法,無法通過反射進行調用,於是採用修改ConnectivityManager源碼,將TETHERING_WIFI字段、startTethering方法及OnStartTetheringCallback類中隱藏相關的標誌去掉,然後單獨編譯一個jar包。最後將jar包拷貝到工程中的方法。但個人水平有限,無法進行驗證。
3.android8.0 可以通過打開wifi熱點,並在其回調函數中獲取wifi熱點名稱和wifi熱點密碼,但該wifi熱點名稱和密碼都是隨機的,無法在打開wifi熱點前知道,而且每次打開都會變化。
以下爲最常用方法:(可設置無密碼,WPA_EAP,WPA2_PSK三種安全方式,以下爲WPA2_PSK方式)
public void createWifitHot(String name, String password) {
try {
//wifi和熱點不能同時打開,所以先判斷wifi是否打開,打開則關閉
if (mWifiManager.isWifiEnabled()) {
mWifiManager.setWifiEnabled(false);
}
//java反射機制得到Method
Method method = mWifiManager.getClass().getMethod("setWifiApEnabled", WifiConfiguration.class, boolean.class);
//配置熱點信息
WifiConfiguration config = new WifiConfiguration();
config.SSID = name;
config.preSharedKey = password;
config.hiddenSSID = true;
config.status = WifiConfiguration.Status.ENABLED;
config.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.TKIP);
config.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP);
config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA2_PSK);
config.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.TKIP);
config.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP);
//通過java反射調用WifiManager的setWifiApEnabled方法
method.invoke(mWifiManager, config, true);
} catch (Exception e) {
e.printStackTrace();
}
}
以下爲隨機方法:
WifiManager manager = (WifiManager) getApplicationContext().getSystemService(Context.WIFI_SERVICE);
//cancelLocalOnlyHotspotRequest 是關閉熱點
//打開熱點
manager.startLocalOnlyHotspot(new WifiManager.LocalOnlyHotspotCallback(){
@Override
public void onStarted(WifiManager.LocalOnlyHotspotReservation reservation) {
super.onStarted(reservation);
Log.d(TAG, "Wifi Hotspot is on now");
}
@Override
public void onStopped() {
super.onStopped();
Log.d(TAG, "onStopped: ");
}
@Override
public void onFailed(int reason) {
super.onFailed(reason);
Log.d(TAG, "onFailed: ");
}
},new Handler());
關閉WIFI熱點方法如下:
public void closeWifiHotspot() {
try {
Method method = wifiManager.getClass().getMethod("getWifiApConfiguration");
method.setAccessible(true);
WifiConfiguration config = (WifiConfiguration) method.invoke(wifiManager);
Method method2 = wifiManager.getClass().getMethod("setWifiApEnabled", WifiConfiguration.class, boolean.class);
method2.invoke(wifiManager, config, false);
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
至於WIFI熱點連接時,如果WIFI連接斷開,沒有找到 有效的回調方法。只能過段時間查詢一次狀態判斷是否仍在連接。
3.WIFI熱點的IP地址
R 熱點的IP地址可通過以下方法獲取,但連接設備的IP地址無法獲取。我採用的方法是設備連接後通過UDP向wifi熱點發送數據包,wifi熱點在接收到數據包時通過DatagramPacket的getAddress和getPort獲得該設備的IP地址及端口號。
public String getIpAddressFromHotspot(){
// WifiAP ip address is hardcoded in Android.
/* IP/netmask: 192.168.43.1/255.255.255.0 */
String ipAddress = "192.168.43.1";
DhcpInfo dhcpInfo = mWifiManager.getDhcpInfo();
int address = dhcpInfo.gateway;
ipAddress = ((address & 0xFF)
+ "." + ((address >> 8) & 0xFF)
+ "." + ((address >> 16) & 0xFF)
+ "." + ((address >> 24) & 0xFF));
return ipAddress;
}
DatagramPacket receivePacket = new DatagramPacket(receiveData, receiveData.length);
mDatagramSocket.receive(receivePacket);
InetAddress inetAddress = receivePacket.getAddress();
int port = receivePacket.getPort();