Android Long Running Wi-Fi Scanning Service

Viewed 748

I have been following https://developer.android.com/guide/topics/connectivity/wifi-scan guide in order to create a Wi-Fi scanner. I am using a foreground service with a handler to call wifiMananger.startScan(); every 30 seconds (I tried with 15 minutes).

Everything works great for about 2 hours then suddenly WifiManager.EXTRA_RESULTS_UPDATED boolean returns false and the wifiManager.getScanResults() are not getting updated. Then as soon as the phone is plugged in it starts sending results again. (No, it is not low on battery)

I have battery optimization turned off. I have all of the required permissions allowed. Locations is turned on with Wi-Fi scanning enabled. The device I'm testing on is a Samsung S7 Edge running Android 8. So I know it's not the new OS. (I also tested with a Nokia 5.1 running Android 10 with pretty much the same results).

Does anyone know why this is happening or has anyone encountered this issue before?

Thanks in advance.

2 Answers

Updated: In case of your problem, since you are using exactly 30 seconds due to some problem there might be more than 4 time in a 2 minutes period, make it like 35 seconds and test the result.

Original Answer: From this WifiManager startScan throttled in P Beta (Developer Preview 2) :

"Call Limitations - Throttling

We are further limiting the number of scans apps can request to improve network performance and improve battery life.

The WifiManager.startScan() usage is limited to:

  • Each foreground app is restricted to 4 scans every 2 minutes.
  • All background apps combined are restricted to one scan every 30 minutes."

It is said that this restriction is due to the battery drain, so it is normal to remove the restriction while charging. Read more about throttling in official documentation.

This is because Android OS enters the infamous "Doze mode". I recommend you to look through the official documentation/explanation.

Unfortunately, there is no way around this. It will also affect any kind of a foreground service and pause it for longer periods. Doze mode will only trigger if the screen is locked and the device is not plugged in.

I encountered the same issue on my project and we implemented a periodic check. If the screen is locked and device not plugged in for a longer period of time, we show a notification asking the user to either plug the device in or open the app so the service could keep working. The implementation is a bit lengthy, but if it is what you decide to go with, I can update the answer with some of the code (using the AlarmManager within a BroadcastReceiver to achieve this).

Related