Filter the scan of WifiManager possible? - android

I am trying to scan the strength of several wireless signals. For that I use the WifiManager, in a loop I call startScan() and I have a broadcast receiver to get the results.
My question is:
How can I make a scan ONLY for some networks? In the results I get all the networks available. Can I filter the scan to search only for some bssids? or ssid? I don´t care about other values than the ones of my AP´s. And I need to do this scan with the highest frecuency possible.
Another thing is: when I call startScan again (500ms after the previous call) does it stop the scanning? Because I want to reduce to maximun the frequency of getting the signals streght and it seems that the results sometimes are incomplete??
Would it be possible to modify the source code of WifiManager class to filter the scan to some ids?
Thanks a lot!

No, you can't set a filter, but you can filter the results later on yourself, which should have not a big performance hit (filtering a list with < 100 entries). Also, from my experience, if you request a scan while a scan is already running, no new scan is initiated. Therefore there is no point in starting a new scan before the last scan has returned results. You also can't modify the WifiManager as it is part of the android platform.

Related

Understanding Android BLE ScanSettings parameters

The documentation around ScanSettings is very laconic and I'm having a hard time coming up with an optimal configurations.
My requirements dictate I should report a new advertisement packet that matches my filter criteria (filtered on service UUIDs) as soon as possible. Duplicate advertisement packets are of no use to me. The advertisement packets will change when the peripheral will register an event on its side and the advertisement packet is thus an opportunity for me to detect changes and act accordingly. I also need to know when the peripheral stopped advertising (powered off or not in range anymore).
I've tried to set the callback type like following:
setCallbackType(ScanSettings.CALLBACK_TYPE_FIRST_MATCH | ScanSettings.CALLBACK_TYPE_MATCH_LOST)
The documentation for this parameters says:
int CALLBACK_TYPE_ALL_MATCHES
Trigger a callback for every Bluetooth advertisement found that matches the filter criteria. If no filter is active, all advertisement packets are reported.
int CALLBACK_TYPE_FIRST_MATCH
A result callback is only triggered for the first advertisement packet received that matches the filter criteria.
int CALLBACK_TYPE_MATCH_LOST
Receive a callback when advertisements are no longer received from a device that has been previously reported by a first match callback.
I was hoping with this to get notified when the peripheral becomes available and then get notified when the peripheral is lost. However this doesn't trigger any scan results, at least not on my Pixel 2. So I just switched to use CALLBACK_TYPE_ALL_MATCHES and now I get all the advertisement packets. This is probably what I want anyways if I want to get updated packets from the same peripheral.
I looked at the setMatchMode parameters and it appears that this only configures the callbacks rate based on the signal strength:
int MATCH_MODE_AGGRESSIVE
In Aggressive mode, hw will determine a match sooner even with feeble signal strength and few number of sightings/match in a duration.
int MATCH_MODE_STICKY
For sticky mode, higher threshold of signal strength and sightings is required before reporting by hw
The setNumOfMatches claims to handle the number of advertisements per filter, but none of the documented parameters seem to make a difference, I still get a burst of packets from the same peripheral that didn't change, seemingly at about the same rate no matter the parameter.
To meet the part of my requirement where I need to determine if the peripheral stopped advertising (powered off or not in range) I came up with a timestamp of last seen packet from the peripheral and determine if the peripheral is lost or not when I don't see a packet for x amount of seconds. This was necessary because the CALLBACK_TYPE_FIRST_MATCH and CALLBACK_TYPE_MATCH_LOST don't seem to work at all.
This unfortunately means I get bursts of similar packets triggering a chain reaction in my code that I now have to deal with.
How can I configure the scanning so that I get notified only when the advertisement packet changes or the peripheral stopped advertising? Am I missing something here, or that's just not possible.
I've recently had to implement reacting to a device that stops advertising (updating a list of available BLE devices). The majority of my testing was also done on the Pixel 2.
I'm not sure you can receive a callback upon advertisement package change for a peripheral AND receive a callback when a peripheral stops advertising, although I have not tested this.
To receive a callback when the device stops advertising and stop the bombardment of callbacks for every packet, use :
Kotlin:
private val bleScanSettings =
ScanSettings.Builder().setCallbackType((ScanSettings.CALLBACK_TYPE_FIRST_MATCH or ScanSettings.CALLBACK_TYPE_MATCH_LOST)).build()
Java:
ScanSettings bleScanSettings = new ScanSettings().Builder.setCallbackType((ScanSettings.CALLBACK_TYPE_FIRST_MATCH | ScanSettings.CALLBACK_TYPE_MATCH_LOST)).build();
My code is in Kotlin, the Java code is what I think it should be and looks identical to yours. This configuration will trigger an error callback when scanning without a ScanFilter, could that be your original issue?
This configuration will trigger a callback upon receiving the first matching advertisement packet for a device as well as when a matched device stops advertising.
You could try to see if the matching callback is also triggered when the advertisement packet for a (previously matched) device changes. Otherwise, it seems impossible.
Set code like this:
new ScanSettings.Builder ()
.setScanMode (ScanSettings.SCAN_MODE_BALANCED)
.setCallbackType (ScanSettings.CALLBACK_TYPE_ALL_MATCHES)
.build (),...
This setting works on all devices. But each smartphone gives you a different error and this causes confusion.

