Connecting to WiFi network automatically in Android 5 and 6 - android

Been struggling with connecting to WiFi network in Android 5 and 6 for a while and other similar questions don't seem to work for me. I could get the same code working in Android 4.4.2
Adding the code snippet below.
String networkSSID = getSsid();
String networkPass = getNetworkPass();
WifiConfiguration conf = new WifiConfiguration();
conf.SSID = "\"" + networkSSID + "\"";
conf.status = WifiConfiguration.Status.ENABLED;
conf.priority = 40;
conf.allowedProtocols.set(WifiConfiguration.Protocol.RSN);
conf.allowedProtocols.set(WifiConfiguration.Protocol.WPA);
conf.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK);
conf.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP);
conf.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.TKIP);
conf.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP40);
conf.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP104);
conf.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP);
conf.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.TKIP);
conf.preSharedKey = "\""+ networkPass +"\"";
int value = mWifiManager.addNetwork(conf);
Log.i(TAG_CHECK, "Connecting to : " + value);
boolean enabled = mWifiManager.enableNetwork(value, true);
Log.i(TAG_CHECK, "enabled to : " + enabled);
mWifiManager.reconnect();
And here is what I noticed.
mWifiManager.addNetwork(conf)
returns some (+) integer with Android 5(phone) and Android 6(tab).
But both don't connect unless I open the wifi settings (I don't have to do anything and just landing there connects) or I manually turn off and turn on Wifi from the top bar to automatically connect.
The listeners to detect connection to the network are in tact for both the versions to precisely know when the connection get established - confirming the above behaviour. Have attached a pic of the permissions granted below.
Any pointers as to what I am missing?
EDIT: Upon digging into WifiManager class, looks like the Access Point remains in WIFI_AP_STATE_DISABLED state. I should also highlight that everything worked as expected while trying on a different Android M phone.
EDIT2
I have the following observations.
1. The issue so far is specific to 1 android 6.0.1 Samsung tablet and 1 android 5.0.2 Micromax phone. It works just fine on 3 other android 6.0.1 phones, 1 android N phone and Android 4.4.2 phone.
2. The access point ends up in wifi_ap_disabled state in the problematic cases consistently. Both addNetwork and enableNetwork calls are affirmative.
3. These access points are not that of a router wifi but that of other phones that broadcast. The problematic phones can programatically connect to wifi hotspots (setup manually and not in the programatic way as I would like to) without any issue.
4. Mobile data enabled/disabled state or wifi state with a different connected network doesn't change the dynamics for both working and problematic phones.
This makes me think that it is a combination of phones/tabs (and not OS) and the access point broadcast configuration. Do you think I should be playing around with some config parameters?
Edit 3 - Important Update
So the wifimanager is obtained like below
WifiManager mWifiManager = (WifiManager) getSystemService(Context.WIFI_SERVICE);
I instantiate mWifiManager in a service (inside onCreate method) and use that later to scan and connect with inputs from front-end activity. While it doesn't work in the way as described earlier, using the same snippet seems to work when the enableNetwork call is done right in the onCreate method - working just as expected. It also works fine when called from front-end activity but only when I don't instantiate mWifiManager in the service.
Though I would expect only one reference to a system service - WifiManager i.e, I think the subsequent usage of that reference (or a different reference to WifiManager) gets a lower priority (or gets deprioritized by the previous reference) and hence doesn't get completely executed leaving the access point in disabled state and requiring manual intervention to help complete the execution by WifiManager and other wifi system services.
Also, I notice the same in Android 5.0.2 phone, the asynchronous enableNetwork does get executed, but it takes some time to execute it.
My questions
1. It is no more a question about the correctness of the code. Services in general have lesser priority compared to front-end threads So, is there is way I could prioritise the enableNetwork call so that it gets immediately executed?
2. What happens in case of multiple references to WifiManager?

I believe if you add a disconnect() it will do what you want. I've added a check here because addNetwork() can fail to add your network. For Android 6.0+, you can't add a network if it exists already but if this fails you can try getting the network id then connecting. (For instance, it will be there if added (and saved) if you re-install) I also do not add quotes to SSID in Lollipop (ver 21)+.
int value = mWifiManager.addNetwork(conf);
// need to check the result if successful
if (value == -1) {
return; // network not added successfully
}
Log.i(TAG_CHECK, "Connecting to : " + value);
mWifiManager.disconnect(); // add a disconnect
boolean enabled = mWifiManager.enableNetwork(value, true);
Log.i(TAG_CHECK, "enabled to : " + enabled);
mWifiManager.reconnect();

Related

WiFiManager EnableNetwork() not working on android 10

