Android 12 Wifi 开发(获取列表连接断开连接)

Posted LinkDamo

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android 12 Wifi 开发(获取列表连接断开连接)相关的知识,希望对你有一定的参考价值。

获取Wifi列表:

扫描(这个方法早在android 9.0 就被弃用),不过如果不调用的话是没法及时获取Wifi列表的广播的。(不需要也能正常获取,没有延迟,经实验毫无区别)

public static void searchWifiList(WifiManager manager) 
        manager.startScan();

创建广播并接收:

/**
     * 获取附近的WiFi列表
     *
     * @param manager WifiManager
     * @param flag    是否保留重名但BSSID不同的wifi     true保留,false不保留
     * @return wifi列表
     */
    public static List<ScanResult> scanResults(WifiManager manager, boolean flag) 
        List<ScanResult> scanResults = new ArrayList<>();
        HashSet<String> hs = new HashSet<>();
        Log.d("WifiUtils", "scanResults: " + manager.getScanResults().size());
        if (flag) 
            scanResults = manager.getScanResults();
            return scanResults;
        
        for (ScanResult scanResult : manager.getScanResults()) 
            if (hs.add(scanResult.SSID)) 
                scanResults.add(scanResult);
            
        
        return scanResults;
    
private final BroadcastReceiver receiver = new BroadcastReceiver() 
        @Override
        public void onReceive(Context context, Intent intent) 
            if (intent.getAction().equals(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION)) 
                Log.d("WifiFragment", "onReceive: 刷新数据");
                results = WifiUtils.scanResults(manager, true);
                mainBinding.scanResult.getAdapter().notifyDataSetChanged();
             else if (intent.getAction().equals(WifiManager.WIFI_STATE_CHANGED_ACTION)) 
                int wifiState = intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE, 0);
                switch (wifiState) 
                    case WifiManager.WIFI_STATE_DISABLED:
                        Log.d("WifiFragment", "onReceive: wifi 关闭");
                        mainBinding.switchWifi.setText("已停用");
                        results = new ArrayList<>();
                        mainBinding.scanResult.getAdapter().notifyDataSetChanged();
                        break;
                    case WifiManager.WIFI_STATE_DISABLING:
                    case WifiManager.WIFI_STATE_ENABLING:
                    case WifiManager.WIFI_STATE_UNKNOWN:
                        break;
                    case WifiManager.WIFI_STATE_ENABLED:
                        Log.d("WifiFragment", "onReceive: wifi 打开");
                        mainBinding.switchWifi.setText("已启用");
                        break;
                
            
        
    ;

配置并连接(无系统签名):

/**
     * 创建连接
     * @param manager WifiManager
     * @param ssid  Wifi名称
     * @param bssid 唯一标识(可以为空)
     * @param passwd    密码  (当前网络是开放网络时,可以为空)
     * @param isHidden  是否是隐藏网络
     * @param capabilities  安全协议(根据协议选择连接方式)
     */
    @RequiresApi(api = Build.VERSION_CODES.Q)
    public static void connectWifiForQ(WifiManager manager, String ssid, String bssid, String passwd, boolean isHidden, String capabilities) 
        if (capabilities.contains("WPA-PSK") || capabilities.contains("WPA2-PSK")) 
            setWPA2ForQ(manager, ssid, bssid, passwd, isHidden);
         else 
            setESSForQ(manager, ssid, isHidden);
        
    

    // WPA2-PSK
    @RequiresApi(api = Build.VERSION_CODES.Q)
    public static int setWPA2ForQ(WifiManager manager, String ssid, String bssid, String passwd, boolean isHidden) 
        WifiNetworkSuggestion suggestion;
        if (bssid == null) 
            suggestion= new WifiNetworkSuggestion.Builder()
                    .setSsid(ssid)
                    .setWpa2Passphrase(passwd)
                    .setIsHiddenSsid(isHidden)
                    .build();
         else 
            suggestion= new WifiNetworkSuggestion.Builder()
                    .setSsid(ssid)
                    .setBssid(MacAddress.fromString(bssid))
                    .setWpa2Passphrase(passwd)
                    .setIsHiddenSsid(isHidden)
                    .build();
        
        List<WifiNetworkSuggestion> suggestions = new ArrayList<>();
        suggestions.add(suggestion);
        int status = manager.addNetworkSuggestions(suggestions);
        if (status != WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS) 
            // 连接失败
            Log.d("WifiUtils", "setWPA2ForQ: 添加失败");
         else 
            Log.d("WifiUtils", "setWPA2ForQ: 添加成功");
        
        return status;
    

    // ESS
    @RequiresApi(api = Build.VERSION_CODES.Q)
    public static int setESSForQ(WifiManager manager, String ssid, boolean isHidden) 
        WifiNetworkSuggestion suggestion = new WifiNetworkSuggestion.Builder()
                .setSsid(ssid)
                .setIsHiddenSsid(isHidden)
                .build();
        List<WifiNetworkSuggestion> suggestions = new ArrayList<>();
        suggestions.add(suggestion);
        int status = manager.addNetworkSuggestions(suggestions);
        if (status != WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS) 
            // 连接失败
            Log.d("WifiUtils", "setWPA2ForQ: 添加失败");
         else 
            Log.d("WifiUtils", "setWPA2ForQ: 添加成功");
        
        return status;

    

