ReactiveWiFi
ReactiveWiFi copied to clipboard
Too much callbacks when observing "observeWifiAccessPoints"
I'm using ReactiveWifiLocal.observeWifiAccessPoints(context)
everything works well except that I'm receiving too much events, and it is causing high cpu load, lags and battery drain.
I can handle it partially by using .throttleFirst(SAMPLING_TIME, TimeUnit.SECONDS)
but anyway the library it-selves receives callbacks in BroadcastReceiver
I suggest to do something like
public static Observable<List<ScanResult>> observeWifiAccessPoints(final Context context,final int scanInterval) {
final WifiManager wifiManager = (WifiManager) context.getApplicationContext().getSystemService(Context.WIFI_SERVICE);
wifiManager.startScan(); // without starting scan, we may never receive any scan results
final IntentFilter filter = new IntentFilter();
filter.addAction(WifiManager.RSSI_CHANGED_ACTION);
filter.addAction(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION);
return Observable.create(new Observable.OnSubscribe<List<ScanResult>>() {
@Override
public void call(final Subscriber<? super List<ScanResult>> subscriber) {
final BroadcastReceiver receiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
AndroidSchedulers.mainThread().createWorker().schedule(new Action0() {
@Override
public void call() {
wifiManager.startScan(); // we need to start scan again to get fresh results ASAP
}
}, scanInterval, TimeUnit.SECONDS);
subscriber.onNext(wifiManager.getScanResults());
}
};
context.registerReceiver(receiver, filter);
subscriber.add(unsubscribeInUiThread(new Action0() {
@Override
public void call() {
context.unregisterReceiver(receiver);
}
}));
}
});
}
This is how often I get updates:
10-30 13:31:29.051 28695-28695/br.com.oitchau D/WiFiListener: mark as available 8 items 10-30 13:31:29.118 28695-28695/br.com.oitchau D/WiFiListener: mark as available 8 items 10-30 13:31:29.159 28695-28695/br.com.oitchau D/WiFiListener: mark as available 8 items 10-30 13:31:29.199 28695-28695/br.com.oitchau D/WiFiListener: mark as available 8 items 10-30 13:31:29.304 28695-28695/br.com.oitchau D/WiFiListener: mark as available 8 items 10-30 13:31:29.358 28695-28695/br.com.oitchau D/WiFiListener: mark as available 8 items 10-30 13:31:29.396 28695-28695/br.com.oitchau D/WiFiListener: mark as available 8 items 10-30 13:31:29.426 28695-28695/br.com.oitchau D/WiFiListener: mark as available 8 items 10-30 13:31:29.465 28695-28695/br.com.oitchau D/WiFiListener: mark as available 8 items 10-30 13:31:29.499 28695-28695/br.com.oitchau D/WiFiListener: mark as available 8 items 10-30 13:31:29.538 28695-28695/br.com.oitchau D/WiFiListener: mark as available 8 items 10-30 13:31:29.580 28695-28695/br.com.oitchau D/WiFiListener: mark as available 8 items 10-30 13:31:29.626 28695-28695/br.com.oitchau D/WiFiListener: mark as available 8 items
Hi,
Thanks for reporting this issue. I'll take a closer look on that. Generally, we cannot really control the time, when new set of the access points will be delivered. It depends on Android and a specific device. I'll analyze this issue in the free time and try to figure out if it's possible to improve it. Please note, even if we add scan interval, delivery of the results is a separate thing and we never know, when we receive them even when the scan will be delayed.
Regards, Piotr
Thanks for quick reply, I tested above mentioned solution, looks like when you don't call wifiManager.startScan();
after receiving data in broadcast receiver the system wont send you updates
That's correct. I know it's not the best solution, but it's the only solution I know, which allows to receive updates about access points continuously. If you call wifiManger.startScan();
once, you'll get results only once.
You can build another observable on top of that for your specific use case. E.g. you can store unique APs somewhere (in the memory, database, shared prefs, etc.) and then subscribe the new observable for data changes so you won't be flooded by incoming scan results all the time.
var disposable: Disposable? = null
disposable = ReactiveWifi.observeWifiAccessPoints(applicationContext)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe({ scanResults ->
// logic
disposable?.dispose()
})
I'm using ReactiveWifi.observeWifiAccessPoints(context) to fetch the list of access points in my android app. Everything works fine when device is in unlock mode. If device goes to lock mode, access points list do not update and it gives previously captured list i.e., captured in unlock mode. When i come back from lock mode to unlock mode, app freezes for few seconds and after few seconds it get resumes & works normally. I need help to get list of access points when my phone is in lock mode.
I've added screenshot of logs below.
Hi @akashgowda0110. I was AFK. I'm not sure about behavior and monitoring capabilities in "lock mode". Maybe Android OS is blocking scanning in this mode due to performance or energy saving reasons. It's reasonable for me. Have you put scanning code in the Service
? IMO in the Activity
it shouldn't work in "locked mode" by design. Moreover, the issue mentioned by you is different than this one.
Thank you. As you told, Android OS which was blocking for energy saving reason. Works fine with Naugat and below versions of android. Oreo version of android having problem with this.