On android 10 mobile phone. I seldom engaged in an issue.
The Enablenetwork() function doesn't work.
Here is some code
WifiConfiguration Config = new WifiConfiguration();
Config.Ssid = "\"" + SSID + "\"";
temp = WiFi.AddNetwork(Config);
WiFi.SaveConfiguration();
bool Enable_Success = WiFi.EnableNetwork(temp, true);
On my device(Samsung s9, android 10)
The function just sometimes works. Sometimes not working.
When not working. I observe the wifi status of my phone.
The wifi just keep connecting to current connected SSID.
Not even tried to connected to target SSID. Just keep it's current status.
What would be the problem?
Thank you!
Maybe you can try disconnect other network first.
wifiManager.disconnect();// disconnect first
WifiConfiguration Config = new WifiConfiguration();
Config.Ssid = "\"" + SSID + "\"";
temp = WiFi.AddNetwork(Config);
WiFi.SaveConfiguration();
bool Enable_Success = WiFi.EnableNetwork(temp, true);
Assuming that the network is open (meaning without any password), then you need to explicitly say it in the configuration object.
Config.AllowedKeyManagement.Set((int)KeyManagementType.None);
Android 10 uses a different set of functions to connect to wifi than previous versions of Android. You will want to do something like this:
var connectivity_manager = GetSystemService(Context.ConnectivityService) as ConnectivityManager;
var wifi_network_specifier = (new WifiNetworkSpecifier.Builder()).SetSsid(ssid).Build();
var network_request = (new NetworkRequest.Builder()).AddTransportType(TransportType.Wifi)
.SetNetworkSpecifier(wifi_network_specifier).Build();
connectivity_manager.RequestNetwork(network_request, network_callback);
Note that this code assumes an open network. If you have a WPA network, you can add the password to the WifiNetworkSpecifier.Builder. Also, as far as I can tell, the new WifiNetworkSpecifier.Builder does not support WEP networks. So, if you are attempting to programmatically connect to a WEP network with Android 10, you may have a difficult time.

WifiManager enableNetwork reverts to previous network after a few seconds

On Android 8.1.0 and above, I am coming up against a major issue.
When connecting to a network with no internet using enableNetwork, Android decides after a few seconds to put the device back on the previous network.
I have intentionally connected to the network desired and am planning to use bindToNetwork to ensure that all traffic goes through the network, however Android appears to be ignoring the bind and simply disconnecting very quickly afterwards.
I have seen a few permutations of this question being asked here, all with no replies, unfortunately.
I am creating an connecting to the network with the following code. I am able to see the network connecting.
WifiConfiguration conf = new WifiConfiguration();
conf.SSID = desiredSSID;
if (desiredNetwork.has("password")) {
conf.preSharedKey = String.format("\"%s\"", desiredNetwork.get("password"));
}
conf.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.TKIP);
conf.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP);
conf.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK);
conf.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.TKIP);
conf.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP);
conf.allowedProtocols.set(WifiConfiguration.Protocol.RSN);
int networkID = wifiManager.addNetwork(conf);
wifiManager.enableNetwork(networkID, true);
Is there an available option to disable this behaviour, as I intentionally connecting to a network with no internet available.
Thanks.
I was able to resolve this issue by removing the existing config from the configured wifi list. The network will not disconnect from a new config.
List<WifiConfiguration> wifiConfigurationList = wifiManager.getConfiguredNetworks();
for (WifiConfiguration removeConfig : wifiConfigurationList) {
if (removeConfig.SSID.equals(desiredSSID)) {
wifiManager.removeNetwork(removeConfig.networkId);
break;
}
}
Simply adding the network again, as above fixes the issue.

Discover specific Bluetooth Low Energy Service by UUID in Android

Does anyone know how to discover a BLE Service by UUID in Android? There is a discoverServices() method in Android, but there seems to be no way to discover one individual Service instead of all of them. In Bluetooth, discovering all Services takes a 'long' time, whereas discovering individual Services based on UUID does not take as long. It takes even longer for Android because Android also discovers all the Characteristics and Descriptors as well.
TL;DR: you can't - if you don't want to do some really ugly and potentially dangerous hack.
There is no easy way to do this. If you look at what discoverServices() does on Nougat, you'll see it calls GattService:L1454.
void discoverServices(int clientIf, String address) {
enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
Integer connId = mClientMap.connIdByAddress(clientIf, address);
if (DBG) Log.d(TAG, "discoverServices() - address=" + address + ", connId=" + connId);
if (connId != null)
gattClientSearchServiceNative(connId, true, 0, 0);
else
Log.e(TAG, "discoverServices() - No connection for " + address + "...");
}
The key here is gattClientSearchServiceNative:
gattClientSearchServiceNative(int conn_id,
boolean search_all,
long service_uuid_lsb,
long service_uuid_msb)
If search_all is true, it will scan everything. If not, it will search only a service with the provided UUID and its characteristics and descriptors.
You could actually try and use reflection to call this directly passing a false search_all parameter and a valid UUID, but that's a really bad practice and will end up crashing when a new version comes out and the internal implementation of this class changes.

