Android Getting WiFi signal strength as it changes - android

I want to get the Signal strength of the WiFi network I am connected to , as it changes .
This is my broadcast receiver
registerReceiver(new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
int info = Wifi.getConnectionInfo().getRssi();
textStatus.append("\n\n : " + Integer.toString(info));
}
}, new IntentFilter(WifiManager.RSSI_CHANGED_ACTION));
I am getting it only once . How do i get it as it changes ?

Update: From tests in Android 4.4 and 5.0 the interval between sequential WiFi scans seems to be less than a second. You can take a look at my demo for RF measurements using Android device, here:
https://github.com/panosvas/Measurements
where you can find an implementation of WiFi measurements one after another. I have also created a Server for storing these measurements as well as a remote trigger app using UDP packets where you can find here:
https://github.com/panosvas/IndoorPositioningServer
Actually, you cannot take the RSSI each time it changes because it is possible that the RSSI value changes in a period of mseconds or even faster and each wifi measurement in Android takes approximately 5 seconds depending also on the device.
So, what you advice my answers in the following posts for that:
Wifi Scanner which scans 20 times
How to update wifi RSSI values without a click button

Related

Different interval time between BLE device advertising and the callback from startScan of android phone

I use android phone to detect a beacon using startScan method, the interval time of beacon adversing is 800ms, but I got the beacon data from callback of startScan every 3~10 seconds. My expectation is I can get the data every 1 second.
Below is my codes. So is there any other ways to get my expectation. Or someone can explain why the interval time is not the same as the adversing time ?
ScanSettings.Builder builder = new ScanSettings.Builder()
.setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY);
// scan filters has been set the right value.
bluetoothLeScanner.startScan(scanFilters, builder.build(), scanCallback);
Nothing about the code shown is a problem. I can confirm your expectation is met with equivalent code in other apps on other devices. This suggests a problem with :
Your BLE device not advertising as often as you expect
Your Android phone (possible but unlikely)
Some other aspect of your code that you did not show in your question.
Is you BLE device a beacon? If so, I suggest:
Install BeaconScope on the same phone, scan for your beacon, then check the PPS rating (Packets Per Second -- scan for at least 30 seconds until the measurement stabilizes). If you see a value of 0.1-0.3 then the problem is NOT with your code and must be (1) or (2). If you see a much higher PPS value, the problem is with some other aspect of your code not shown.
Use a second Android phone with BeaconScope as a transmitter and transmit a beacon at the 10 Hz default rate. Does your app get a packet every 100-200ms? If so, you have confirmed the problem is with your BLE device not transmitting as much as you expect.
If your BLE device is not a beacon you can at least perform the second test.
It's recommended to use 'SCAN_MODE_LOW_LATENCY' mode only hen the application is running in the foreground.
Incase you are in background, you can run a sticky foreground service and set a periodic frequency of 1 sec for your service.
Also scanning Ble for every 1 sec might be extremely heavy for the app.

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.

How to get Bluetooth connection Link Rate android

In android application we can get WiFi connection link rate using wifiInfo.getLinkSpeed() method.
But is there any way to get Bluetooth connection Link Rate? Any API or method available for this?
I worked on Bluetooth applications and I had the same need as yours but I didn't find a solution to get the Bluetooth connection speed in mbps.
So, this solution may not give you an exact value for Bluetooth link rate as you requested, but it actually gives you a reference to the Bluetooth link quality (good, medium, bad) using the Received Signal Strength Indicator (RSSI).
To read the value of your Bluetooth RSSI, you should add a BroadcastReceiver to your class :
private final BroadcastReceiver receiver = new BroadcastReceiver(){
#Override
public void onReceive(Context context, Intent intent) {
if(BluetoothDevice.ACTION_FOUND.equals(intent.getAction())) {
//Get the RSSI value here
int rssi = intent.getShortExtra(BluetoothDevice.EXTRA_RSSI,Short.MIN_VALUE);
}
}
};
Your receiver has to be registered using :
registerReceiver(receiver, new IntentFilter(BluetoothDevice.ACTION_FOUND));
Now, you need to know that the data transfer speed increases as the RSSI value increases , so, all you have to do is to define a range for each link quality.
PS: Refer to this link to learn more about RSSI values for Bluetooth Bluetooth RSSI values are always in dBm in all Android devices?
Hope this helps :)
The short answer is no such interface.
The long answer is, the speed in Bluetooth is vary due to hardware and software difference for different device, e.g. BR/EDR/BLE, and Bluetooth only defined the maximum speed data for BR/EDR/BLE. for most cases, the Bluetooth link does not transport user data(except you are listening music or calling), but just keep the link, so it is no meaning for Bluetooth to evaluate the link speed(at least for end user).

Does BLE support pinging?

Is BLE supporting pinging, i.e. sending a message to other devices and receiving their status?
I want to write an app on Android, which will ping each of the nearby devices and calculate the time between sending time and receiving answer, is it possible?
As you pointed out in your comment you like to use as time-of-arrival or time-difference-of-arrival algorithm to calculate the distance based on bluetooth.
To my knowledge this is currently more a theoretical approach in a bluetooth environment. As radio signals travel at light speed (~29.979 cm in one nanosecond) you will need a high sampling resolution to get a accurate result. Each nanosecound deviation will cause an error of roughly 30 cm.
With WiFi this is accomplished with a specalized chipset. To my knowledge this is currently not possibile with android as it would need a lot of low level support (Chipset and OS)
Hope this helps!
here are some sources
Android relative positioning, Wifi:Time of Arrival
Evaluation of indoor positioning based on
Bluetooth Smart technology - page 76
You can easily see the timestamp of discovery for each device in your onScanResult method:
#Override
public void onScanResult(int callbackType, ScanResult result){
Long lastSeen = result.getTimestampNanos();
//rest of your code
}
See the Android Documentation. You can use this timestamp and the time that you started your scan to get an approximate response time for each device.

Data logging with the GPS and Bluetooth(App development)

I'm working on a personal electronics project and I would like to create an app to log GPS data in addition to several other things.
The project is an automatic bicycle derailleur (it will shift gears automatically based on a number of factors such as speed, pedal cadence, gyroscope angle, etc). In addition I would like to create an app which will log things like speed, routes taken, number of hours ridden, etc. To save money, I would like to use my Android phone as both a screen for displaying some of these vitals as well as logging data with the GPS.
I'm very new to Android development, but my question is this: Would it be possible to tell the phone to automatically begin logging data (and possibly open the app, depending on what I decide) once it has been connected to the bike via bluetooth? And concurrently, I'd like it to stop and close the app once it's been disconnected.
Thanks
The problem as I see it, is how you plan on connecting to the bike's Bluetooth radio. Typically an application will initiate a Bluetooth connection (which is different from pairing.) Running a service in the background looking for your Bluetooth device and connecting typically wouldn't be a good solution because searching for Bluetooth devices is very resource intensive.
You might be better off just having the connection initiate when the user starts the app.
The second part, to stop the app once the connection is dropped (becomes out of range, or the device on the bike drops the connection,) is quite straight forward. Make a broadcast receiver:
public class DisconnectBroadcastReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(BasicDMMView.this, "Device disconnected!", Toast.LENGTH_SHORT).show();
// Close anything you need to (log files etc.)
finish();
}
}
And then register the receiver once you've opened the bt connection:
IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_ACL_DISCONNECTED);
mReceiver = new DisconnectBroadcastReceiver();
registerReceiver(mReceiver, filter);
And don't forget to unregister the receiver when you leave the Activity:
unregisterReceiver(mReceiver);

Categories

Resources