Какой интервал следует использовать между каждым сканированием WiFi на Android? - PullRequest
7 голосов
/ 02 октября 2011

Мне нужно регулярно выполнять сканирование Wi-Fi. Я сталкиваюсь с проблемой, когда временной интервал установлен на 1-2 секунды. Кажется, я не получаю ScanResult. Существует ли минимальное количество времени для установки, чтобы WifiManager мог успешно выполнить сканирование WiFi?

Вот код. Я использую Service для сканирования Wifi:

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

Однако, я, кажется, получаю Nullpointer в этой строке: apdataList.add(ap);. Так что мне интересно, слишком ли короткий интервал, из-за чего ScanResult будет пустым?

1 Ответ

13 голосов
/ 02 октября 2011

РЕДАКТИРОВАТЬ после того, как вы опубликовали свой код:

apdataList, похоже, не инициализирован в onCreate ()

добавить это в onCreate ():

apdataList = new List<APData>();

Минимальная задержка сканирования

Я думаю, что нет абсолютной минимальной задержки сканирования.Это слишком сильно зависит от производительности оборудования.

Я советую вам добавить опцию «Как можно быстрее» в ваши предпочтения, а затем использовать асинхронный цикл, который перезапускает сканирование, как только обнаруживаются новые результаты (см.фрагмент кода ниже, он был обновлен в соответствии с вашими потребностями).Таким образом, он будет ограничен только аппаратными характеристиками.


Также вы можете опросить ScanResults, используя WifiManager.getScanResults() Рекомендуемый способ - запустить WifiManager.startScan() и настроитьBroadcastReceiver для WifiManager.SCAN_RESULTS_AVAILABLE_ACTION должен быть уведомлен, как только будут получены результаты сканирования.

Вот пример кода (заимствованный отсюда и адаптированный к вашим потребностям):

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(); 
...