Android WifiManager making a phantom connection?

I'm using WifiManager to test for the presence of a particular SSID and verify a given WPA password, but I'm getting a weird result.
The code looks like this:
WifiConfiguration wc = new WifiConfiguration();
// init ssid and password as Strings ...
wc.SSID = "\"" + ssid + "\"";
wc2.preSharedKey = "\"" + password + "\"";
wc.hiddenSSID = true;
wc.status = WifiConfiguration.Status.ENABLED;
wc.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.TKIP);
wc.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP);
wc.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK);
wc.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.TKIP);
wc.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP);
wc.allowedProtocols.set(WifiConfiguration.Protocol.RSN);
int res = wifi.addNetwork(wc);
boolean b = wifi.enableNetwork(res, true);
The weird part is that enableNetwork() returns true, even if the wifi network with SSID is not online (?!). Note, however, that if the target Wifi network is present and the password is correct, the code successfully makes the connection.
The Android documentation says enableNetwork() "returns true if the operation succeeded." My questions are:
1) How can the network have been enabled if it's not even there?
2) Have I initialized the WifiConfiguration parameter, wc, incorrectly?
3) Is this the right way to make/test a connection to a Wifi network?
1) How can the network have been enabled if it's not even there?
The Android documentation says enableNetwork() "returns true if the operation succeeded."
They actually mean that the enabling operation has been successfully initiated, it has't crashed... This could return false if the wifi instance is not linked any more to the wifi supplicant.
2) Have I initialized the WifiConfiguration parameter, wc, incorrectly?
I am not sure, but it looks alright.
3) Is this the right way to make/test a connection to a Wifi network?
Before enabling the network, you should check if the network is actually available by using the startScan() method. (You will get a list of SSID in the callback).
You should also use a BroadcastReceiver to get the result from the Intent action NETWORK_STATE_CHANGED_ACTION, where you could check if your connection to the access point is successful or not.

Manually starting 3G connection in Android, and keeping it on

How do you start the 3G data connection in Android at the same time WiFi is on? I tried
IConnectivityManager.setMobileDataEnabled(enabled); // via reflection
and it works in the emulator, but in my real phone (Droid 2), it briefly turns on then back off again.
From the shell (adb shell), ip link provides the details of the 3G connection:
15: ppp0: <POINTOPOINT,MULTICAST,NOARP,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UNKNOWN qlen 3 link/ppp
However, it is only available when WiFi is off. When WiFi is on and I try to turn it on manually, it complains the ppp0 device doesn't exist.
bash-3.2# ip link set ppp0 up
ip link set ppp0 up
Cannot find device "ppp0"
When I try to list the device, I can't even find it
bash-3.2# ls /dev/ppp*
ls /dev/ppp*
/dev/ppp
As I understand it's not possible to get 3g and WiFi simultaneously connected without modifying Android platform source code (at least versions 2.3 and 4). The main problem is hardcoded priorities of connections defined in frameworks/base/core/res/res/values/config.xml:
<!-- This string array should be overridden by the device to present a list of network
attributes. This is used by the connectivity manager to decide which networks can coexist
based on the hardware -->
<!-- An Array of "[Connection name],[ConnectivityManager connection type],
[associated radio-type],[priority] -->
<!-- ^^^^^^^^^^---------- Connection priority -->
<string-array translatable="false" name="networkAttributes">
<item>"wifi,1,1,1"</item>
<item>"mobile,0,0,0"</item>
<item>"mobile_mms,2,0,2"</item>
<item>"mobile_supl,3,0,2"</item>
<item>"mobile_hipri,5,0,3"</item>
</string-array>
This config.xml is then read by ConnectivityService which is subscribed to connect/disconnect events. And in connect handler it decides what it should do with other connections:
private void handleConnect(NetworkInfo info) {
//------------8-<--------------------------
// if this is a default net and other default is running
// kill the one not preferred
if (mNetAttributes[type].isDefault()) {
if (mActiveDefaultNetwork != -1 && mActiveDefaultNetwork != type) {
if ((type != mNetworkPreference &&
mNetAttributes[mActiveDefaultNetwork].mPriority >
// ^^^^^^^^^ --- From config.xml
mNetAttributes[type].mPriority) ||
// ^^^^^^^^^-------- From config.xml
mNetworkPreference == mActiveDefaultNetwork) {
// don't accept this one
if (DBG) Slog.v(TAG, "Not broadcasting CONNECT_ACTION " +
"to torn down network " + info.getTypeName());
teardown(thisNet);
return;
//------------8-<--------------------------
You could try keeping both active at the same time by modifying your connectivityservice,
but I'd advice against it, since it'll most likely destroy your battery life.
See here if you want to give it a try anyway (and make sure you have a backup, obviously)
If you're trying to connect to a specific machine you can try ConnectivityManager.requestRouteToHost.

Categories

Resources