Android NDK开发详解连接性之WLAN 扫描功能概览

Android NDK开发详解连接性之WLAN 扫描功能概览


您可以使用 WifiManager API 提供的 WLAN 扫描功能来获取设备上可见的 WLAN 接入点列表。

WLAN 扫描流程

扫描流程分为三步:

为 SCAN_RESULTS_AVAILABLE_ACTION 注册一个广播监听器,系统会在完成扫描请求时调用此监听器,提供其成功/失败状态。对于搭载 Android 10(API 级别 29)及更高版本的设备,系统将针对平台或其他应用在设备上执行的所有完整 WLAN 扫描发送此广播。应用可以使用广播被动监听设备上所有扫描的完成情况,无需发出自己的扫描。

使用 WifiManager.startScan() 请求扫描。请务必检查方法的返回状态,因为调用可能因以下任一原因失败:

由于短时间扫描过多,扫描请求可能遭到节流。
设备处于空闲状态,扫描已停用。
WLAN 硬件报告扫描失败。
使用 WifiManager.getScanResults() 获取扫描结果。系统返回的扫描结果为最近更新的结果,但如果当前扫描尚未完成或成功,可能会返回以前扫描的结果。也就是说,如果在收到成功的 SCAN_RESULTS_AVAILABLE_ACTION 广播前调用此方法,您可能会获得较旧的扫描结果。

以下代码提供了如何实现这些步骤的示例:

Kotlin

val wifiManager = context.getSystemService(Context.WIFI_SERVICE) as WifiManager

val wifiScanReceiver = object : BroadcastReceiver() {

  override fun onReceive(context: Context, intent: Intent) {
    val success = intent.getBooleanExtra(WifiManager.EXTRA_RESULTS_UPDATED, false)
    if (success) {
      scanSuccess()
    } else {
      scanFailure()
    }
  }
}

val intentFilter = IntentFilter()
intentFilter.addAction(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION)
context.registerReceiver(wifiScanReceiver, intentFilter)

val success = wifiManager.startScan()
if (!success) {
  // scan failure handling
  scanFailure()
}

....

private fun scanSuccess() {
  val results = wifiManager.scanResults
  ... use new scan results ...
}

private fun scanFailure() {
  // handle failure: new scan did NOT succeed
  // consider using old scan results: these are the OLD results!
  val results = wifiManager.scanResults
  ... potentially use older scan results ...
}

Java

WifiManager wifiManager = (WifiManager)
                   context.getSystemService(Context.WIFI_SERVICE);

BroadcastReceiver wifiScanReceiver = new BroadcastReceiver() {
  @Override
  public void onReceive(Context c, Intent intent) {
    boolean success = intent.getBooleanExtra(
                       WifiManager.EXTRA_RESULTS_UPDATED, false);
    if (success) {
      scanSuccess();
    } else {
      // scan failure handling
      scanFailure();
    }
  }
};

IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION);
context.registerReceiver(wifiScanReceiver, intentFilter);

boolean success = wifiManager.startScan();
if (!success) {
  // scan failure handling
  scanFailure();
}

....

private void scanSuccess() {
  List<ScanResult> results = wifiManager.getScanResults();
  ... use new scan results ...
}

private void scanFailure() {
  // handle failure: new scan did NOT succeed
  // consider using old scan results: these are the OLD results!
  List<ScanResult> results = wifiManager.getScanResults();
  ... potentially use older scan results ...
}

限制

Android 8.0(API 级别 26)引入了有关权限和 WLAN 扫描允许频率的限制。

为了提高网络性能和安全性,延长电池续航时间,Android 9(API 级别 28)收紧了权限要求,并进一步限制 WLAN 扫描频率。

权限

注意:在以下提到位置权限或位置收集逻辑的各个部分中,请记住,当应用在后台运行时,获取位置信息访问权限对于应用的核心功能而言至关重要,同时需要向用户提供适当的声明。
Android 8.0 和 Android 8.1:

成功调用 WifiManager.getScanResults() 需要以下任意一项权限:

ACCESS_FINE_LOCATION
ACCESS_COARSE_LOCATION
CHANGE_WIFI_STATE
对于上述权限,如果调用应用一项都不具备,调用将会失败,并显示 SecurityException。

或者,在搭载 Android 8.0(API 级别 26)及更高版本的设备上,您可以使用 CompanionDeviceManager 代表应用对附近的配套设备执行扫描,而不需要位置权限。如需详细了解此选项,请参阅配套设备配对。

Android 9:

成功调用 WifiManager.startScan() 需要满足以下所有条件:

应用拥有 ACCESS_FINE_LOCATION 或 ACCESS_COARSE_LOCATION 权限。
应用拥有 CHANGE_WIFI_STATE 权限。
设备已启用位置信息服务(位于设置 > 位置信息下)。
Android 10(API 级别 29)及更高版本:

成功调用 WifiManager.startScan() 需要满足以下所有条件:

如果您的应用以 Android 10(API 级别 29)SDK 或更高版本为目标平台,应用需要拥有 ACCESS_FINE_LOCATION 权限。
如果您的应用以低于 Android 10(API 级别 29)的 SDK 为目标平台,应用需要拥有 ACCESS_COARSE_LOCATION 或 ACCESS_FINE_LOCATION 权限。
应用拥有 CHANGE_WIFI_STATE 权限。
设备已启用位置信息服务(位于设置 > 位置信息下)。
若要成功调用 WifiManager.getScanResults(),请确保满足以下所有条件:

如果您的应用以 Android 10(API 级别 29)SDK 或更高版本为目标平台,应用需要拥有 ACCESS_FINE_LOCATION 权限。
如果您的应用以低于 Android 10(API 级别 29)的 SDK 为目标平台,应用需要拥有 ACCESS_COARSE_LOCATION 或 ACCESS_FINE_LOCATION 权限。
应用拥有 ACCESS_WIFI_STATE 权限。
设备已启用位置信息服务(位于设置 > 位置信息下)。
如果调用应用无法满足上述所有要求,调用将失败,并显示 SecurityException。

节流

使用 WifiManager.startScan() 扫描的频率适用以下限制。

Android 8.0 和 Android 8.1:

每个后台应用可以在 30 分钟内扫描一次。

Android 9:

每个前台应用可以在 2 分钟内扫描四次。这样便可在短时间内进行多次扫描。

所有后台应用总共可以在 30 分钟内扫描一次。

Android 10 及更高版本:

适用 Android 9 的节流限制。新增一个开发者选项,用户可以关闭节流功能以便进行本地测试(位于开发者选项 > 网络 > WLAN 扫描调节下)。

本页面上的内容和代码示例受内容许可部分所述许可的限制。Java 和 OpenJDK 是 Oracle 和/或其关联公司的注册商标。

最后更新时间 (UTC):2020-06-23。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

五一编程

程序之路有我与你同行

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值