SCAN_RESULTS_AVAILABLE_ACTION在Android 6.0中返回空列表

昨天我的Nexus 5从Android MNC收到更新到版本6.0 - Marshmallow 。 此后,扫描设备中可用networking的操作停止接收列表,在这种情况下,结果列表的大小为0,即使Wifi系统设置中列出了10个以上的Wifinetworking。

代码如下:注册SCAN_RESULTS_AVAILABLE_ACTION并等待Receiver中的事件,如下所示:

 // Register the Receiver in some part os fragment... getActivity().registerReceiver(wifiListener, new IntentFilter(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION)); WifiManager wifiManager = (WifiManager) getActivity().getSystemService(Context.WIFI_SERVICE); wifiManager.startScan(); // Inside the receiver: WifiManager wifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE); List<ScanResult> results = wifiManager.getScanResults(); // the result.size() is 0 after update to Android v6.0, same code working in older devices. 

我search了关于这个API主题的变化 ,但是我没有看到这个function的任何重大改变。

有没有人注意到这个? 在API中是新东西还是只是一个孤立的情况?

从Android 6.0开始,权限行为已经更改为运行时。 要使用需要权限的function,应该先检查权限是否先前被授予。 使用checkSelfPermission(permissionString) 方法返回一个结果, checkSelfPermission(permissionString)权限是PERMISSION_GRANTED还是PERMISSION_DENIED

如果未获得许可或者是第一次,则应该提出许可请求。 给用户授予或拒绝的选项。

 if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED){ requestPermissions(new String[]{Manifest.permission.ACCESS_COARSE_LOCATION}, PERMISSIONS_REQUEST_CODE_ACCESS_COARSE_LOCATION); //After this point you wait for callback in onRequestPermissionsResult(int, String[], int[]) overriden method }else{ getScanningResults(); //do something, permission was previously granted; or legacy device } 

如果您的代码在M之前的设备上运行,则继续执行代码,使用传统方法授予权限。

一旦请求许可,对话框将显示给用户。 他/她的回应将作为:

 @Override public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) { if (requestCode == PERMISSIONS_REQUEST_CODE_ACCESS_COARSE_LOCATION && grantResults[0] == PackageManager.PERMISSION_GRANTED) { // Do something with granted permission mWifiListener.getScanningResults(); } } 

之后,您可以使用LocationServices.SettingsApi检查位置服务是否处于开启状态,并请求用户在禁用此选项时启用。 这是可能的Play服务LocationSettingsStatusCodes.RESOLUTION_REQUIREDcallback。

我在AOSP问题跟踪问题185370中find相关问题WifiManager#getScanResults()返回一个空数组列表,如果GPSclosures。

问题来自#1 ,手机必须打开位置服务才能获取手机的wifi列表。

从#18开始 ,Android项目成员声称开发团队已经解决了您所报告的问题,并将在未来的版本中提供。

APP在targetSdkVersion 23中,只需按照上面的解决scheme来检查运行时权限。 强化定位服务问题将在Android未来版本中解决。

编辑

所以,这个问题似乎是与新的权限处理。 在进入wifi代码之前,您必须先获得许可。 这里是一个例子:

 // call this method only if you are on 6.0 and up, otherwise call doGetWifi() private void getWifi() { if (checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) { requestPermissions(new String[]{Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION}, 0x12345); } else { doGetWifi(); // the actual wifi scanning } } @Override public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) { if (requestCode == 0x12345) { for (int grantResult : grantResults) { if (grantResult != PackageManager.PERMISSION_GRANTED) { return; } } getWifi(); } } 

这项检查必须在活动中完成。

原始示例代码在此处可用,根据本主题中讨论的问题进行修改。

原版的

根据API的链接更改 ,您的应用程序必须具有其中一个位置权限。 引用:

WifiManager.getScanResults():您的应用程序必须具有ACCESS_FINE_LOCATION或ACCESS_COARSE_LOCATION权限。

另外请注意,您的BroadcastReceiver在SCAN_RESULTS_AVAILABLE_ACTION操作中收到了新的布尔键 : EXTRA_RESULTS_UPDATED 。 这显示扫描是否完成,您可以通过调用wifiManager.getScanResults()来访问结果。

除了给出的回答之外, 您还可以使用ContextCompat checkSelfPermission来允许向下兼容较低的Android版本:

 if (ContextCompat.checkSelfPermission(getContext(), Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) { requestPermissions(new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, PERMISSIONS_REQUEST_CODE_ACCESS_FINE_LOCATION); // Get the result in onRequestPermissionsResult(int, String[], int[]) } else { // Permission was granted, do your stuff here }