配置并连接(有系统签名):

/**
     * 连接wifi
     *
     * @param manager       WifiManager
     * @param configuration Wifi配置
     * @return 是否连接成功
     */
    public static boolean connectWifi(WifiManager manager, WifiConfiguration configuration) 
        int id = manager.addNetwork(configuration);
        WifiInfo connectionInfo = manager.getConnectionInfo();
        manager.disableNetwork(connectionInfo.getNetworkId());
        boolean b = manager.enableNetwork(id, true);
        Log.d("WifiManagerUtils", "connectWifi: 连接状态=" + b);
        if (b) 
            manager.saveConfiguration();
         else 
            Log.d("WifiManagerUtils", configuration.toString());
        
        return b;
    

    /**
     * 创建Wifi配置
     *
     * @param SSID         wifi名称
     * @param password     wifi密码
     * @param hidden       网络是否隐藏(该方法与添加隐藏网络通用)
     * @param capabilities 网络安全协议
     * @return 配置好的wifi
     */
    public static WifiConfiguration createWifiInfo(String SSID, String password, boolean hidden, String capabilities) 
        WifiConfiguration configuration = new WifiConfiguration();
        configuration.SSID = "\\"" + SSID + "\\"";
        if (hidden) 
            configuration.hiddenSSID = true;
        
        Log.d("WifiManagerUtils", "createWifiInfo: " + capabilities);
        if (capabilities.contains("SAE") && Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) 
            setWPA3(configuration, password);
         else if (capabilities.contains("WPA-PSK") || capabilities.contains("WPA2-PSK")) 
            setWPA(configuration, password);
         else if (capabilities.contains("WEP")) 
            setWEP(configuration, password);
         else 
            setESS(configuration);
        
        return configuration;
    

    /**
     * 设置wpa3协议
     *
     * @param configuration 配置
     * @param password      密码
     */
    public static void setWPA3(WifiConfiguration configuration, String password) 
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) 
            configuration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.SAE);
        
        configuration.preSharedKey = "\\"" + password + "\\"";
    

    /**
     * WPA协议
     *
     * @param configuration 配置
     * @param password      密码
     */
    public static void setWPA(WifiConfiguration configuration, String password) 
        configuration.preSharedKey = "\\"" + password + "\\"";
        //公认的IEEE 802.11验证算法。
        configuration.allowedAuthAlgorithms.clear();
        configuration.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.OPEN);
        //公认的的公共组密码。
        configuration.allowedGroupCiphers.clear();
        configuration.allowedGroupCiphers.set(WifiConfiguration.PairwiseCipher.CCMP);
        configuration.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.TKIP);
        //公认的密钥管理方案。
        configuration.allowedKeyManagement.clear();
        configuration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK);
        //密码为WPA。
        configuration.allowedPairwiseCiphers.clear();
        configuration.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP);
        configuration.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.TKIP);
        //公认的安全协议。
        configuration.allowedProtocols.clear();
        configuration.allowedProtocols.set(WifiConfiguration.Protocol.RSN);
    

    /**
     * WEP协议
     *
     * @param configuration 配置
     * @param password      密码
     */
    public static void setWEP(WifiConfiguration configuration, String password) 
        configuration.wepKeys[0] = "\\"" + password + "\\"";
        configuration.wepTxKeyIndex = 0;
        configuration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
        configuration.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP40);
    


    /**
     * 无密码
     *
     * @param configuration 配置
     */
    public static void setESS(WifiConfiguration configuration) 
        configuration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
    

断开连接(无系统签名):

//Android11及以上可以使用,清除建议列表,可以断开当前的网络
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) 
                List<WifiNetworkSuggestion> networkSuggestions = wifiManager.getNetworkSuggestions();
                wifiManager.removeNetworkSuggestions(networkSuggestions);
            

监听连接状态:

 //监听网络连接状态
        connectivityManager.registerDefaultNetworkCallback(new ConnectivityManager.NetworkCallback()
            @Override
            public void onAvailable(@NonNull Network network) 
                super.onAvailable(network);
                Log.d("MainActivity", "onAvailable: 网络已连接");
                Toast.makeText(MainActivity.this, "已连接网络", Toast.LENGTH_SHORT).show();
            

            @Override
            public void onUnavailable() 
                super.onUnavailable();
                Log.d("MainActivity", "onUnavailable: 网络已断开");
                Toast.makeText(MainActivity.this, "已断开网络", Toast.LENGTH_SHORT).show();
            
        );

注意事项:

断开当前Wifi后,再重新连接该Wifi,可能会出现无法连接的情况。

这种情况我是通过关闭Wifi后再重新打开解决的,但是对Wifi的开关控制要涉及到权限问题——

需要System权限,在Manifest中添加:

android:sharedUserId="android.uid.system"

然后需要系统签名,可在系统源码中获得。

不知道各位有没有什么好的解决方法。

项目地址:

有系统签名(推荐)——

