Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Faster WiFi scanning alternative than WifiManager startScan()?

  • TL;DR version

I need to scan and get the BSSID / M.A.C address and Signal Level of the nearby Access Points several times a second. WifiManager.startScan() scans about 3.5 seconds which is a bit slow. (better than 6 seconds for others but still too slow for me). I'm looking for a way to get results every 200ms or maybe even less.

  • The more detailed version.

I'm trying to build a location finding app that uses WiFi signals instead of the GPS. So far so good with the exception that i need to get a lot of data in order to have accurate and consistent results.

I need to get the BSSID and the Signal Level from every Access Point I can find and than store this data for later use. I've tried using the WifiManager and the BroadcastReceiver to scan and get the scan results. The problem with them is that they are really slow. It takes at least 3 seconds for a single scan. In 3 seconds signal level value will change , leading to inaccurate results. I also need to have several thousand scans which will take an awful loooot of time. So far I haven't found an alternative. My phone is currently running Android 8.0.0

Perhaps if I optimise my code the scan will perform faster?

onCreate method:

@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 + "  ");            
    }
}

And when I press the button the scan starts.

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);
                    }
                }
            }
    );
}

Thank you in advance for your time!

like image 604
Bogdan Mihai Avatar asked Jul 29 '18 15:07

Bogdan Mihai


2 Answers

You can skip passive channel scanning by using the hidden API, startscanActive. startScanActive is not an exposed API in android reference; so use it at your own risk. If you must use it, refer this - https://github.com/mozilla/MozStumbler/issues/40

Also, note that if the API indeed scans only active channels as the name suggests, you will not be able to get APs present on passive channels in your scan results

like image 150
Viral Modi Avatar answered Oct 13 '22 01:10

Viral Modi


Bad news from official Android side https://android.googlesource.com/platform/frameworks/base/+/478ee74428e04522d6ac0bf10c30ddaaf62028a4 and https://android.googlesource.com/platform/frameworks/opt/net/wifi/+/4f11976612567e57eefb0b58c7aef1059f52b45c announce (or propose?) to significantly limit scanResult requests per time from v9 Pie on. In concrete values, your app should be limited to max 4 scanResult requests in 2 minutes.

This will be a disaster/nightmare for all existing WiFi-Tool apps. Official reason: safe battery.

Let's unite our voices and let them know we want Android as a Swiss Army knife and not let it become another white brick.

like image 45
Markus G Avatar answered Oct 12 '22 23:10

Markus G