Android 6.0中的SCAN_RESULTS_AVAILABLE_ACTION返回空列表

Dei*_*zan 45 android android-wifi android-6.0-marshmallow

昨天我的Nexus 5收到了Android MNC版本的更新6.0 - Marshmallow.从那时起,扫描设备中可用网络的操作就会停止接收列表,在这种情况下,结果列表的大小为0,即使在Wifi系统设置中列出了10多个Wifi网络.

通常的代码是: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.
Run Code Online (Sandbox Code Playgroud)

我搜索了有关此主题的API主题的更改,但我没有看到此功能的任何重大更改.

有没有人注意到这个?API中是新的东西还是仅仅是一个孤立的案例?

Nik*_*ski 58

从Android 6.0开始,权限行为已更改为运行时.要使用需要权限的功能,应先检查先前是否已授予权限.使用checkSelfPermission(permissionString) 方法返回结果,许可是PERMISSION_GRANTEDPERMISSION_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
}
Run Code Online (Sandbox Code Playgroud)

如果您的代码在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();
     }
 }
Run Code Online (Sandbox Code Playgroud)

之后,您可以检查位置服务是否为ON,LocationServices.SettingsApi如果禁用此选项,则使用并请求用户启用.这可以通过Play服务LocationSettingsStatusCodes.RESOLUTION_REQUIRED回调实现.

  • M上有7.5%的用户,这意味着其他人应该接受"访问位置"权限,这对他们来说完全没用.最有可能它会吓跑他们 - 从未使用(并且不应该使用)位置的应用程序开始要求额外的许可.有没有办法只为M添加权限? (5认同)

Fan*_*ang 34

我发现AOSP问题跟踪器问题185370中的相关问题WifiManager#getScanResults()如果GPS关闭则返回一个空数组列表.

问题从#1提到,移动必须打开位置服务才能获得移动的wifi列表.

#18开始,Android项目成员声称开发团队已经修复了您报告的问题,并且将在未来版本中提供.

APP位于targetSdkVersion 23中,只需按照上述解决方案检查运行时权限即可.强制启用位置服务问题将在Android未来版本中修复.

  • @fantasy非常感谢您的回答。但这是一个令人烦恼的问题,因为我已经允许向我的应用程序授予位置权限,但是我的设备GPS处于关闭状态,但仍然无法正常工作。现在,如果用户未明确打开GPS,这种情况就没有用了。我不明白,wifi扫描确实需要GPS的帮助。 (2认同)

Ger*_*ssy 7

编辑

因此,问题似乎与新的权限处理有关.在继续使用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();
    }
}
Run Code Online (Sandbox Code Playgroud)

此检查必须在活动中完成.

此处提供原始示例代码,并根据本主题中讨论的问题进行了修改.

原版的

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

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

另请注意,您的BroadcastReceiver在行动时收到了一个新的布尔键SCAN_RESULTS_AVAILABLE_ACTION:EXTRA_RESULTS_UPDATED.这表示扫描是否完成,您可以通过调用访问结果wifiManager.getScanResults().


小智 6

除非您打开GPS,否则这将无法工作。很奇怪,但这是我获得wifi列表的唯一方法:-(。