I'm totaly lost in the versions of WiFi APIs.
I want to connect to a configured WiFi Network programmaticaly.
As decribed in this question:
Connect to wifi network Android programmatically
I develop on Android 10 and want to write a code that is also compatible with older Android Versions.
On my android 10 the code described does not work.
What code do I need to implement the functionality on Android 10?
What do I do to write an application that also runs on my other Android 9 phone?
Regards Jürgen
From Android Q, connecting to Wifi Network has changes a lot.
First of all the code you are using or #matdev mentioned uses API public int addNetwork (WifiConfiguration config) from WifiManager is deprecated in Android 10 and will return -1 as networkID.
From Android Q, two classes are suggested for Wifi connection. But each of them has its own advantage and disadvantage.
1. WifiNetworkSpecifier
A code example from WifiUtil Library
WifiNetworkSpecifier.Builder wifiNetworkSpecifierBuilder = new WifiNetworkSpecifier.Builder()
.setSsid(scanResult.SSID)
.setBssid(MacAddress.fromString(scanResult.BSSID));
final String security = ConfigSecurities.getSecurity(scanResult);
ConfigSecurities.setupWifiNetworkSpecifierSecurities(wifiNetworkSpecifierBuilder, security, password);
NetworkRequest networkRequest = new NetworkRequest.Builder()
.addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
.setNetworkSpecifier(wifiNetworkSpecifierBuilder.build())
.build();
// not sure, if this is needed
if (networkCallback != null) {
connectivityManager.unregisterNetworkCallback(networkCallback);
}
networkCallback = new ConnectivityManager.NetworkCallback() {
#Override
public void onAvailable(#NonNull Network network) {
super.onAvailable(network);
wifiLog("AndroidQ+ connected to wifi ");
// bind so all api calls are performed over this new network
connectivityManager.bindProcessToNetwork(network);
}
#Override
public void onUnavailable() {
super.onUnavailable();
wifiLog("AndroidQ+ could not connect to wifi");
}
};
connectivityManager.requestNetwork(networkRequest, networkCallback);
My observation with this implementation is - It is more like P2P communication, and at this time other application from the same device cannot use internet from the connected WiFi network
2. WifiNetworkSuggestion
A code example from developer.android.com
final WifiNetworkSuggestion suggestion1 =
new WifiNetworkSuggestion.Builder()
.setSsid("test111111")
.setIsAppInteractionRequired(true) // Optional (Needs location permission)
.build();
final WifiNetworkSuggestion suggestion2 =
new WifiNetworkSuggestion.Builder()
.setSsid("test222222")
.setWpa2Passphrase("test123456")
.setIsAppInteractionRequired(true) // Optional (Needs location permission)
.build();
final WifiNetworkSuggestion suggestion3 =
new WifiNetworkSuggestion.Builder()
.setSsid("test333333")
.setWpa3Passphrase("test6789")
.setIsAppInteractionRequired(true) // Optional (Needs location permission)
.build();
final PasspointConfiguration passpointConfig = new PasspointConfiguration();
// configure passpointConfig to include a valid Passpoint configuration
final WifiNetworkSuggestion suggestion4 =
new WifiNetworkSuggestion.Builder()
.setPasspointConfig(passpointConfig)
.setIsAppInteractionRequired(true) // Optional (Needs location permission)
.build();
final List<WifiNetworkSuggestion> suggestionsList =
new ArrayList<WifiNetworkSuggestion> {{
add(suggestion1);
add(suggestion2);
add(suggestion3);
add(suggestion4);
}};
final WifiManager wifiManager =
(WifiManager) context.getSystemService(Context.WIFI_SERVICE);
final int status = wifiManager.addNetworkSuggestions(suggestionsList);
if (status != WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS) {
// do error handling here…
}
// Optional (Wait for post connection broadcast to one of your suggestions)
final IntentFilter intentFilter =
new IntentFilter(WifiManager.ACTION_WIFI_NETWORK_SUGGESTION_POST_CONNECTION);
final BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
if (!intent.getAction().equals(
WifiManager.ACTION_WIFI_NETWORK_SUGGESTION_POST_CONNECTION)) {
return;
}
// do post connect processing here...
}
};
context.registerReceiver(broadcastReceiver, intentFilter);
My observation with the above mentioned implementation is, when you call the wifiManager.addNetworkSuggestions it return success and show user a notification for connection. If the user accept, device gets connected to the WiFi network and other app can user internet. But if user disconnect from network and you call wifiManager.addNetworkSuggestions again, it will return WifiManager.STATUS_NETWORK_SUGGESTIONS_ERROR_ADD_DUPLICATE error.
It looks like this API just provide a suggestion list of networks where the device can auto connect. But the connection will be determined by the OS.
But if you really need a solution, an undocumented way use to the Default Wifi QR Code Scanner from Android Source that can detect both QR Code schems Zxing and DPP.
here is an a code example :
#Override
protected void onActivityResult(int requestCode, int resultCode, #Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if(requestCode == REQUEST_CODE_WIFI_QR_SCANNER && resultCode == RESULT_OK)
{
//WIFI Connection is Successful
}
else
{
//.......
}
}
#RequiresApi(api = Build.VERSION_CODES.Q)
private void startWifiQRCodeScanner(Context context)
{
final String INTENT_ACTION_WIFI_QR_SCANNER = "android.settings.WIFI_DPP_ENROLLEE_QR_CODE_SCANNER";
WifiManager wifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
if(wifiManager.isEasyConnectSupported())
{
final Intent intent = new Intent(INTENT_ACTION_WIFI_QR_SCANNER);
startActivityForResult(intent, REQUEST_CODE_WIFI_QR_SCANNER);
}
}
Here is a solution working from Android 6 (API level 23)
String AP_SSID = "YourWifiNetworkSSID";
String AP_PASSWORD = "YourWifiNetworkPassword";
wifiManager = (WifiManager) getApplicationContext().getSystemService(WIFI_SERVICE);
WifiConfiguration conf = new WifiConfiguration();
conf.SSID = "\"" + AP_SSID + "\""; // Please note the quotes. String should contain ssid in quotes
conf.preSharedKey = "\"" + AP_PASSWORD + "\"";
wifiManager.addNetwork(conf);
try {
List<WifiConfiguration> list = wifiManager.getConfiguredNetworks();
for (WifiConfiguration i : list) {
if (i.SSID != null && i.SSID.equals("\"" + AP_SSID + "\"")) {
wifiManager.disconnect();
wifiManager.enableNetwork(i.networkId, true);
wifiManager.reconnect();
break;
}
}
} catch (SecurityException e) {
Log.e(TAG, e.getMessage());
}
Related
"Addnetwork" is used below Android 9.0. This method returns correctly, but it fails when Android 10.0 is used. It always returns - 1. What is the reason?
This is my core code:
public WifiConfiguration createWifiInfo(String SSID, String Password,
int Type) {
WifiConfiguration config = new WifiConfiguration();
config.allowedAuthAlgorithms.clear();
config.allowedGroupCiphers.clear();
config.allowedKeyManagement.clear();
config.allowedPairwiseCiphers.clear();
config.allowedProtocols.clear();
config.SSID = "\"" + SSID + "\"";
WifiConfiguration tempConfig = this.isExsits(SSID);
if (tempConfig != null) {
mWifiManager.removeNetwork(tempConfig.networkId);
}
if (Type == 1) // WIFICIPHER_NOPASS
{
config.wepKeys[0] = "";
config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
config.wepTxKeyIndex = 0;
}
return config;
}
Partial code:
WifiConfiguration wifiInfo = createWifiInfo("", "", 1);
networkId = mWifiManager.addNetwork(wifiInfo);//result: networkId:-1
WifiManager.addNetwork(WifiConfiguration config) has been deprecated in API level 29.
Instead, developers are expected to use the WifiNetworkSpecifier or "Wi-Fi suggestion API" as stated in the link above. Both APIs show a different system dialog which asks the user to connect to a specified network.
You can find an example for the WifiSuggestions API in this StackOverflow thread: Creating a custom wifi setup
With Android 10, I'm using the following method to connect to my Wifi Access Point :
#RequiresApi(api = Build.VERSION_CODES.Q)
public static void connectToWifiAccessPoint(String AP_SSID, String AP_PASSWORD, ConnectivityManager connectivityManager) {
WifiNetworkSpecifier.Builder builder = null;
builder = new WifiNetworkSpecifier.Builder();
builder.setSsid(AP_SSID);
builder.setWpa2Passphrase(AP_PASSWORD);
WifiNetworkSpecifier wifiNetworkSpecifier = builder.build();
NetworkRequest.Builder networkRequestBuilder = new NetworkRequest.Builder();
networkRequestBuilder.addTransportType(NetworkCapabilities.TRANSPORT_WIFI);
networkRequestBuilder.setNetworkSpecifier(wifiNetworkSpecifier);
NetworkRequest networkRequest = networkRequestBuilder.build();
connectivityManager.requestNetwork(networkRequest, new ConnectivityManager.NetworkCallback() {
#Override
public void onAvailable(#NonNull Network network) {
super.onAvailable(network);
connectivityManager.bindProcessToNetwork(network);
}
});
}
A few seconds after calling this method, the OS displays this pop-up:
After hitting the connect button, the same pop-up appears a few seconds later, and the
smartphone is still not connected to the access point.
Any idea how to fix this please ?
I struggle couple days ago with wifi connection on Andrdoid Q, the link of my question in stackOverflow.
So, the solution is compile your app with targetSdkVersion 28.
and for connection to wifi use this function :
public void connectToWifi(String ssid, String key) {
Log.e(TAG, "connection wifi pre Q");
WifiConfiguration wifiConfig = new WifiConfiguration();
wifiConfig.SSID = "\"" + ssid + "\"";
wifiConfig.preSharedKey = "\"" + key + "\"";
int netId = wifiManager.addNetwork(wifiConfig);
if (netId == -1) netId = getExistingNetworkId(wifiConfig.SSID);
wifiManager.disconnect();
wifiManager.enableNetwork(netId, true);
wifiManager.reconnect();
}
Try to forget the wifi Access point from saved networks
I need a simple code how to connect from mobile application to secure WIFI (EAP-AKA). I have below code but I don't know is or correct or not, and don't know how to use it. It will be great if anyone has sample code.
// Initialize the WifiConfiguration object
WifiConfiguration wifi = new WifiConfiguration();
WifiEnterpriseConfig enterpriseConfig = new WifiEnterpriseConfig();
wifi = new WifiConfiguration();
wifi.SSID = ssid;
wifi.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_EAP);
wifi.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.IEEE8021X);
enterpriseConfig.setIdentity(userName);
enterpriseConfig.setPassword(passWord);
enterpriseConfig.setEapMethod(WifiEnterpriseConfig.Eap.AKA);
wifi.enterpriseConfig = enterpriseConfig;
I found the answer, and decided to put it, may be it help anyone
Sample code application can be found in my repository
https://github.com/malah-code/Android-Eap-Aka-Sample
Code
// Initialize the WifiConfiguration object
logThis("attemp to connect\n");
mProgressView.refreshDrawableState();
WifiEnterpriseConfig enterpriseConfig = new WifiEnterpriseConfig();
WifiConfiguration wifi = new WifiConfiguration();
wifi.SSID = mSSIDView.getText().toString();
wifi.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_EAP);
wifi.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.IEEE8021X);
enterpriseConfig.setEapMethod(WifiEnterpriseConfig.Eap.AKA);
wifi.enterpriseConfig = enterpriseConfig;
logThis("finding saved WiFi\n");
wifi.networkId = ssidToNetworkId(wifi.SSID);
if (wifi.networkId == -1) {
logThis("WiFi not found - adding it.\n");
wifiManager.addNetwork(wifi);
} else {
logThis("WiFi found - updating it.\n");
wifiManager.updateNetwork(wifi);
}
logThis("saving config.\n");
wifiManager.saveConfiguration();
wifi.networkId = ssidToNetworkId(wifi.SSID);
logThis("wifi ID in device = " + wifi.networkId + "\n");
SupplicantState supState;
int networkIdToConnect = wifi.networkId;
if (networkIdToConnect >= 0) {
logThis("Start connecting...\n");
// We disable the network before connecting, because if this was the last connection before
// a disconnect(), this will not reconnect.
wifiManager.disableNetwork(networkIdToConnect);
wifiManager.enableNetwork(networkIdToConnect, true);
WifiInfo wifiInfo = wifiManager.getConnectionInfo();
supState = wifiInfo.getSupplicantState();
logThis("WifiWizard: Done connect to network : status = " + supState.toString());
} else {
logThis("WifiWizard: cannot connect to network");
}
I am new to android application development and I want to build an application that uses wifi to connect to another devices (not mobile devices) and sends some data from my phone to a device and receives some data from the other device.
What I have in my local network:
mobile phone support wifi with android os.
device support wifi connection (e.g. temperature sensor).
What I need:
The phone needs to connect to the router and receive a list of available devices and check if the sensor is connected to the network or not.
Connect to the sensor and send a message from the phone that tells the sensor to measure the temperature.
The sensor sends back a message that contains the temperature.
Your question is nor quite clear to me. But as per my understanding you want to list down some Wi-Fi enabled devices on your mobile & then connect to one of them & finally communicate with them.
For Listing all access points you have to implement the code below.
private final BroadcastReceiver mWifiScanReceiver = new BroadcastReceiver(){
#Override
public void onReceive(Context c, Intent intent) {
String action = intent.getAction();
if (WifiManager.SCAN_RESULTS_AVAILABLE_ACTION.equals(action)) {
List<ScanResult> scanResults = mainWifiObj.getScanResults();
mScannedNetworksAdapter.clear();
listView_Access_point.clearChoices();
if (scanResults != null) {
for (ScanResult result : scanResults) {
mScannedNetworksAdapter.add(result)
}
}
listView_Access_point.setAdapter(mScannedNetworksAdapter);
}
}
};
Now After listing all the Wi-Fi access points you have to click one of them to get connected. To do this you have implement OnItemClickListener & then override onItemclick(). See the code below.
#Override
public void onItemClick(AdapterView<?> parent, View arg1, int position, long arg3) {
ScanResult result = (ScanResult) parent.getItemAtPosition(position);
WifiConfiguration conf = new WifiConfiguration();
conf.SSID = "\"" + result.SSID + "\"";
conf.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
WifiManager wifiManager = (WifiManager)context.getSystemService(Context.WIFI_SERVICE);
wifiManager.addNetwork(conf);
List<WifiConfiguration> list = wifiManager.getConfiguredNetworks();
if(list!=null){
for( WifiConfiguration i : list ) {
if(i.SSID != null && i.SSID.equals("\"" + result.SSID + "\"")) {
wifiManager.disconnect();
wifiManager.enableNetwork(i.networkId, true);
wifiManager.reconnect();
break;
}
}
}
}
Then you have to implement a BroadcastReceiver which tells if the access point is connected successfully.
private final BroadcastReceiver mWifiConnectionEstablished = new BroadcastReceiver() {
#Override
public void onReceive(Context c, Intent intent) {
String action = intent.getAction();
if (WifiManager.NETWORK_STATE_CHANGED_ACTION.equals(action)) {
NetworkInfo nwInfo = intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO);
if (NetworkInfo.State.CONNECTED.equals(nwInfo.getState()) && nwInfo.isConnected()) {
//The connection is established. Now do your stuff here
}
}
}
};
Finally there are several methods for communication. One of them is socket communication. You will get several examples in google for socket communication in android.
I am trying to write some code that will disconnect current wifi network (if any) and reconnect to a specific wifi network with known SSID.
I have been following the code used here; How do I connect to a specific Wi-Fi network in Android programmatically?
which works but the connection takes several seconds, upto about 10 seconds.
Specifically, I use the code as follows;
WifiManager wifiManager = (WifiManager)context.getSystemService(Context.WIFI_SERVICE);
WifiConfiguration config;
I obtain the config, whether by creating a new one and setting the SSID and KeyMgmt to NONE and then adding it;
wifiManager.add(config);
or by getting a config that already exists;
List<WifiConfiguration> list = wifiManager.getConfiguredNetworks();
for( WifiConfiguration i : list ) {
if(i.SSID != null && i.SSID.equals("\"" + networkSSID + "\"")) {
config = i;
break;
}
}
Then I call;
wifiManager.disconnect();
wifiManager.enableNetwork(i.networkId, true);
wifiManager.reconnect();
I have a broadcast received checking the wifi state and when i get a connected for my correct SSID i can continue, however, this process takes upto 10 seconds, how can i set up the config or wifimanager to connect to this much quicker?
Thanks
I think this code is help to you..
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.network_test);
context = this;
mUpdate = new UpdateTimeTask();
mHandler = new Handler();
mHandler.post(mUpdate);
}
public Boolean isNetAvailable(Context con) {
try{
connectivityManager = (ConnectivityManager) con.getSystemService(Context.CONNECTIVITY_SERVICE);
wifiInfo = connectivityManager.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
mobileInfo = connectivityManager.getNetworkInfo(ConnectivityManager.TYPE_MOBILE);
if(wifiInfo.isConnected() || mobileInfo.isConnected()) {
return true;
}
}catch(Exception e){
e.printStackTrace();
}
return false;
}
private class UpdateTimeTask implements Runnable{
public void run() {
boolean net = isNetAvailable(context);
if(net != false) {
Toast.makeText(getBaseContext(), "network Available", Toast.LENGTH_SHORT).show();
}
else
{
Toast.makeText(getBaseContext(), "network Not Available", Toast.LENGTH_SHORT).show();
}
mHandler.postDelayed(mUpdate, 30000);
}
}
}
Have you tried adding startScan() to your routine to force an immediate rescan for available networks at the time you wish to connect? I imagine forcing that command repeatedly with an alarmManager or something similar is possible, but I would think that has the potential to have an expensive performance/battery impact. If you have a specific trigger, it could be a solution.
See here: http://developer.android.com/reference/android/net/wifi/WifiManager.html#startScan()