I am looking for a programmatic way on Android to determine whether the WIFI my device is currently connected to is "secured" using either WEP, WPA, or WPA2. I've tried Google searching and I cannot find a programmatic way to determine this. I've also looked at the TelephonyManager (http://developer.android.com/reference/android/telephony/TelephonyManager.html) which also lacks this information.
Thanks,
J
There is a way using the ScanResult object.
Something like this:
WifiManager wifi = (WifiManager) getSystemService(Context.WIFI_SERVICE);
List<ScanResult> networkList = wifi.getScanResults();
//get current connected SSID for comparison to ScanResult
WifiInfo wi = wifi.getConnectionInfo();
String currentSSID = wi.getSSID();
if (networkList != null) {
for (ScanResult network : networkList) {
//check if current connected SSID
if (currentSSID.equals(network.SSID)) {
//get capabilities of current connection
String capabilities = network.capabilities;
Log.d(TAG, network.SSID + " capabilities : " + capabilities);
if (capabilities.contains("WPA2")) {
//do something
} else if (capabilities.contains("WPA")) {
//do something
} else if (capabilities.contains("WEP")) {
//do something
}
}
}
}
References:
http://developer.android.com/reference/android/net/wifi/WifiManager.html#getScanResults()
http://developer.android.com/reference/android/net/wifi/ScanResult.html#capabilities
http://developer.android.com/reference/android/net/wifi/WifiInfo.html
android: Determine security type of wifi networks in range (without connecting to them)
ScanResult capabilities interpretation
Related
I am developing an Android App. The app will keep trying to connect to an dedicated WiFi AP when started. This is working. However when I tested to power off the AP, so the app must have been disconnected from the AP, my app still return the SSID of the AP when I use WifiManager.getConnectionInfo().getSSID() to check the SSID, why? And how can I update the current SSID when it is not connected, even it return "unknown ssid"?
Below is the method I check the SSID, the app will invoke this method continuously:
WifiManager wifiManager; // <- In MainAativity
// ....
int checkWiFiSSID() {
wifiManager = (WifiManager) getSystemService(Context.WIFI_SERVICE);
if (!wifiManager.isWifiEnabled()) {
Log.d(TAG, "WiFi is disabled, enable it now");
wifiManager.setWifiEnabled(true);
} else {
WifiInfo wifiInfo = wifiManager.getConnectionInfo();
String ssid = wifiInfo.getSSID();
// This line always show the AP SSID even the AP is powered down, why??
Log.d(TAG, "AP SSID: " + ssid);
}
}
Thank you.
UPDATE:
Having read the document carefully, I found that if the WifiManager is trying to connect to an AP, even it is not connected, the getSSID() will return its SSID. As my app is keep trying to connect to the AP once it is disconnected. I guess this is the reason, but I am not sure.
I'm trying to connect to a WiFi hotspot (open network) which doesn't have Internet access when the app starts.
However, there's another saved Wifi which has Internet. When I turn on Wifi, it always connects automatically to the one with Internet access.
I have been trying to fix this issue for like a week now! But nothing is working. In fact, my code disconnects from the network with internet but doesn't connect to the network I want. It doesn't make sense.
On the WiFi settings activity, it says "No Internet detected. Won't reconnect automatically."
private boolean tryConnect(WifiManager wifiManager, List<ScanResult> scanResults) {
for (ScanResult scanResult : scanResults) {
Log.d(TAG, "SCAN-RESULT: " + scanResult);
if (scanResult.SSID.toLowerCase().contains(MainActivity.ARDRONE2_HOTSPOT_NAME) && WifiUtilities.getScanResultSecurity(scanResult) == WifiUtilities.NetworkSecurity.OPEN) {
Log.d(TAG, "Trying Connecting to ARDrone2");
WifiConfiguration wifiConfiguration = new WifiConfiguration();
wifiConfiguration.SSID = String.format("\"%s\"", scanResult.SSID);
wifiConfiguration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
wifiConfiguration.priority = Integer.MAX_VALUE - 1;
List<WifiConfiguration> wifiConfigList = wifiManager.getConfiguredNetworks();
int networkId = -1;
for (WifiConfiguration wifiConfig : wifiConfigList) {
if (wifiConfig != null) {
if (wifiConfig.SSID.equals("\"" + scanResult.SSID + "\"")) {
networkId = wifiConfig.networkId;
} else {
wifiManager.disableNetwork(wifiConfig.networkId);
}
}
}
if (networkId == -1) {
networkId = wifiManager.addNetwork(wifiConfiguration);
} else {
networkId = wifiManager.updateNetwork(wifiConfiguration);;
}
wifiManager.saveConfiguration();
wifiManager.disconnect();
wifiManager.enableNetwork(networkId, true);
wifiManager.reconnect();
return true;
}
}
return false;
}
The debug log: "Trying Connecting to ARDrone2" appears and yet it doesn not connect!!!
A similar question has been asked here Android, automatically connecting to wifi networks that have no internet access but no comments or answers were provided.
It seems like the problem was with my own phone. I have CM13.0 and apparently they don't allow connecting to networks that don't have Internet access. Even manual connecting to a network without Internet is a lot of trouble.
I tried it on other phones with non-custom ROMs and they all worked as expected according to the code above:
Disable all saved networks (this could be improved)
Disconnect from currently connected network
Connect to the ARDrone2
I have a method to detect available wifi access ppoints. My method works well but when I am not in the range I still getiing the SSID of the last scan results displayed in my xml file though I am out of the range of this SSID.
private void check_wifi_available() {
WifiManager wifi = (WifiManager) getSystemService(Context.WIFI_SERVICE);
if (!wifi.isWifiEnabled()) {
Toast.makeText(this, "Please turn your Wi-Fi on",
Toast.LENGTH_SHORT).show();
}
WifiManager wifiManager = (WifiManager) getSystemService(Context.WIFI_SERVICE);
final List<ScanResult> results = wifiManager.getScanResults();
if (results != null) {
// list of access points from the last scan
List<ScanResult> updatedResults = new ArrayList<ScanResult>();
// pick Wi-Fi access points which begins with these "SV-"
// characters.
for (int i = 0; i < results.size(); i++) {
String ssid = results.get(i).SSID;
// Pattern p = Pattern.compile("^KD-(4[0-9]{2}|500)$");
// Matcher m = p.matcher(ssid);
// if(m.matches()){}else{}
if (ssid.startsWith("KD")) {
updatedResults.add(results.get(i));
}
}
if (updatedResults.size() > 0) {
String a = deliverBestAccessPoint(updatedResults);
textWifi.setText(a.toString());
}
}
}
This is best handled by the operating system. The best you could do is set up a timer to periodically scan for WiFi devices and update the results.
Other than that, on rooted devices you may be able to manually send 802.11 requests to the access point/router and do a timeout check for replies.
To clarify: the operating system, when it is scanning for devices, sends out a broadcast message and reports what devices it hears back from. When devices are toward the edge of the 'range' they may report as being available even if connecting and maintaining a connection is problematic because the signal is not strong enough.
EDIT:
For what it's worth, ScanResult has a "level" member variable that reports the signal strength. You could do some more fine filtering for low-strength results. http://developer.android.com/reference/android/net/wifi/ScanResult.html
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.
I am writing an application to display the WiFi network types and status. How do I find all the "not in range" WiFi networks? Is it possible to get the list of all configured (previously seen) WiFi networks that are out of range?
I used the below code to get the result
WifiManager mWifiManager = (WifiManager) getSystemService(Context.WIFI_SERVICE);
List<WifiConfiguration> configs = mWifiManager.getConfiguredNetworks();
List<ScanResult> results = mWifiManager.getScanResults();
if (configs != null) {
for (WifiConfiguration config : configs) {
for (ScanResult result : results) {
if (result.SSID == null || result.SSID.length() == 0) {
continue;
}
else {
if (result.SSID.equals(MyString.removeDoubleQuotes(config.SSID))) {
int level = mWifiManager.CalculateSignalLevel(result.level, 4);
Log.d("MyApp", Config.SSID + " " + level);
}
}
}
}
}
But if configured network is high in number then it will take long time to execute. Is there any way to optimize this problem? By getting the scanned result of only the configured network.
How about subtracting the wifi networks in range from all wifi networks?