Is it possible to do a partial Wifi Scan on Android?

I want to non-selectively be able to receive a subset of all Wifi routers' information in range of the Android device. However, in the WifiManager API I only see the getScanResults() method returning List (the results of the latest access point scan). Is there a way to get a subset of this list at the expense of smaller scan time?
There are no such APIs in WifiManager

Android Ble, Pheriperal Advertise status during the scan

In my application I need to start some BLE scans, get the results and then show them in a list or in a grid.
When i start the scan my device start to look for advertisements basing on which ScanFilters I wrote.
Every time a Pheriperal is found I the application trigger the scan callback method and i can add the new device into the list.
If i got an error the app trigger the callback method and i can tell the user about the broblem.
Example
Imagine the Scan going on for 30s.
At the moment it starts i get 3 Ble Pheriperal.
At second 15 one of them stop to advertise and turn bluetooth off.
At the end of the scan my list will have 3 Ble devices but i will not be able to connect to one of them.
How do I know which of them is the one which turned off?
Where do i get his status?
Thanks for the help.
You can try this, technically it is possible as per the documentation. in onScanResult callback, check for the callbackType parameter. If it is CALLBACK_TYPE_MATCH_LOST then get the device from the results and remove it from your cache.

BluetoothAdapter: How do I know if no BLE devices are found after startLeScan()?

I am developing an Android app to record the RSSI fluctuations from a BLE beacon. I use the startLeScan(BluetoothAdapter.LeScanCallback callback) method and from the callback get the RSSI value every time the beacon is discovered (till I have some MAX_NUM values). Then I call stopLeScan().
However, I also want to know whenever the app performs a scan but is unable to discover the beacon during this period. As I understand, this will result in the onLeScan() callback not being invoked. How can I do this?

How to get wifi signal strength of a router in android program in real time?

Using BroadcastReceiver() in wifimanger,i am able to get RSSI strength for every 4-5 seconds.
But i need it in real time.
Can i get the strength in real time?
Your best bet would be to start a scan with the WifiManager getScanResults:
final WifiManager wifi = (WifiManager) getSystemService(Context.WIFI_SERVICE);
List<ScanResult> results = wifi.getScanResults();
However, note that it returns the latest results which might be sooner or later than 4-5 seconds ago. But at least you obtain the most recent results.
Edit
You cannot get signal strength results in real time because there is no continuous scan.
If you must, you can initiate a scan with startScan, but you will have to wait for the asynchronous event sent on completion of the scan.
I was trying to do the same thing and I found a decent solution.
If you use an Asynchronous task and run a loop that gets an updated RSSI on every iteration, you can update the UI with onProgressUpdate().
I added a Thread.sleep(500) in my loop so it updates every half second.
If you have more questions I'd be glad to help.

Categories

Resources