What interval should I use between each WiFi scan on Android?
Asked Answered
L

2

7

I need to perform Wifi scans at regular intervals. I am encountering a problem when the time interval is set to 1-2 seconds. It seems like I am not getting any ScanResult. Is there a minimum amount of time to set so that the WifiManager is able to perform a successful WiFi scan?

Here is the code. I am using a Service to do the Wifi scan:

public class WifiScanning extends Service{
  private static final String TAG = "WifiScanning";
  private Timer timer;
  public int refreshRate, numberOfWifiScan, wifiScanGranularity;
  WifiReceiver receiverWifi = new WifiReceiver();
  WifiManager wifi;
  StringBuilder sb;
  List<ScanResult> wifiList;
  List<APData> apdataList;
  List<List<APData>>surveyData;

  private TimerTask updateTask = new TimerTask() {
    @Override
    public void run() {
      Log.i(TAG, "Timer task doing work");
      wifi.startScan();
    }
  };
  @Override
    public IBinder onBind(Intent intent) {
      // TODO Auto-generated method stub
      return null;
    }
  @Override
  public void onCreate() {
    super.onCreate();
    Log.i(TAG, "Service creating");
    //retrieve the mapRefreshRate from config.xml
    XMLOperations test = new XMLOperations();
    Configuration config = new Configuration();
    config = test.saxXmlParsing(this, 1);
    if(config==null)
      config = test.saxXmlParsing(this, 2);
    refreshRate = Integer.parseInt(config.getMapRefreshRate());
    numberOfWifiScan = Integer.parseInt(config.getNumberOfWifiScan_Positioning());
    wifiScanGranularity = Integer.parseInt(config.getWifiScanGranularity_Positioning());
    timer = new Timer();
    Log.i(TAG, "Refresh Rate: "+ String.valueOf(refreshRate));
    timer.schedule(updateTask, 0, refreshRate);
    wifi = (WifiManager) getSystemService(Context.WIFI_SERVICE);
    registerReceiver(receiverWifi, new IntentFilter(
    WifiManager.SCAN_RESULTS_AVAILABLE_ACTION));
  }
  @Override
  public void onDestroy() {
    super.onDestroy();
    Log.i(TAG, "Service destroying");
    unregisterReceiver(receiverWifi);
    if (timer != null){
      timer.cancel();
      timer.purge();
      timer = null;
    }
  }
  class WifiReceiver extends BroadcastReceiver {
    public void onReceive(Context c, Intent intent) {
      sb = new StringBuilder();
      wifiList = wifi.getScanResults();
      String ap_ssid;
      String ap_mac;
      Double ap_rssi;
      for(int i = 0; i < wifiList.size(); i++){
        ap_ssid = wifiList.get(i).SSID;
        ap_mac = wifiList.get(i).BSSID;
        ap_rssi = Double.valueOf(wifiList.get(i).level);
        APData ap = new APData(ap_ssid,ap_mac,ap_rssi);
        apdataList.add(ap);
        sb.append(" " + (wifiList.get(i).SSID).toString());
        sb.append(" " + (wifiList.get(i).BSSID).toString());
        sb.append((" " + String.valueOf(wifiList.get(i).level)));
        sb.append("\n");
      }
      Log.d(TAG, sb.toString());
      for(int i=1; i<=numberOfWifiScan; i++){
        surveyData.add(apdataList);
      }
    }
  }
}

However, I seem to get Nullpointer at this line: apdataList.add(ap);. So I wonder whether the interval is too short, which causes ScanResult to be empty?

Libre answered 2/10, 2011 at 7:11 Comment(1)
I would not conclude that your ScanResult List is empty. If it was the case, you would not enter your for loop (wifiList.size() would be 0). You should check why ap or apdataList is null in your code. I do not see apdataList=new List<APData>(); in your onCreate(). Might well be the reason.Kuhlman
O
13

EDIT after you posted your code:

apdataList does not seem to be initialized in onCreate()

add this to onCreate():

apdataList = new List<APData>();

Minimum scanning delay

I think that there is no absolute minimum scanning delay. It depends too much on the hardware performances.

My advice is that you add a 'As Fast As Possible' option to your preferences then use an asynchronous loop that relaunch a scan as soon as new results are found (see the code snippet below, it was updated to suit your needs). This way, it will only be limited by hardware performances.


Also you can poll the ScanResults using WifiManager.getScanResults() The recommended way is to launch WifiManager.startScan() and set up a BroadcastReceiver for WifiManager.SCAN_RESULTS_AVAILABLE_ACTION to be notified as soon as the scan results are ready.

Here's a sample code (borrowed from here and adapted to your needs):

IntentFilter i = new IntentFilter(); 
i.addAction (WifiManager.SCAN_RESULTS_AVAILABLE_ACTION); 
registerReceiver(new BroadcastReceiver(){ 
      public void onReceive(Context c, Intent i){ 
      // Code to execute when SCAN_RESULTS_AVAILABLE_ACTION event occurs 
      WifiManager w = (WifiManager) c.getApplicationContext().getSystemService(Context.WIFI_SERVICE); //Use getApplicationContext to prevent memory leak
      myScanResultHandler(w.getScanResults()); // your method to handle Scan results
      if (ScanAsFastAsPossible) w.startScan(); // relaunch scan immediately
      else { /* Schedule the scan to be run later here */}
      } 
    }, i ); 


    // Launch  wifiscanner the first time here (it will call the broadcast receiver above)
    WifiManager wm = (WifiManager)getApplicationContext.getSystemService(Context.WIFI_SERVICE); 
    boolean a = wm.startScan(); 
Olimpiaolin answered 2/10, 2011 at 7:43 Comment(6)
i have added my coding... Thats seems to be what i am doing. refreshRate can be set by user. Thus, i want to set a minimum value for that as currently i set to from 0-10sec.Libre
siily me... always forgotten to instantiate it. But still the what should be the minimum value i should set?Libre
@Libre see my edits (do not miss the edited source code)Kuhlman
it would means that the program would perform wifi scanning and yet is processing the scan result because i got two wifiscanner running? Cause what i am trying to do here to calculate user position based on the scan result and the time interval is suppose to be the map refresh rate. Truly test out the performance of the device...Libre
WifiManager.SCAN_RESULTS_AVAILABLE_ACTION can be used in SL4A (or Python for Android) by using droid.eventRegisterForBroadcast("android.net.wifi.SCAN_RESULTS") and then using eventWait or eventPoll to listen for the eventPhototube
Just wondering...would the system's own regular scanning interfere with this, or would the system reset its next scan to be N seconds after the last scan triggered, even if that scan were triggered by an app?Ambient
E
1

From Android 8 and higher, the limit is 4 times in 2 minutes. So you could scan 4 times with 1 second of delay in between. But you would not get any further scan results for the next 126 seconds.

So the fastest interval where every scan is successful would be every 30 seconds.

Enugu answered 30/11, 2020 at 12:30 Comment(1)
Could you share where this restriction is imposed (in AOSP source or document)?Recrement

© 2022 - 2024 — McMap. All rights reserved.