首页 文章

Android 6.0中的SCAN_RESULTS_AVAILABLE_ACTION返回空列表

提问于
浏览
44

昨天,我的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中是新的东西还是仅仅是一个孤立的案例?

5 回答

  • 54

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

    如果您的代码在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 Services LocationSettingsStatusCodes.RESOLUTION_REQUIRED 回调可以实现这一点 .

  • 7

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

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

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

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

  • 3

    编辑

    因此,问题似乎与新的权限处理有关 . 在继续使用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 keyEXTRA_RESULTS_UPDATED . 这表示扫描是否完成,您可以通过调用 wifiManager.getScanResults() 来访问结果 .

  • 33

    除了给定的答复;您还可以使用 checkSelfPermissionContextCompat 来向后兼容较低的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
    }
    
  • 1

    除非您打开GPS,否则此功能无效 . 很奇怪,但这是我得到wifi列表的唯一方法:-( .

相关问题