Android熱點(diǎn)相關(guān)知識(shí)整理

1. Android開啟熱點(diǎn)的API

Android 8.0及以上,Android官方提供了開啟熱點(diǎn)的API

wifiManager.startLocalOnlyHotspot(new WifiManager.LocalOnlyHotspotCallback(){
                        @Override
                        public void onStarted(WifiManager.LocalOnlyHotspotReservation reservation) {
                            super.onStarted(reservation);
                            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                                Log.i(TAG, "Wifi Hotspot is on now, " + reservation.getWifiConfiguration().SSID);
                                Log.i(TAG, "Wifi Hotspot is on now, " + reservation.getWifiConfiguration().preSharedKey);
                            }
                        }

                        @Override
                        public void onStopped() {
                            super.onStopped();
                            Log.i(TAG, "onStopped: ");
                        }

                        @Override
                        public void onFailed(int reason) {
                            super.onFailed(reason);
                            Log.i(TAG, "onFailed: ");
                        }
                    }, new Handler());
05-21 20:37:18.517 18966-18966/com.gnet.rxjavademo I/hotspot: Wifi Hotspot is on now, AndroidShare_6819
05-21 20:37:18.517 18966-18966/com.gnet.rxjavademo I/hotspot: Wifi Hotspot is on now, a329a61ae014

該API生成的熱點(diǎn)名稱和密碼都是隨機(jī)的字符串,也就是一次性的,回調(diào)中可以獲取到SSID和preSharedKey(就是密碼)。而且要注意以下兩點(diǎn):

  • 1、需要網(wǎng)絡(luò)權(quán)限和定位權(quán)限(這點(diǎn)有點(diǎn)想不通)
int granted = ContextCompat.checkSelfPermission(this, Manifest.permission_group.LOCATION);
        if (granted == PackageManager.PERMISSION_DENIED) {
            ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_COARSE_LOCATION}, 0x11);
        }

<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
  • 2、這個(gè)熱點(diǎn)是不能訪問外網(wǎng)的,只能是局域網(wǎng)內(nèi)使用,所以沒啥太大的用處。
  • 3、保持這個(gè)熱點(diǎn)的引用是有生命周期,我自己的例子中是局部變量,wifiManager是Actvity的一個(gè)私有屬性,當(dāng)擁有該wifiManager的Activity被Destroy時(shí),當(dāng)前創(chuàng)建的這個(gè)本地?zé)狳c(diǎn)也會(huì)自動(dòng)關(guān)閉。因此,需要將這個(gè)wifiMananger放在生命周期更長的類中。

綜上,在Android 8.0上,沒有開啟可訪問互聯(lián)網(wǎng)的手機(jī)熱點(diǎn)的方法。

2. 獲取熱點(diǎn)開關(guān)狀態(tài):

Android的API是隱藏的,不能直接用,這里只能用反射的方式來獲取熱點(diǎn)開啟狀態(tài)

/**
     * 判斷熱點(diǎn)是否開啟
     * @param context
     * @return
     */
    public static boolean isWifiApOpen(Context context) {
        try {
            WifiManager manager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
            //通過放射獲取 getWifiApState()方法
            Method method = manager.getClass().getDeclaredMethod("getWifiApState");
            //調(diào)用getWifiApState() ,獲取返回值
            int state = (int) method.invoke(manager);
            //通過放射獲取 WIFI_AP的開啟狀態(tài)屬性
            Field field = manager.getClass().getDeclaredField("WIFI_AP_STATE_ENABLED");
            //獲取屬性值
            int value = (int) field.get(manager);
            //判斷是否開啟
            if (state == value) {
                return true;
            } else {
                return false;
            }
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        }
        return false;
    }

3. 獲取當(dāng)前熱點(diǎn)的名稱:

獲取熱點(diǎn)名稱的API也是別隱藏了,通過反射的方式獲取。但是,Android 8.0以上,即使通過反射的方式也是獲取不到的,代碼運(yùn)行時(shí)會(huì)報(bào)SecurityException,后面會(huì)說Android 8.0上的處理方法。

public static String getWiFiApSSID(Context context) {
        String ssid = "";
        // Android 8 及以上無法獲取到ssid
        if (Build.VERSION.SDK_INT < 26) {
            try {
                WifiManager manager = (WifiManager) context.getApplicationContext().getSystemService(Context.WIFI_SERVICE);
                //拿到getWifiApConfiguration()方法
                Method method = manager.getClass().getDeclaredMethod("getWifiApConfiguration");
                //調(diào)用getWifiApConfiguration()方法,獲取到 熱點(diǎn)的WifiConfiguration
                WifiConfiguration configuration = (WifiConfiguration) method.invoke(manager);
                ssid = configuration.SSID;
            } catch (NoSuchMethodException e) {
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        } else {
            /*BluetoothAdapter myDevice = BluetoothAdapter.getDefaultAdapter();
            ssid = myDevice.getName();*/
            return "";
        }

        return ssid;
    }

針對Android 8.0以上,沒有現(xiàn)成的API可用。經(jīng)過搜索,發(fā)現(xiàn)可以通過獲取手機(jī)名稱來獲取熱點(diǎn)名稱。


圖1.jpg
圖2.jpg

在系統(tǒng)設(shè)置,關(guān)于手機(jī)界面,有設(shè)備名稱,在名稱修改界面可以看到一行字:“使用藍(lán)牙互聯(lián)、WiFi直連、熱點(diǎn)共享和USB連接時(shí),其他設(shè)備將看到此名稱”
也就是說,設(shè)備名稱和熱點(diǎn)名稱是保持一致的。
于是,尋找獲取手機(jī)名稱的方法:

BluetoothAdapter myDevice = BluetoothAdapter.getDefaultAdapter();
String deviceName = myDevice.getName();

但是,這個(gè)方法也有問題,就是它只能獲取手機(jī)默認(rèn)的名稱,如果用戶手動(dòng)修改了設(shè)備名稱,這個(gè)方法返回的還是默認(rèn)的名稱。
所以,沒招了。。。誰有更好的方法,歡迎留言。

4. Android開啟熱點(diǎn)本機(jī)IP

Android手機(jī)開啟熱點(diǎn)后,本機(jī)的IP地址是固定的192.168.43.1

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容