You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Android P中WifiManager.startScan()已废弃,如何每3秒获取WiFi扫描结果?

Android P+ 实现WiFi扫描结果定期获取(接近3秒间隔)

嘿,这个问题我之前做项目的时候踩过坑,给你梳理几个可行的思路,不过得先明确Android P(API 28)及更高版本的核心限制:谷歌废弃了startScan(),而且应用完全失去了主动触发WiFi扫描的能力,所有扫描都由系统根据自身策略(耗电、位置变化、网络需求等)来调度。直接调用getScanResults()拿到的是系统最近一次扫描的缓存,所以更新慢是必然的。

要尽可能接近每3秒获取一次最新结果,可以试试下面这些方案:

1. 监听系统扫描完成广播,实时获取最新结果

系统每次完成WiFi扫描后,都会发送WifiManager.SCAN_RESULTS_AVAILABLE_ACTION广播,我们可以注册这个广播接收器,在收到通知时立即拉取最新结果。

步骤:

  • 先申请必要权限(Manifest里配置):
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
  • 代码里注册广播接收器:
private WifiManager mWifiManager;
private BroadcastReceiver mScanResultReceiver;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    mWifiManager = (WifiManager) getSystemService(Context.WIFI_SERVICE);

    // 初始化广播接收器
    mScanResultReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            if (WifiManager.SCAN_RESULTS_AVAILABLE_ACTION.equals(intent.getAction())) {
                // 检查扫描是否成功更新
                boolean isUpdated = intent.getBooleanExtra(WifiManager.EXTRA_RESULTS_UPDATED, false);
                if (isUpdated) {
                    List<ScanResult> latestResults = mWifiManager.getScanResults();
                    // 这里处理你的扫描结果
                    processScanResults(latestResults);
                } else {
                    // 扫描失败,可能是权限不足或系统限制
                    Log.w("WiFiScan", "扫描结果未更新");
                }
            }
        }
    };

    // 注册广播
    IntentFilter filter = new IntentFilter(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION);
    registerReceiver(mScanResultReceiver, filter);
}

@Override
protected void onDestroy() {
    super.onDestroy();
    // 记得注销广播,避免内存泄漏
    unregisterReceiver(mScanResultReceiver);
}

private void processScanResults(List<ScanResult> results) {
    // 你的业务逻辑,比如打印结果、更新UI等
}

注意:这个方案的扫描频率完全依赖系统,默认情况下系统可能十几秒甚至几十秒才扫一次,达不到3秒的要求,所以需要配合下面的方法来触发系统更频繁扫描。

2. 利用位置服务触发系统高频扫描

系统为了辅助定位,在位置变化时会主动触发WiFi扫描。我们可以通过请求高频位置更新,让系统被迫更频繁地做WiFi扫描,从而间接实现接近3秒的结果更新。

步骤:

  • 确保已经申请ACCESS_FINE_LOCATION权限(Android 10+还需要ACCESS_BACKGROUND_LOCATION才能在后台生效)
  • 集成Fused Location Provider请求位置更新:
private FusedLocationProviderClient mFusedLocationClient;
private LocationCallback mLocationCallback;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    // 初始化位置服务
    mFusedLocationClient = LocationServices.getFusedLocationProviderClient(this);
    
    // 配置位置请求参数,设置3秒间隔
    LocationRequest locationRequest = LocationRequest.create();
    locationRequest.setInterval(3000); // 3秒一次位置更新
    locationRequest.setFastestInterval(1000); // 最快1秒一次(系统可能调整)
    locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY); // 高精度模式会触发WiFi扫描

    // 位置更新回调,在这里获取WiFi扫描结果
    mLocationCallback = new LocationCallback() {
        @Override
        public void onLocationResult(LocationResult locationResult) {
            super.onLocationResult(locationResult);
            // 位置更新时,系统大概率刚完成WiFi扫描,直接取最新结果
            List<ScanResult> latestResults = mWifiManager.getScanResults();
            processScanResults(latestResults);
        }
    };

    // 开始请求位置更新
    if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
        mFusedLocationClient.requestLocationUpdates(locationRequest, mLocationCallback, Looper.getMainLooper());
    }
}

@Override
protected void onDestroy() {
    super.onDestroy();
    // 停止位置更新,避免耗电
    mFusedLocationClient.removeLocationUpdates(mLocationCallback);
}

注意

  • 这种方式依赖位置服务,用户关闭位置服务后就失效了
  • 系统依然会限制扫描频率,即使你设置3秒位置间隔,也可能无法做到精确3秒一次(比如后台时系统会降低频率)
  • 高频位置更新会增加耗电,要注意用户体验,最好只在前台需要时开启

3. 避坑提醒

  • 绝对不要用TimerHandler每隔3秒调用getScanResults(),这样拿到的都是旧缓存,不会有新结果
  • Android 10+后台获取扫描结果必须申请ACCESS_BACKGROUND_LOCATION权限,否则只能在前台获取
  • 系统对WiFi扫描有全局频率限制,即使你做了所有操作,也无法突破系统的耗电保护策略,所以只能尽可能接近3秒的目标

内容的提问来源于stack exchange,提问作者EAK TEAM

火山引擎 最新活动