Device Discovery in Android - android

I am trying to create an application which can find all devices in local area network. I have been able to do it by pinging the IP range. Are there any other ways to do the same?
Is it possible to do detect devices in same network by listening to incoming packets in android ?

Following code will search the device and put their information in a list:-
//an array list of DeviceList type, which will take the info from getter setters
ArrayList<DeviceList> Dlist = new ArrayList<DeviceInfo>();
wifiManager wifi = (WifiManager) getSystemService(Context.WIFI_SERVICE);
if(wifi.isWifiEnabled()){
List<ScanResult>wifilist =wifi.getScanResults();
if(wifilist != null){
for(int m = 0; m < wifilist.size(); m++)
{
int signallevel = WifiManager.calculateSignalLevel(wifilist.get(m).level,20);
int signalStrength=(signallevel*100)/20;
DeviceList dInfo = new DeviceList();
dInfo.setDeviceName((wifilist.get(m).SSID));
dInfo.setSignalStrength(String.valueOf((signalStrength+"%")));
dInfo.setDeviceType("WiFi");
Dlist.add(dInfo);
}
}
and you'll need some getter setters for this. You can add them in a different class as follows:-
public class DeviceList {
String DeviceName="";
String SignalStrength="";
String deviceType="";
public String getDeviceName() {
return DeviceName;
}
public void setDeviceName(String deviceName) {
DeviceName = deviceName;
}
public String getSignalStrength() {
return SignalStrength;
}
public void setSignalStrength(String signalStrength) {
SignalStrength = signalStrength;
}
public String getDeviceType() {
return deviceType;
}
public void setDeviceType(String deviceType) {
this.deviceType = deviceType;
}
}

This depends on what you want to do with the devices.
To discover UPNP compatible devices, you could use the Cling library.
This will return a list of devices, descriptions and services available.
Pinging the IP range will only show devices that respond to ping, and could depend on the network setup.

Related

Android Wifi Roaming through AP with same SSID

I saw that Android system has a bad behavior with Wifi roaming.
We have a Wifi centralized network with many AP with a signle SSID.
The Adroid Phones wont roams seamlessly.
An Android Phone tries to stay connected to an AP until the signal reaches zero even if there are others AP (with the same SSID) with a good signal!
When the signal is zero, finally it performs an assosiation to another AP (with a good signal). But with this behavior the phone loses all the TCP Connections!
For example:
the phone is connected in WiFi to AP1
the phone moves in the building and now hears two signals from AP1 and from AP2.
When the signal form AP2 is stronger than the signal from AP1, i want that the phone do a reassosiation (not an assosiation) to AP2.
The idea is:
Perform a WifiManager.startScan()
Get the results WifiManager.getScanResults()
Find the best AP in the results
Perform a reassosiation to the best AP
Repeat every 30 seconds.
I talk about reassosiation because i don't want that the phone loses the TCP Connections.
There is a way to do this ?
Thank you,
Salvo
You cannot do this as you describe. A client cannot determine the state of the TCP connection on it's own. Your network must also move the communication channel from one AP to another. This can be done with the right network controllers.
Also, you should look at IEEE 802.11k -
https://en.wikipedia.org/wiki/IEEE_802.11k-2008
Add below permissions;
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
Register for below intent;
private WifiBroadcastReceiver wifiBroadcastReceiver = new WifiBroadcastReceiver();
Then in routine;
registerReceiver(wifiBroadcastReceiver, new IntentFilter("android.net.wifi.SCAN_RESULTS"));
Use the below class to change the reassociation;
public class WifiBroadcastReceiver extends BroadcastReceiver {
private WiFiManager manager = null;//set the value in constructor
private WifiConfiguration connectedConfiguration = null;//set the value in constructor
private int connectedNetId;
private void updateConnectedConfiguration(String ssid) {
configs = manager.getConfiguredNetworks();
int nid = 0;
for (WifiConfiguration cnf : configs) {
if (cnf.SSID.substring(1, cnf.SSID.length() - 1).equals(ssid)) {
connectedConfiguration = cnf;
connectedNetId = nid;
}
nid++;
}
}
public void onReceive(Context c, Intent intent) {
List<ScanResult> results = manager.getScanResults();
WifiInfo info = manager.getConnectionInfo();
ScanResult stronger = null;
for (ScanResult scanResult : results) {
try {
if (scanResult.SSID.equals(info.getSSID())) {
if (stronger == null) {
if (WifiManager.compareSignalLevel(info.getRssi() + 5, scanResult.level) < 0) {
stronger = scanResult;
}
} else if (WifiManager.compareSignalLevel(stronger.level, scanResult.level) < 0) {
stronger = scanResult;
}
}
} catch (Exception e) {
}
}
if (stronger != null && !stronger.BSSID.equals(info.getBSSID())) {
updateConnectedConfiguration(info.getSSID());
if (connectedConfiguration != null) {
connectedConfiguration.BSSID = stronger.BSSID;
manager.updateNetwork(connectedConfiguration);
manager.saveConfiguration();
manager.enableNetwork(connectedNetId, true);
manager.reassociate();
info = manager.getConnectionInfo();
//showNotification("\nConnecting " + stronger.SSID, stronger.BSSID + " " + stronger.level + "dBm");
}
}
}
}

How to differentiate Open and Secure WiFi networks without connecting to it in Android programmatically?

I am trying to develop a small app where I can scan and connect to the WiFi hot-spots from scanned list of networks. But for both, Open and Secure networks I have written a password prompt and if the network is open (by knowing it beforehand) I do not enter password and keep the text blank and enter and then it connects. Can anyone tell how to identify programmatically open and secure wifi so that I won't ask for password for Open network and let it connect directly. (I won't be knowing which is Open and Which is secure network in future, so we need to identify open and secure network from SSID or something)
Here you have capabilities field which is used to identify the network type
WifiManager wifimanger = (WifiManager) getSystemService(Context.WIFI_SERVICE);
List<ScanResult> networkList = wifimanger.getScanResults();
if (networkList != null) {
for (ScanResult network : networkList) {
String capabilities = network.capabilities;
Log.w(TAG, network.SSID + " capabilities : " + capabilities);
if (capabilities.toUpperCase().contains("WEP")) {
// WEP Network
} else if (capabilities.toUpperCase().contains("WPA")
|| capabilities.toUpperCase().contains("WPA2")) {
// WPA or WPA2 Network
} else {
// Open Network
}
}
}
Use this filter function to differentiate.
private boolean isProtectedNetwork(String capability){
return (capability.contains("WPA") ||
capability.contains("WEP") ||
capability.contains("WPS")
);
}
So when you have hold of all the List. Just iterate through it and add them in two different lists. (One for open and one for secure networks).
Here is the code for that
private void filterScan(List<ScanResult> allScanResults){
List<ScanResult>openScans = new ArrayList<ScanResult>();
List<ScanResult>closeScans = new ArrayList<ScanResult>();
for(ScanResult result : allScanResults)
{
if(!isProtectedNetwork(result.capabilities))
{
openScans.add(result);
}
else {
closeScans.add(result);
}
}
}
Useful Resource:
You can find more related solutions on My Github Repository
Today I was looking for an answer to this same question, but the solution pointed out here and in other similar questions made me a little insecure. And if a new security mode is created in the future?
For now I prefer to do something like:
public WifiSecurityMode testAgainstSecurityModes(WifiSecurityMode... securities) {
for (WifiSecurityMode security : securities) {
if (this.capabilities.toUpperCase().contains(security.getName().toUpperCase())) {
return security;
}
}
return WifiSecurityMode.UNKNOWN;
}
public enum WifiSecurityMode {
WEP("WEP"), WPA("WPA"), WPA2("WPA2"),//....
UNKNOWN ("UNKNOWN");
private String name;
WifiSecurityMode (String name){
this.name = name;
}
public String getName() {
return name;
}
}
//to use it: (WifiInfo are just a class I create to encapsulate the values in a ScanResult object)
public List<WifiInfo> getOpenWifis() {
List<WifiInfo> open = new ArrayList<>();
for (WifiInfo w : wifiInfoList) {
if (w.testAgainstSecurityModes(WifiSecurityMode.WEP, WifiSecurityMode.WPA, WifiSecurityMode.WPA2).equals(WifiSecurityMode.UNKNOWN)) {
open.add(w);
}
}
return open;
}
After that, you do what you want with UNKNOWN return.
If a new security mode be created in the future, you will not need to change testAgainstSecurityModes method.