https://github.com/Ouanu/WIFI_DEMOhttps://github.com/Ouanu/WIFI_DEMO无系统签名——

https://github.com/Ouanu/WifiDemohttps://github.com/Ouanu/WifiDemo

不需系统签名的方法(需要root):

步骤如下——

1、在/data目录下创建一个文本,用来标识Wifi是打开或者关闭状态,比如:

文本文件名字:node

内容:0                // (0是关,1是开)

2、chmod 666 /data/node (赋予该文件的读写权限)

3、创建循环检测该文件内容的脚本,并针对内容执行adb命令

adb shell svc wifi enable    // 开启WIFI
adb shell svc wifi disable    // 关闭WIFI

4、应用端(App)对该文本进行读写

即可实现不需系统签名也可控制WIFI模块的开关

Android 获取连接WiFi和蓝牙名称

一、获取WiFi名称:

//获取连接的wifi名称
public String getConnectWifiSsid() {
	WifiManager wifiManager = (WifiManager) getApplicationContext().getSystemService(Context.WIFI_SERVICE);
	WifiInfo wifiInfo = wifiManager.getConnectionInfo();
	//获取wifi信号强度
	rssi = wifiInfo.getRssi();
	String wifiid = wifiInfo.getSSID().replace("\\"", "").replace("\\"", "");
	MyLog.getInstance().PrintLog(TAG, "ssid======" + wifiid);
	MyLog.getInstance().PrintLog(TAG, "rssi======" + rssi);
    return wifiid;
}

根据信号强度设置wifi格数图片

if (rssi >= -55) {
	//满格信号
    image_wifi.setImageDrawable(ContextCompat.getDrawable(activity, R.mipmap.wifi4));
} else if (rssi < -55 && rssi >= -70) {
	//三格信号
 	image_wifi.setImageDrawable(ContextCompat.getDrawable(activity, R.mipmap.wifi3));
} else if (rssi < -70 && rssi >= -85) {
	//二格信号
	image_wifi.setImageDrawable(ContextCompat.getDrawable(activity, R.mipmap.wifi2));
} else if (rssi < -85&& rssi >= -100) {
	//一格信号
 	image_wifi.setImageDrawable(ContextCompat.getDrawable(activity, R.mipmap.wifi1));
}

二、获取蓝牙名称:

添加蓝牙权限:

<uses-permission android:name="android.permission.BLUETOOTH"/>
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
//获取连接的蓝牙名称
 public String getConnectedBtDevice() {
     //获取蓝牙适配器
     BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
     //得到已匹配的蓝牙设备列表
     Set<BluetoothDevice> bondedDevices = bluetoothAdapter.getBondedDevices();
     if (bondedDevices != null && bondedDevices.size() > 0) {
         for (BluetoothDevice bondedDevice : bondedDevices) {
			  try {
                  //使用反射调用被隐藏的方法
                  Method isConnectedMethod = BluetoothDevice.class.getDeclaredMethod("isConnected", (Class[]) null);
                  isConnectedMethod.setAccessible(true);
                  boolean isConnected = (boolean) isConnectedMethod.invoke(bondedDevice, (Object[]) null);
                  MyLog.getInstance().PrintLog(TAG, "isConnected:" + isConnected);
			      if (isConnected) {
                        return bondedDevice.getName();
                    }
                } catch (NoSuchMethodException e) {
                    e.printStackTrace();

                } catch (IllegalAccessException e) {
                    e.printStackTrace();

                } catch (InvocationTargetException e) {
                    e.printStackTrace();
                }
            }
        }
        return null;
    }
BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
//判断蓝牙功能是否存在
if (mBluetoothAdapter == null) {
showToest("该设备不支持蓝牙");
return;
}
//获取名字 MAC地址
String name = mBluetoothAdapter.getName();
String address = mBluetoothAdapter.getAddress();
Log.i(TAG, "蓝牙名: "+name+"mac地址:"+address);
//获取蓝牙的状态
int state = mBluetoothAdapter.getState();
switch (state){
	case BluetoothAdapter.STATE_ON:
		showToest("蓝牙已经打开");
		Log.i(TAG, "蓝牙已经打开 ");
		break;
	case BluetoothAdapter.STATE_OFF:
		showToest("蓝牙已经关闭");
		Log.i(TAG, "蓝牙已经关闭 ");
		break;
	case BluetoothAdapter.STATE_TURNING_OFF:
		showToest("蓝牙正在关闭");
		Log.i(TAG, "蓝牙正在关闭 ");
		break;
	case BluetoothAdapter.STATE_TURNING_ON:
		showToest("蓝牙正在打开");
		Log.i(TAG, "蓝牙正在打开 ");
		break;
		default:
		break;
}

以上是关于Android 12 Wifi 开发(获取列表连接断开连接)的主要内容,如果未能解决你的问题,请参考以下文章

Android连接指定Wifi的方法

如何使用 xamarin android 应用程序获取 wifi 列表

Qt for android 获取 Wifi 列表

Android:如果手机通过 WiFi 连接,则无法从网络获取地理位置

Android开发,怎么在代码里获得当前连接wifi的端口号?

Android开发—智能家居系列:UDP通信发送指令