Android系统编程入门系列之硬件交互——无线通信WLAN

Android系统的移动设备大多支持无线WLAN技术。利用该技术,不仅能实现互联网通信,还能实现无线定位,热点共享等远程通信功能。针对使用WLAN的不同功能,可能需要分别申请不同的权限声明,同时调用不同的系统框架API,下文将按照不同的使用功能分别介绍。
扫描无线设备 该功能通常只允许在系统自带的设置应用中使用,当然如果是第三方应用的目标版本在Android 9.0即API 28以下,也可以使用该功能。扫描周围的无线设备,需要用到android.net.wifi.WifiManager wifi管理类。
权限声明 【Android系统编程入门系列之硬件交互——无线通信WLAN】在扫描无线设备时,需要启用设备的位置开关,同时申请Manifest.permission.ACCESS_FINE_LOCATION="android.permission.ACCESS_FINE_LOCATION"精确定位权限或者Manifest.permission.ACCESS_COARSE_LOCATION="android.permission.ACCESS_COARSE_LOCATION"模糊定位权限。
另外,由于需要使用设备的WLAN才能扫描,所以需要申请获取设备自身wifi状态的权限Manifest.permission.ACCESS_WIFI_STATE="android.permission.ACCESS_WIFI_STATE"
同样扫描也会修改设备自身的wifi状态,所以也需要声明wifi状态修改的权限Manifest.permission.CHANGE_WIFI_STATE="android.permission.CHANGE_WIFI_STATE"
扫描流程 首先在可以获取上下文环境Context对象的位置,调用该对象的getSystemService(String name)方法,参数 name 值为Context.WIFI_SERVICE="wifi",返回WifiManagerwifi管理类对象。
在需要开启扫描的位置,调用WifiManager对象的startScan()方法,即可开始扫描,该方法会返回boolean类型的结果标志是否成功启动扫描。
虽然已经成功启动了扫描无线设备的功能,但是查看扫描结果还需要借助四大组件中负责进程间通信的广播接收器。自定义BroadcastReceiver的目的就是用于接收扫描结果。因此在调用context.registerReceiver(BroadcastReceiver receiver, IntentFilter intentFilter)方法注册该广播接收器时,通过IntentFilter对象设置的意图行为addAction(String action)传入的参数 action 值为WifiManager.SCAN_RESULTS_AVAILABLE_ACTION="android.net.wifi.SCAN_RESULTS"。最终,在该类的onReceiver(Context context, Intent intent)方法中,可以对接收到的参数 intent 意图获取保存的结果,调用该参数的getBooleanExtra(String key, boolean default)方法,传入参数 key 的值为WifiManager.EXTRA_RESULTS_UPDATED="resultsUpdated",即可得到boolean类型的实际扫描结果。
在得到扫描结果为true之后,可以继续调用WifiManager对象的getScanResults()方法获取扫描结果,得到由android.net.wifi.ScanResult扫描结果类组成的List数组。
建立网络连接 通过WLAN设备可以建立网络连接,以此与其他WLAN设备通信。建立wifi连接的途径主要有两种,包括连接其他WLAN广播设备,或者与另外一个WLAN设备建立一对一连接(俗称热点连接)。之后的连接状态和通信过程,则都是主要借助android.net.ConnectivityManager连接管理类。获取该连接管理类对象的方法同样是在可以获取上下文环境Context对象的位置,调用该对象的getSystemService(String name)方法,参数 name 值为Context.CONNECTIVITY_SERVICE="connectivity",返回ConnectivityManager 连接管理类对象。其后流程暂先不表,这里主要介绍如何建立wifi连接。
权限声明 与其他WLAN设备建立网络连接,首先要在清单文件中声明[Manifest.permission.ACCESS_WIFI_STATE](https://developer.android.google.cn/reference/android/Manifest.permission#ACCESS_WIFI_STATE
WLAN广播连接 在Android 10即API 29版本以前,主要依赖WifiManager管理类对象。而从Android10及API 29版本开始,改由android.net.wifi.WifiNetworkSuggestionwifi网络建议类执行相关操作。
适用于API 29之前版本 通过android.net.wifi.WifiConfiguration的相关变量,配置要连接的WLAN设备信息,包括 SSID 对应的wifi名, preSharedKey对应的wifi密码, allowKeyManagement 对应的加密方式等信息。
在创建并配置WifiConfiguration对象的相关信息之后,调用WifiManager对象的addNetwork(WifiConfiguration config)方法,将上述对象作为参数 config 的值传入,即可得到 int 类型的本地id索引值,如果添加失败,则返回的该索引值将为非正数。成功得到该索引值之后,再次调用WifiManager对象的enableNetwork(int netId, boolean attemptConnect),其参数 netId 即得到的索引值传入,参数 attemptConnect 如果为true会立即尝试连接,否则只是保存该wifi信息,并不会自动连接。
一旦系统尝试连接,网络连接状态会通过系统广播实时发送,因此如果想在应用程序中实时监听网络连接状态,只需要在获取上下文环境Context对象的位置,注册一个自定义的BroadcastReceiver广播接收器。监听的Intent意图对象中的 action 参数值WifiManager.RSSI_CHANGED_ACTION="android.net.wifi.RSSI_CHANGED"为连接的WLAN设备RSSI发生改变时的行为标签。另外可以通过意图对象的getBundle()等系列参数获取网络状态信息,其值均在WifiManager中以常量形式定义。
适用于API 29及以后版本 通过android.net.wifi.WifiNetworkSuggestion.Builder建造者模式的无参构造方法和setX()系列方法配置要连接的WLAN设备信息,包括setSsid(String ssid)对应的wifi名,和setWpa2Passphrase(String passphrase)对应设置wpa2加密模式下的密码,及其他相关参数。最终调用该对象的build()方法,返回建造出来的WifiNetworkSuggestionwifi网络建议类的实例化对象。可以同时创建多个不同的WifiNetworkSuggestion对象,以List列表的形式保存。
之后调用WifiManager管理类对象的addNetworkSuggestions(List networkSuggestions)方法,参数 networkSUggestions 便是所有要保存的WifiNetworkSuggestion对象集合。返回int类型的结果标记添加操作是否执行成功,如果执行成功,将会返回WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS=0的标记值。
在网络添加成功后,同样可以通过注册自定义的BroadcastReceiver的方式监听网络连接状态。与API 29以前的版本不同的是,这里要监听的Intent意图对象中的参数 action 行为值为WifiManager.ACTION_WIFI_NETWORK_SUGGESTION_POST_CONNECTION="android.net.wifi.action.WIFI_NETWORK_SUGGESTION_POST_CONNECTION",在该行为值下同样可以获取网络状态信息。

    推荐阅读