Get listed bluetooth devices uuid with out pairing

I can list out bluetoothdevices available, but I am not getting the server bluetoothdevice's UUID.
my purpose is to list out number of bluetooth server (another android device/s) available. I am not even sure how can I recognize my server device/s from all the bluetoothdevices available.
For the first mensioned issue, I used fetchUuidsWithSdp() also, but I am getting nullvalue in the UUID broadcast receiver. Somebody please help,
Thanks in advance.
bluetooth = BluetoothAdapter.getDefaultAdapter();
if(bluetooth != null)
{
String status;
if (bluetooth.isEnabled()) {
String mydeviceaddress = bluetooth.getAddress();
String mydevicename = bluetooth.getName();
status = mydevicename + " : " + mydeviceaddress;
bluetooth.startDiscovery();
}
else
{
status = "Bluetooth is not Enabled.";
}
}
And in Broadcast Receiver
public class Receiver extends BroadcastReceiver
{
#Override
public void onReceive(Context context, Intent intent)
{
if (BluetoothDevice.ACTION_FOUND.equals(intent.getAction()))
{
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
String uuid = intent.getStringExtra(BluetoothDevice.EXTRA);
}
}

Android tether - get current SSID

Duplicate question - How to get my wifi hotspot ssid in my current android system
Sorry for duplicate this qustion, but it still doesn't have the answer. My mobile in tethering mode, so I want to know SSID of it. How can I find this one? Thanks a lot!
It's a bit late but i recently managed to get the SSID of the device's hotspot. It's working on my Galaxy Nexus, but haven't tested it quite much.
public static WifiConfiguration getWifiApConfiguration(final Context ctx) {
final WifiManager wifiManager = (WifiManager) ctx.getSystemService(Context.WIFI_SERVICE);
final Method m = getWifiManagerMethod("getWifiApConfiguration", wifiManager);
if(m != null) {
try {
return (WifiConfiguration) m.invoke(wifiManager);
} catch(Exception e) {
}
}
return null;
}
private static Method getWifiManagerMethod(final String methodName, final WifiManager wifiManager) {
final Method[] methods = wifiManager.getClass().getDeclaredMethods();
for (Method method : methods) {
if (method.getName().equals(methodName)) {
return method;
}
}
return null;
}
Just call getWifiApConfiguration(getActivity()).SSID to get the hotspot name. Nullpointer check is recommended before ;)
WifiManager mng = (WifiManager)context.getSystemService(Context.WIFI_SERVICE).
String currentSSID = mng.getConnectionInfo().getSSID()

