SCAN_RESULTS_AVAILABLE_ACTION return Android 6.0 中的空列表
SCAN_RESULTS_AVAILABLE_ACTION return empty list in Android 6.0
昨天我的 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.
我在 changes of the API 主题中搜索了关于此的内容,但我没有看到此功能的任何重大更改。
有人注意到了吗? API 中有什么新东西还是只是一个孤立的案例?
编辑
所以,问题似乎出在新的权限处理上。在继续使用 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();
}
}
此检查必须在 Activity 内完成。
原始示例代码可用here,根据本主题讨论的问题修改
原创
根据链接 changes of the API,您的应用程序必须具有其中一项位置权限。引用:
WifiManager.getScanResults(): Your app must have ACCESS_FINE_LOCATION or ACCESS_COARSE_LOCATION permission.
另请注意,您的 BroadcastReceiver 在 SCAN_RESULTS_AVAILABLE_ACTION
操作上收到了一个 new boolean key:EXTRA_RESULTS_UPDATED
。这显示扫描是否完成,您可以通过调用 wifiManager.getScanResults()
.
访问结果
从 Android 6.0 开始,权限行为已更改为运行时。要使用需要权限的功能,应首先检查之前是否授予了权限。使用 checkSelfPermission(permissionString)
method 返回结果,授权为 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 之前的设备上 运行,您可以继续使用您的代码,使用旧方法授予权限。
请求权限后,将向用户显示对话框。 His/her 响应将传递为:
@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_REQUIRED
回调实现。
我在 AOSP 问题跟踪器问题 185370 WifiManager#getScanResults() returns 如果 GPS 关闭,则为空数组列表。
#1中提到的问题,手机必须开启位置服务才能获取手机的wifi列表。
并且来自 #18,Android 项目成员声称开发团队已经修复了您报告的问题,并将在未来的版本中提供。
APP的targetSdkVersion 23,按照上面的方法检查runtime权限即可。强制启用位置服务问题将在 Android 未来版本中修复。
除了给定的回复;您还可以使用 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
}
除非您打开了 GPS,否则这将不起作用。很奇怪,但这是我获得 wifi 列表的唯一方法:-(。
昨天我的 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.
我在 changes of the API 主题中搜索了关于此的内容,但我没有看到此功能的任何重大更改。
有人注意到了吗? API 中有什么新东西还是只是一个孤立的案例?
编辑
所以,问题似乎出在新的权限处理上。在继续使用 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();
}
}
此检查必须在 Activity 内完成。
原始示例代码可用here,根据本主题讨论的问题修改
原创
根据链接 changes of the API,您的应用程序必须具有其中一项位置权限。引用:
WifiManager.getScanResults(): Your app must have ACCESS_FINE_LOCATION or ACCESS_COARSE_LOCATION permission.
另请注意,您的 BroadcastReceiver 在 SCAN_RESULTS_AVAILABLE_ACTION
操作上收到了一个 new boolean key:EXTRA_RESULTS_UPDATED
。这显示扫描是否完成,您可以通过调用 wifiManager.getScanResults()
.
从 Android 6.0 开始,权限行为已更改为运行时。要使用需要权限的功能,应首先检查之前是否授予了权限。使用 checkSelfPermission(permissionString)
method 返回结果,授权为 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 之前的设备上 运行,您可以继续使用您的代码,使用旧方法授予权限。
请求权限后,将向用户显示对话框。 His/her 响应将传递为:
@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_REQUIRED
回调实现。
我在 AOSP 问题跟踪器问题 185370 WifiManager#getScanResults() returns 如果 GPS 关闭,则为空数组列表。
#1中提到的问题,手机必须开启位置服务才能获取手机的wifi列表。
并且来自 #18,Android 项目成员声称开发团队已经修复了您报告的问题,并将在未来的版本中提供。
APP的targetSdkVersion 23,按照上面的方法检查runtime权限即可。强制启用位置服务问题将在 Android 未来版本中修复。
除了给定的回复;您还可以使用 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
}
除非您打开了 GPS,否则这将不起作用。很奇怪,但这是我获得 wifi 列表的唯一方法:-(。