昨天,我的Nexus 5收到了从Android MNC
到版本6.0 - Marshmallow
的更新。
从那时起,扫描设备中可用网络的操作就会停止接收列表,在这种情况下,结果列表的大小为0,即使在Wifi系统设置中列出了10多个Wifi网络。
这是通常的代码:注册SCAN_RESULTS_AVAILABLE_ACTION
并等待接收器中的事件,如下所示:
// 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中是新内容还是仅仅是一个孤立的案例?
答案 0 :(得分:56)
从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之前的设备上运行,则继续使用您的代码,使用传统方法授予权限。
一旦请求获得许可,将向用户显示对话框。他/她的回复将以:
发送@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
检查位置服务是否为ON,并请求用户启用此选项是否已禁用。这可以通过Play服务LocationSettingsStatusCodes.RESOLUTION_REQUIRED
回调来实现。
答案 1 :(得分:33)
我在AOSP问题跟踪器问题185370中发现相关问题如果GPS已关闭,WifiManager#getScanResults()将返回一个空数组列表。
问题从#1提到,手机必须打开位置服务才能获得手机的wifi列表。
来自#18,Android项目成员声称开发团队已修复您已报告的问题,并且将在未来版本中提供。
APP在targetSdkVersion 23中,只需按照上述解决方案检查运行时权限即可。强制启用位置服务问题将在Android未来版本中修复。
答案 2 :(得分: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();
}
}
此检查必须在活动中完成。
原始示例代码可用here,根据本主题中讨论的问题进行修改。
根据链接的changes of the API,您的应用程序必须具有其中一个位置权限。引用:
WifiManager.getScanResults():您的应用必须具有ACCESS_FINE_LOCATION或ACCESS_COARSE_LOCATION权限。
另请注意,您的BroadcastReceiver会在SCAN_RESULTS_AVAILABLE_ACTION
操作上收到new boolean key:EXTRA_RESULTS_UPDATED
。这表明扫描是否完成,您可以通过调用wifiManager.getScanResults()
来访问结果。
答案 3 :(得分:3)
除了给定的回复;您还可以使用checkSelfPermission
ContextCompat
来支持与较低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
}
答案 4 :(得分:3)
除非您打开了GPS,否则这将无法工作。很奇怪,但这是我获得wifi列表的唯一方法:-(。