android: Determine security type of wifi networks in range (without connecting to them)

I can enumerate all wifi networks in range (using startScan + SCAN_RESULTS_AVAILABLE_ACTION + getScanResults) and get their SSID and BSSID values, but I can't figure out how to determine the security type of each network.
In my main object:
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION);
registerReceiver(scanReceiver, intentFilter);
((WifiManager)getSystemService(Context.WIFI_SERVICE)).startScan();
In my scanReceiver object:
public void onReceive(Context c, Intent intent) {
if (WifiManager.SCAN_RESULTS_AVAILABLE_ACTION.equals(intent.getAction())){
mainObject.scanComplete();
}
}
And again in my main object:
public void scanComplete()
{
List<ScanResult> networkList = ((WifiManager)getSystemService.(Context.WIFI_SERVICE)).getScanResults();
for (ScanResult network : networkList)
{
<do stuff>
}
}
The code works insofar that scanComplete eventually gets called, and I can successfully enumerate all nearby wifi networks and get their SSID and BSSID, but I can't figure out how to determine their security type.
Is there a way to do this?
Thanks in advance.
I think you can find it in the source code of Settings.apk.
First you should call wifiManager.getConfiguredNetworks() or wifiManager.getScanResults(),
then use the two methods below: (find them in AccessPoint class "com.android.settings.wifi"):
static int getSecurity(WifiConfiguration config) {
if (config.allowedKeyManagement.get(KeyMgmt.WPA_PSK)) {
return SECURITY_PSK;
}
if (config.allowedKeyManagement.get(KeyMgmt.WPA_EAP) ||
config.allowedKeyManagement.get(KeyMgmt.IEEE8021X)) {
return SECURITY_EAP;
}
return (config.wepKeys[0] != null) ? SECURITY_WEP : SECURITY_NONE;
}
static int getSecurity(ScanResult result) {
if (result.capabilities.contains("WEP")) {
return SECURITY_WEP;
} else if (result.capabilities.contains("PSK")) {
return SECURITY_PSK;
} else if (result.capabilities.contains("EAP")) {
return SECURITY_EAP;
}
return SECURITY_NONE;
}
Hope this is helpful.
You need to parse the ScanResult's capabilities string in the scanComplete method. According to the Android developer documentation, :
ScanResult.capabilities describes the authentication, key management, and
encryption schemes supported by the access point.
You might be able to make use of -- or at the very least use as an example -- the static helper methods available in the AccessPointState class.
AccessPointState.getScanResultSecurity
AccessPointState.isEnterprise
Thanks very much,... you made my day...
I have something to add here. Without scanning for the networks, one can get the currently connected wifi configuration information (specially encryption and key management) as follows,
WifiManager wifi = (WifiManager) getSystemService(Context.WIFI_SERVICE);
List<ScanResult> networkList = wifi.getScanResults();
if (networkList != null) {
for (ScanResult network : networkList)
{
String Capabilities = network.capabilities;
Log.w (TAG, network.SSID + " capabilities : " + Capabilities);
}
}
The security type of each network is in the Capabilities column of the scan results.
So to get the security type for you, add this to your part of your code.
public void scanComplete()
{
List<ScanResult> networkList = ((WifiManager)getSystemService.(Context.WIFI_SERVICE)).getScanResults();
for (ScanResult network : networkList)
{
String Capabilities = network.capabilities;
//Then you could add some code to check for a specific security type.
if(Capabilities.contains("WPA"))
{
// We know there is WPA encryption
}
else if(Capabilities.contains("WEP"))
{
// We know there is WEP encryption
}
else
{
// Another type of security scheme, open wifi, captive portal, etc..
}
}
}
Anyways, here's some quick source code. I would fully recomment Ayj's answer though, as it is an exceptional response and more complete.

Categories

Resources