Android 8 Oreo中WifiManager的startscan方法未收到响应

5
根据官方的Android文档,WifiManager中的startScan方法在API P级别已被弃用。但是我尝试在API 26级别(P之前)使用此方法却没有成功。我开发了一个需要扫描WiFi网络的应用程序,如果用户同意所需权限,则此行为对于应用程序的适当功能至关重要。然而,当调用startScan方法时,我没有收到任何响应。有人能帮助我解决这个问题或找到替代解决方案吗?
这是文档的链接。 https://developer.android.com/reference/android/net/wifi/WifiManager.html#startScan() 谢谢
编辑: 以下是启动扫描进程的代码:
public boolean startScan() {
   WifiManager wm = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
   if (!wm.isWifiEnabled()) {
     try {
       wm.setWifiEnabled(true);
     } catch (SecurityException e) {
       Log.w(LOG_TAG, "Error enabling wifi", e);
       return false;
     }
   }
   boolean started = wm.startScan();
   Log.d(LOG_TAG, "Scan started? " + started);
   return started;
}

这是接收扫描结果的BroadcastReceiver。在Android 8及以上的版本中,只有当targetSdkVersion为26+时有效。

public class InOutWifiScanResultsReceiver extends BroadcastReceiver {
   private static final String LOG_TAG = "ScanResults";

   @Override
   public void onReceive(Context context, Intent intent) {
     super.onReceive(context, intent); // Never called in Android 8 and targetSdkVersion 26+
     List<ScanResult> results = getWifiResults(context);
     Log.d(LOG_TAG, "Received results (" +  results.size() + " AP's)");
   }

   private static List<ScanResult> getWifiResults(Context context) {
      WifiManager wm = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
      try {
        return wm.getScanResults();
      } catch (SecurityException e) {
        return new ArrayList<>();
      }
   }
}

在清单文件中,我们使用以下权限和声明了广播接收器:

<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<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"/>

 <receiver
    android:name=".InOutWifiScanResultsReceiver"
    android:exported="false">
    <intent-filter>
        <action android:name="android.net.wifi.SCAN_RESULTS"/>
    </intent-filter>
 </receiver>

在运行时需要位置权限,所以我确定它已被允许。我也确信位置是活动的(GPS级别)。

BroadcastReceiver工作正常,因为使用targetSdkVersion = 25或更低版本编译时,一切都按预期工作并接收到扫描结果。我还测试了android:exported="true",但对结果没有影响。

非常感谢您的帮助。

1个回答

6
在 Android 8 或更高版本中,通过 Manifest 声明的隐式 BroadcastReceivers 由于性能原因不再发送或接收(这是在 Android 8 中引入的一种优化,限制了 后台执行)。有一些例外情况在 这里 列出,但 android.net.wifi.SCAN_RESULTS 动作不是例外情况,因此在 Android 8+ 中,您不能在 Manifest 中注册 android.net.wifi.SCAN_RESULTS 动作以等待 ScanResults(实际上可以,但您将什么也收不到)。
如果您的 targetSdkVersion 是 26(Android 8 Oreo)或更高版本,则会发生这种情况,但如果您在 Gradle 文件中声明了一个 targetSdkVersion 为 25 或更低,则该优化不会运行于您的应用程序中,您通过 Manifest 注册的隐式 Intents 将按预期工作。
为了让它在Android 8 Oreo中正常工作,且targetSdkVersion为26+,您需要通过应用程序上下文进行注册。
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction("android.net.wifi.SCAN_RESULTS");
context.registerReceiver(new InOutWifiScanResultsReceiver(), intentFilter);

但是,请注意,这种注册需要应用程序正在运行,因此当您的应用程序停止时,您将无法接收此广播接收器。

P.S:您的代码是正确的,但您没有考虑到这个Android 8的限制。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接