I've been trying to use the new Android WiFi Suggestion API with the code taken exactly from the example, but each time I try to connect to a network, when I call wifiManager.addNetworkSuggestions(suggestionsList) I get status 3 in response, which (according to this site) means IP provision failure. What does that mean? How can I handle that?
My app has all the required permissions and even some more (CHANGE_WIFI_STATE, ACCESS_WIFI_STATE, INTERNET, ACCESS_FINE_LOCATION, CHANGE_NETWORK_STATE, ACCESS_NETWORK_STATE), and the location is turned on. I tried with a few WiFi networks (all are visible in the WiFi settings), but still got the same IP provisioning error.
Had the same issue and found it quite confusing because status = 3 can mean two things: STATUS_SUGGESTION_APPROVAL_REJECTED_BY_USER or STATUS_NETWORK_SUGGESTIONS_ERROR_ADD_DUPLICATE.
In my case it was the latter. Basically the suggestion is remembered once submitted. I solved this by removing my suggestion before it's added:
wifiManager.removeNetworkSuggestions(suggestions)
val status = wifiManager.addNetworkSuggestions(suggestions)
Related
Up to API lvl 29 we have been using WifiConfiguration to set up wifi connections with our DPC (both device and Profile Owner modes). Since API lvl 29 we can still save Open, WEP, WPA networks, but any attempt of saving EAP network is completely ignored. We tried to use WifiSuggestions method and the suggestion is properly displayed in the notification bar, but when the user taps on "allow" - nothing happens. There are no errors in the log, addNetworkSuggestions() method returns STATUS_NETWORK_SUGGESTIONS_SUCCESS.
This problem exists only when our DPC is provided Device/Profile Owner permissions with full provisioning process (work profile creation or fully managed during the first start). Getting Device Owner status using ADB lets us save the network by allowing the network suggestion.
This is how we set up the network suggestion:
#RequiresApi(api = Build.VERSION_CODES.Q)
public static WifiNetworkSuggestion setupWifiNetworkSuggestion (WifiConfiguration wifiConfiguration){
return new WifiNetworkSuggestion.Builder()
.setSsid(wifiConfiguration.SSID)
.setIsHiddenSsid(wifiConfiguration.hiddenSSID)
.setWpa2EnterpriseConfig(wifiConfiguration.enterpriseConfig)
.build();
}
after that we call:
List<WifiNetworkSuggestion> networkSuggestionList = new ArrayList<>();
networkSuggestionList.add(setupWifiNetworkSuggestion(wifiConfiguration));
int status = mWifiManager.addNetworkSuggestions(networkSuggestionList);
if (status != WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS) {
_logger.error("Problem adding network suggestion, status code: " + status);
}
Are we missing something? The same code works in our other app where we do not use EMM provisioning to get Device Owner. All the requested permissions are the same in both apps. We tried to get some error info or set up some logs but we only get success statuses all the way.
We finally made it work! The problem was caused by three separate issues:
We were lacking allowed key management setting WifiConfiguration.KeyMgmt.WPA_EAP
Our test RADIUS server rejects connection attempts when any domain is provided in the enterprise config. It was giving us unnecessary disconnections even at the point when we resolved Android-side issues
MOST IMPORTANT: For some reason our password policy was not enforced and on test environment we use self-signed certificates. Without at least PIN-lock set up on the device, the certificates cannot be attached to the network profile, therefore it cannot be added/connected to. Even if the network is saved, it lacks the certificate which has to be selected manually (it is deployed properly to the certificate store, though)
WiFi networks added through addNetworkSuggestions do not appear on the system-provided list of saved WiFi networks. But if the device sees the WiFi, it will add a note that this network was suggested by this and that app. Then the user can connect with the WPA Enterprise credentials configured in the code.
From my understanding, it is expected behavior that nothing happens that the user could see.
Also, if you uninstall the app, the suggested networks disappear again.
As a Device Owner, you should be able to use the otherwise deprecated WifiManager.AddNetwork() method to add the network to the system list. I haven't tested that myself.
On Android 12 (but not with 10 and 11), you can ask the user to add a network to the system list using this code:
var suggestionsList = new WifiNetworkSuggestion[]
{
networkSuggestion
};
Bundle bundle = new Bundle();
bundle.PutParcelableArrayList(
Android.Provider.Settings.ExtraWifiNetworkList,
suggestionsList
);
Intent intent = new Intent(Android.Provider.Settings.ActionWifiAddNetworks);
intent.PutExtras(bundle);
intent.AddFlags(ActivityFlags.NewTask);
Android.App.Application.Context.StartActivity(intent);
I am trying to read the Preferred network type setting from the device. But nowhere android API's are available.
Use case:
Trying to read the Preferred network type and connected network type so that if the device has LTE enabled and the user is forcefully switched back to the lower network(3G,2G); then there should be a notification sent to the user.
I have checked the system setting code, But it's deprecated.
Settings.Secure.getString(getApplicationContext().getContentResolver(),
Settings.System.NETWORK_PREFERENCE);
Is there any alternate way to read the system secured settings(By reflection?).
And Also is it possible to write back the setting with the user permission?
Help is much appreciated.
I think the right code is:
Settings.Global.getString(context.getContentResolver(),Settings.Global.NETWORK_PREFERENCE)
this has many similar questions (google for: "no internet access detected. won't automatically reconnect." or: android force wifi connection programmatically).
i thought i had a answer here, but it stopped working after installing 6.0.1 updates (i have may 1 security patches).
seems like this is a behaviour change.
i have some 2013 nexus 7's with 6.0.1 that run a kiosk type app and want to connect programmatically to a specific wireless network that has no internet connection. each tablet has a unique static ip address of the form: 192.168.0.xx. i use the normal java socket constructors and check to see if the interface is up using: NetworkInterface.getNetworkInterfaces().
a manual connection has been made. sometimes there is a dialog that asks whether or not you want to always connect. i always check yes.
but the wifi says: "no internet access detected. won't automatically reconnect" after the router cycles power.
doing a disconnect, enable, reconnect does not work. at best it gets: ip6-localhost/::1.
has anyone had any luck using a request object, or bindProcessToNetwork?
edit: related.
edit: the problem seems to be with: CAPTIVE_PORTAL_DETECTION_ENABLED - this string seems to be defined in the source:
public static final String
CAPTIVE_PORTAL_DETECTION_ENABLED = "captive_portal_detection_enabled";
...
MOVED_TO_GLOBAL.add(Settings.Global.CAPTIVE_PORTAL_DETECTION_ENABLED);
but throws" android.provider.Settings$SettingNotFoundException: captive_portal_detection_enabled when used explicitly and is not visible to android studio.
also, doing a settings list global does not contain the constant.
edit doing a adb shell settings put global captive_portal_detection_enabled 0 does seem to work, but this can not be done in the field when the router cycles power. this value seems to persist when the tablet cycles power. and now this value shows up in a settings list global. also, using the raw string: Settings.Global.getInt(getContentResolver(),"captive_portal_detection_enabled"); now returns 0.
edit: looks like setting it requires: android.permission.WRITE_SECURE_SETTINGS, but of course this fails when put into the manifest since we are not a system app.
edit: trying to exec the shell command throws: java.lang.SecurityException, so it looks like you need to issue the command from adb :(
thanks
Could you try and set the global setting captive_portal_detection_enabled to 0 (false).
What's actually happening is that by default, everytime you connect to a wifi, the FW will test against a server (typically google) to see if it's a captive wifi (needs login). So if your wifi is not connected to google, this check will fail. After that, the device knows that wifi has no internet connection and simply will not autoconnect to it.
Setting this setting to 0, will avoid this check.
Programatically Settings.Global.putInt(getContentResolver(), Settings.Global.CAPTIVE_PORTAL_DETECTION_ENABLED, 0);
You can do it through adb for testing purposes:
adb shell settings put global captive_portal_detection_enabled 0
And retrieve it's value like this:
adb shell settings list global | grep "captive"
IMHO this is not very nice thing to do, since you are changing a setting for the user and many FWs don't provide even an advanced setting to enable/disable this by the user itself. (Google doesn't). But maybe it suits your needs.
Hope it helps!
A non-root solution which is a kind of hack tech. :P
Reboot phone, connect to the non-Internet Wifi;
Go to Settings and create a new user;
Continue, continue, and continue until you see "Checking connection";
As soon as you see "checking connection", switch off your phone;
Switch on your phone again, you will be in "Owner" user, keep it;
Toggle Wifi, and the exclamation mark should disappear quickly :)
Remove that new user or just leave it there;
I don't know why, but it works...
I was under the impression that wifiManager.getConfiguredNetworks() returns the PNL of the current device, however when I click on - forget network, wifiManager.getConfiguredNetworks() still keeps that network but just removes the connection details(like security, password etc.)
Is there anyway knowing which SSID(or BSSID) is actually in PNL? (i.e my device can automatically connect to it)
I found out that this problem appeared only on specifics networks, while in others clicking on forget network actually removes the network from wifiManager.getConfiguredNetworks().
I also found out that the only things different are allowedKeyManagement.cardinality and LinkProperties (which is hidden on Android), so I used an if statement on the WifiConfiguration(=configuredNetwork):
if(configuredNetwork.allowedKeyManagement.cardinality()==1)
wifiManager.removeNetwork(configuredNetwork.networkId);
wifiManager.saveConfiguration();
break;
And for some reason it worked. If anyone have an idea whats cardinality stands for or have a better way of doing this please share.
i am trying to develop a cordova(3.5.0) project in android platform and in that i have to check network connection availability before each API call. for that i am using 'navigator.connection.type',and some times it return 0. why this is happening? plz help me for solving this trouble
Without some more details I can only guess.. There are some conditions which may cause this.
navigator.connection.type = 0 -> connection type unknown.
So you may have a connection, you may not it simply hasn't been determined yet, or because of privileges the device isn't saying.
Are you calling this check too early? ie before deviceready
In our app we do not check the connection each time but we handle it this way:
by making the API request anyway, knowing that its possible to fail, we set a timeout and error handling. If it fails by error or timeout we check connection type and then ping the server with a simple "hello" "acknowledge" request. Its a super small request that we figure will work or if it timeouts again the connection must be so poor it might as well be disconnected.
This is because there are really two types of connection you need to check. Many miss this!
And also because its navigator totally lies some times... :/
Just because wifi is on and connected and navigator tells you this, it doesn't mean you will have a connection to the outside world. You need to check the network hardware (which is all navigator will tell you) but you must also check network connectivity, if this is something you are sensitive about.