Recently I found a seemingly cool way to communicate between devices using Google Nearby API. Skimming through the documentation didn't answer my question - is it possible to measure the connection signal strength in real time, or should I invent some kludges e.g. measuring time of sending and receiving data or something else?
Thank you.
As a developer of Nearby API stated in thread Google Nearby Messages - Cancel initial link between devices :
Today, Nearby doesn't expose distance directly
He suggests to use BLE RSII instead
You can get a rough approximation of distance by measuring BLE RSSI if one of the devices is capable of BLE advertising. This will be sensitive to how the device is held, antenna gain and environmental factors but better than random.
There's not a straight-forward "tape measure" API, though.
If your question really is about "Nearby Connection API" and not "Nearby Messages API", you could simply check the Wifi-Signal Strength:
WifiManager wifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
int numberOfLevels = 5;
WifiInfo wifiInfo = wifiManager.getConnectionInfo();
int level = WifiManager.calculateSignalLevel(wifiInfo.getRssi(), numberOfLevels);
Related
Google introduced a set of limitations in Android 8 or 9 regarding Wi-Fi scanning frequency. Apps are restricted in how frequently they're able to scan for Wi-Fi connections, including P2P Wi-Fi peers. What is the situation with Wi-Fi Aware? Does it have the same limitation? Is it easier to bypass it?
This answer is as per the latest comments by OP.
One way to keep track of the RSSI of the network is to register for the intent RSSI_CHANGED_ACTION using a BroadcastReceiver and then extract the raw RSSI values from the Intent's extra values which are stored with the key Wi-FiManager.EXTRA_NEW_RSSI and obtain the threshold levels(usually the workable values) using calculateSignalLevel(). Some approximate code:
} else if (action.equals(WifiManager.RSSI_CHANGED_ACTION)) {
// Default to -200 as its below WifiManager.MIN_RSSI.
int rawRssi = intent.getIntExtra(WifiManager.EXTRA_NEW_RSSI, -200);
int rssiLevel = mWifiManager.calculateSignalLevel(rawRssi);
}
Also, to answer the previous question as to whether Wi-Fi aware is restricted by the same scan restrictions, the answer is 'no', not because it has a waiver vis-a-vis Wi-Fi-Direct but because it operates differently from a Wi-Fi-Direct connection. For a Wi-Fi Direct connection, one needs to make a request() to the WifiManager for initiating a scan and it is these scans that are throttled, with the duration of throttling varying based on whether the app is in foreground/background. This throttling can of course be overridden from the Developer Settings page.
Wi-Fi-Aware works with a different paradigm. If this is regarding the usage of ranging, then one can leverage Wi-Fi-Aware technology between two devices as follows:
Check whether ranging is supported using Wi-Fi-RTTI apis using context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WIFI_RTT);
Check whether Wi-Fi RTT is available by registering for the intent WifiRttManager.ACTION_WIFI_RTT_STATE_CHANGED and on its receipt, check for whether Wi-Fi RTT is available.
Create a ranging request
Start ranging
Extract rssi from a successful ranging result.
One thing to note is that the requests for ranging are limited to 20 from each UID as per this code from the framework.
static final int MAX_QUEUED_PER_UID = 20;
Note that if you're running as a regular application, your app would have its own UID.
How can I get the direction and the strength of all the nearby Wifi ?
Till now I have been able to get Wifi Strength in Level but only of connected wifi using following code
WifiManager wifiManager = (WifiManager)getSystemService(Context.WIFI_SERVICE);
int numberOfLevels = 5;
WifiInfo wifiInfo = wifiManager.getConnectionInfo();
int level = WifiManager.calculateSignalLevel(wifiInfo.getRssi(), numberOfLevels);
I am trying to do something like this
Play Store App Link
This app gives nearby wifi plot on campas
Can anyone guide my how this is possible?
Short answer "not possible".
Long answer is that the phone gives just the strength of the incoming signal, which can come from any direction. You can not even estimate the distance to the WiFi access point until you know its signal strength with your phone for some known distance. You can however estimate the direction of where the WiFi access point is from movement of your phone and the differences of the WiFi signal strength changes.
The app you linked to tells you to start scanning and then slowly rotate. That is needed for recording the device orientation and the signal strength changes. Then based on the orientation of the device and the signal strength for that orientation it can estimated where the WiFi access point is. I am not connected with that app in any way, nor I have used it. All this information is based on the app's screenshots and general knowledge of how WiFi works.
Then there are other funny things like WiFi access points which can send a stronger signal in a specific direction when it detects a device with low signal.
To find distance you can try:
public double calculateDistance(double signalLevelInDb, double freqInMHz) {
double exp = (27.55 - (20 * Math.log10(freqInMHz)) + Math.abs(signalLevelInDb)) / 20.0;
return Math.pow(10.0, exp);
}
I am working on an app that would allow indoor navigation using hardware devices that emit wifi signals in large public places such as hotels and hospitals. Each location would have multiple devices and each device would be unique so that we can identify the exact location of the device/person.
For this I don't want the user to connect to the wifi, if only a scan of the network was possible which could determine the current wifi beacon the mobile is closest to would do the job. I decided to use Android's WifiManager for the task:
WifiManager wifi = (WifiManager) getSystemService(Context.WIFI_SERVICE);
wifi.setWifiEnabled(true);
wifi.startScan() ;
List<ScanResult> mScanResults = wifi.getScanResults();
String s = "" ;
for(ScanResult result: mScanResults){
Log.d("Wifi", result.SSID) ;
}
None of the attributes for result seem to be appropriate for use as a UID for Wifi Beacon, I have two questions:
a) Can we use something like a BSSID for this purpose?
b) Can I write my own wifi manager class and then somehow negotiate a handshake with the wifi where it just tells me who it is without connecting? If so please share resources for doing the same.
I am trying to create a help wizard to recover from bad network connections in the app. One test case I hope to handle is the case where an end user has WiFi turned off, WiFi is available, and the mobile network is slower than the WiFi network. In this event, I want to be able to (1) discover the available WiFi network s, (2) find the WiFi network speed, (3) Compare its speed to the mobile network speed, (4) digest the user changes to the faster network.
For this to work, I need to know how to programmatically get information on available connections. Is that something we can do? If so, how can we tell what connections are available? Thanks in advance.
Task-1: Discover the available WiFi network
This can be done by getting WifiManager's instance from the System.
WifiManager wifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
wifiManager.getScanResults();
// The above is an async call and will results are available System will broadcast `SCAN_RESULTS_AVAILABLE` intent and you need to set a `BroadCastReceiver` for it.
// And get the results like this
List<ScanResult> results = wifiManager.getScanResults();
Task-2&3: find the network speed
This link gives an answer to your question about how to get network speeds of wifi and mobile network
Wifi:
WifiManager wifiManager = (WifiManager)context.getSystemService(Context.WIFI_SERVICE);
int linkSpeed = wifiManager.getConnectionInfo().getRssi();
In case of mobile it should work:
TelephonyManager telephonyManager = (TelephonyManager)this.getSystemService(Context.TELEPHONY_SERVICE);
CellInfoGsm cellinfogsm = (CellInfoGsm)telephonyManager.getAllCellInfo().get(0);
CellSignalStrengthGsm cellSignalStrengthGsm = cellinfogsm.getCellSignalStrength();
cellSignalStrengthGsm.getDbm();
Then You should compare this signal levels and if WIFI signal is better keep it turn on, but if mobile is better disconnect wifi
Task-4: Switching to the option with higher speed
In Android by default, if wifi is on and connected then your mobile network won't be used. Hence to use mobile data you must either disconnect from all available wifi-networks or switch off the wifi.
I will also suggest you to read link this, this and this for getting more information on how to get connection speed.
Company http://renewlondon.com/ have the terminal stations that collect all near by mac addresses
Can I via iOS SDK, and Android SDK,do the same thing?
You can access the wifi data using 'WifiManager' and after the scanning the scanresult contain all the data like
BSSID The address of the access point.
SSID The network name.
capabilities Describes the authentication, key management, and encryption schemes supported by the access point.
frequency The frequency in MHz of the channel over which the client is communicating with the access point.
level The detected signal level in dBm.
timestamp Time Synchronization Function (tsf) timestamp in microseconds when this result was last seen.
about the wifi devices.
if you need more related to coding, I think I can help you...
Sample code
WifiManager wManager;
List<ScanResult> wifiList;
wManager = (WifiManager) getSystemService(Context.WIFI_SERVICE);
// Inside BroadcastReceiver()
wifiList = wManager.getScanResults();
for (int i=0; i<wifiList.size(); i++){
ScanResult scanresult = wifiList.get(i);
System.out.println("SSID: "+ssid);
System.out.println("RSSI: "+scanresult.level);
System.out.println("Frequency: "+scanresult.frequency);
System.out.println("BSSID: "+scanresult.BSSID);
System.out.println("Capability: "+scanresult.capabilities);
}
Also checkout the BroadcastReceiver().
One way i can think of doing this is making your device as wifi hotspot and use some hidden api to discover devices.You are basically trying to mimic an access point.
Otherwise each device would need some p2p framework on them-either wifi direct on or some other framework like alljoyn or samsung chord which helps in peer to peer discovery