比WifiManager startScan()更快的WiFi扫描替代方法?

时间:2018-07-29 15:07:51

标签: java android android-wifi wifimanager

  • TL; DR版本

我需要每秒扫描几次并获得附近接入点的BSSID / MAC地址和信号电平。 WifiManager.startScan()扫描大约3.5秒,这有点慢。 (对于其他人来说,比6秒要好,但是对我来说仍然太慢)。 我正在寻找一种每200毫秒甚至更少的时间获取结果的方法。

  • 更详细的版本。

我正在尝试构建一个使用WiFi信号而不是GPS的定位应用。到目前为止,一切都很好,但我需要获取大量数据才能获得准确一致的结果。

我需要从我可以找到的每个访问点获取BSSID和信号电平,然后存储此数据以备后用。 我尝试使用WifiManager和BroadcastReceiver进行扫描并获取扫描结果。他们的问题是他们真的很慢。单次扫描至少需要3秒钟。在3秒钟内信号电平值将改变,导致结果不准确。我还需要进行几千次扫描,这将花费大量时间。到目前为止,我还没有找到其他选择。 我的手机当前正在运行Android 8.0.0

也许如果我优化代码,扫描将执行得更快?

onCreate方法:

@Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_sensor);

        btnMainActivity = (Button) findViewById(R.id.button_ToMainActivity);
        btnGetWifiInfo = (Button) findViewById(R.id.button_GetWifiInfo);
        textWifiInfo = findViewById(R.id.textView_wifiInfo);
        textWifiNr = findViewById(R.id.textView_wifiNr);

        mWifiManager = (WifiManager) getApplicationContext().getSystemService(Context.WIFI_SERVICE);
        mWifiReceiver = new BroadcastReceiver() {
            @Override
            public void onReceive(Context c, Intent intent) {
                getScanResultInfo();                   
                timeDifference = SystemClock.elapsedRealtime() - startTime;
                textWifiInfo.setText("Seconds elapsed: "+Double.toString(timeDifference /1000.0));
                nrOfScans++;
                if (nrOfScans < 10){
                    mWifiManager.startScan();
                }
            }
        };

        getWifiInfo();
        toMainActivity();

    }

public void getScanResultInfo(){
    int level;
    List<ScanResult> wifiScanList = mWifiManager.getScanResults();
    textWifiNr.setText("Nr of detected APs: "+ wifiScanList.size());
    for (ScanResult scanResult : wifiScanList) {
        level = WifiManager.calculateSignalLevel(scanResult.level, 5);
        Log.d("WIFI","Level is " + level + " out of 5 " + scanResult.level + " on " + scanResult.BSSID + "  ");            
    }
}

当我按下按钮时,扫描开始。

public void getWifiInfo(){
    btnGetWifiInfo.setOnClickListener(
            new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    finePermission = false;
                    startTime = SystemClock.elapsedRealtime();
                    nrOfScans = 0;
                    checkPermissions();
                    if ( finePermission == true){
                        ((WifiManager) getApplicationContext().getSystemService(WIFI_SERVICE)).startScan();
                        mWifiManager.startScan();
                    }
                    else {
                        Log.d("WIFI"," Missing Permissions: "+finePermission);
                    }
                }
            }
    );
}

提前感谢您的时间!

3 个答案:

答案 0 :(得分:3)

您可以使用隐藏的API startscanActive跳过被动通道扫描。 startScanActive不是android参考中公开的API;因此,使用它需要您自担风险。如果必须使用它,请参考此-https://github.com/mozilla/MozStumbler/issues/40

此外,请注意,如果顾名思义,如果API确实仅扫描主动通道,您将无法在扫描结果中让AP出现在被动通道上

答案 1 :(得分:3)

来自Android官方的坏消息 https://android.googlesource.com/platform/frameworks/base/+/478ee74428e04522d6ac0bf10c30ddaaf62028a4https://android.googlesource.com/platform/frameworks/opt/net/wifi/+/4f11976612567e57eefb0b58c7aef1059f52b45c 宣布(或建议?)从v9 Pie开始每次显着限制scanResult请求。 具体值应限制您的应用在2分钟之内最多4个scanResult请求

这将是所有现有WiFi-Tool应用程序的灾难/噩梦。 官方原因:安全的电池。

让我们团结一致,让他们知道我们希望Android作为瑞士军刀,而不是让它成为另一块白砖。

答案 2 :(得分:1)

  

我需要从每个接入点获取BSSID和信号电平   可以找到并存储这些数据以供以后使用

好消息是,您不需要使用此数据来构建自己的数据库。查看https://wigle.net