I've spent several days trying to figure out what is wrong with my android phone's wifi at school. The school wifi is 802.1x EAP using PEAP..requires username, password.
I've had two Android phones, and have run many different ROMs on them so I know this isn't just a ROM specific problem. I'm currently running 2.2.1 on a Mytouch 3g fender ed. I don't have a data plan with my phone so I keep data off. I only use wifi.
The problem I have is that after I connect to the wifi, everything is fine for a while, but soon (perhaps 15 minutes to an hour later), I'll turn my phone on and when I see the wifi connection, it says Authenticating and it stays stuck there till I reset it. If I try to surf the Internet with normal HTTP it works fine, but if I try to run any apps that require wifi connection, they give an error saying there is a network connection (example would be Google Voice search which will say "Connection Problem"). Feeds can't update, gmail won't update, etc. After I reset the connection, the wifi works perfectly again. I am not sure why this happens. I think it has something to do with how the school's wifi is set up.
To make a quick fix to the problem however, I'm writing an app that will test if the connection is authenticating and reassociate the connection if it is. I'm running into problems though.
Here is the code to see if the wifi is authenticating and also some debug output:
private void checkWifi() {
WifiManager wifi = (WifiManager) getSystemService(Context.WIFI_SERVICE);
WifiInfo info = wifi.getConnectionInfo();
SupplicantState state = info.getSupplicantState();
Log.d(getClass().getSimpleName(), state.toString());
NetworkInfo.DetailedState state2 = WifiInfo.getDetailedStateOf(info.getSupplicantState());
Log.d(getClass().getSimpleName(), state2.toString());
}
And here's the log output:
D/WifiCheckerService(24732): COMPLETED
D/WifiCheckerService(24732): OBTAINING_IPADDR
The log output is the same no matter if the wifi on the phone says Connected or Authenticating which means my program as of now cannot distinguish if it is in the funky "authentication" state or not. I need to be able to distinguish in order to be able to know when to reset the wifi. Any help is greatly appreciated.
Try this.
ConnectivityManager conn = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo nInfo = conn.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
Log.d("MY CONNECTIVITY MANAGER: NETWORK.DETAILEDSTATE", nInfo.getDetailedState().toString());
Log.d("MY CONNECTIVITY MANAGER: NETWORK.STATE", nInfo.getState().toString());
Here's my Output (If you entered a wrong password while connecting).
D/MY CONNECTIVITY MANAGER: NETWORK.DETAILEDSTATE(24732):
AUTHENTICATING D/MY CONNECTIVITY MANAGER: NETWORK.STATE(24732):
CONNECTING
Second Output (While obtaining IP).
D/MY CONNECTIVITY MANAGER: NETWORK.DETAILEDSTATE(24732): OBTAINING_IPADDR
D/MY CONNECTIVITY MANAGER: NETWORK.STATE(24732): CONNECTED
Third Output (Successfully Connected).
D/MY CONNECTIVITY MANAGER: NETWORK.DETAILEDSTATE(24732): CONNECTED
D/MY CONNECTIVITY MANAGER: NETWORK.STATE(24732): CONNECTED
4th Output (If you entered wrong password and failed to connect).
D/MY CONNECTIVITY MANAGER: NETWORK.DETAILEDSTATE(24732): DISCONNECTED
D/MY CONNECTIVITY MANAGER: NETWORK.STATE(24732): DISCONNECTED
5th Output (If WIFI is IDLE and DISCONNECTED).
D/MY CONNECTIVITY MANAGER: NETWORK.DETAILEDSTATE(24732): IDLE
D/MY CONNECTIVITY MANAGER: NETWORK.STATE(24732): DISCONNECTED
// hope it helps
Related
I have an app that's custom built for a client and not available in the Play Store that basically makes some network calls when it detects that the device is connected to their WiFi. This should happen even if it has no internet connection, every request that the app makes is to a local address.
The problem comes with the new batch of tablets that the client has purchased (Galaxy Tab Active 2, Android 8.1.0, Build number M1AJQ.T395XXU3BRJ5), which will always prefer a connection with internet access over whatever network I'm telling it to bind to.
WiFi -> Advanced -> Switch to mobile data is already disabled, so that should not be it.
Here's the code I'm using that has been working until now:
ConnectivityManager cm = (ConnectivityManager) getApplication().getSystemService(Context.CONNECTIVITY_SERVICE);
Network[] networks = cm.getAllNetworks();
for (int i = 0, networksLength = networks.length; !bound && i < networksLength; i++) {
Network network = networks[i];
if (correctNetwork(network)) { //SSID check
bound = cm.bindProcessToNetwork(network);
Log.i(TAG, "Bound? " + bound);
}
}
On all their previous devices, my own phone and even a Galaxy Tab Active 1 this is working: we see "Bound? true" in the logs and every connection is made through the right network. On the Active 2 we always see "Bound? false" and it will use the 4G connection. Disabling data is not an option.
If this is a Samsung bug, is there a workaround for it? Or maybe an alternative way of forcing an HttpURLConnection to use a specific network?
I wrote an app that is triggering a Sony qx smartphone attachable camera over wifi. However I need to transfer the images off the phone over another local network in real time. Since the wifi card is being used for qx connection I need to be able to use ethernet over usb for transferring images off the phone. Http requests will be used to trigger the camera and send the images off the phone.
Is it possible in one android app on a phone with two network interfaces setup to specify for certain http requests to use one network interface and for others to use another network interface ? Does this need to be done through routing tables, not java?
The phone I'm using is a rooted nexus 6p.
Update:
Currently, I was able to get an Ethernet adapter working with the device (Nexus 6P). The device is connected to a local network over Ethernet. When the Wi-Fi interface is off, I can ping all devices on the local network the device is connected to over Ethernet. However, I am unable to access the web servers (Not using DNS) of any of the devices on that network (which I know they are running), i.e. Http via a browser app. The nexus 6p is connected to the network over Ethernet via a Ubiquiti Station. This seems to be a routing issue.
I can tether(usb interface) and use Wi-Fi in one app, so that leads me to believe it is possible to use Ethernet and Wi-Fi.
Update2:
After more testing, it seems to be that it is a permissions issue. Since when I ping the network the device is connected to over Ethernet without first running su in the terminal the network doesn't exist. However, when I run su then ping, I can ping the network. Thus it seems my app needs to get superuser permission before accessing Ethernet. I've granted it superuser access, but nothing has changed. I read that simply running su isn't enough from one of the comments in this post. This is because su just spawns a root shell that dies. This also explains why I couldn't access any of the web servers on this network via a browser app. Is it possible to grant my app access to the Ethernet interface when making HTTP calls like give HttpURLConnection root access, if that makes any sense (running su doesn't work)? There seems to definitely be a solution since HttpURLConnection can make calls over the USB tethering interface (Nexus 6P calls it rndis0) fine.
Update 3:
I found online here , that I can make my app a System app (thought this might grant the app eth0 access). I just moved my app to /system/app and then rebooted. However, this didn't seem to give the app anymore privileges (thus not solving the problem) , or there is something else required to make the app system than just copying it to /system/app.
Update 4:
So I was able to get Ethernet working on every app without root permissions! It seemed to be that it only works over DHCP and does not like static connections, which I was using. It works with Wi-Fi enabled, however, I cannot contact any of the devices on the Wi-Fi network when Ethernet is enabled. Is there a way around this? Does it have to do with setting two default gateways?
Since you were programming in Nexus 6P, you can try to use the new API added in ConnectivityManager to select the ethernet as your preferred network connection for your process.
Since I can't build the similar environment like yours, I am not sure if it works. It's just a suggested solution, totally not tested and verified.
ConnectivityManager connectivityManager = (ConnectivityManager) getSystemService(CONNECTIVITY_SERVICE);
Network etherNetwork = null;
for (Network network : connectivityManager.getAllNetworks()) {
NetworkInfo networkInfo = connectivityManager.getNetworkInfo(network);
if (networkInfo.getType() == ConnectivityManager.TYPE_ETHERNET) {
etherNetwork = network;
}
}
Network boundNetwork = connectivityManager.getBoundNetworkForProcess();
if (boundNetwork != null) {
NetworkInfo boundNetworkInfo = connectivityManager.getNetworkInfo(boundNetwork);
if (boundNetworkInfo.getType() != ConnectivityManager.TYPE_ETHERNET) {
if (etherNetwork != null) {
connectivityManager.bindProcessToNetwork(etherNetwork);
}
}
}
Just to give a little more explanation on how this finally got solved.
Utilizing #alijandro's answer I was able to switch back and forth between Ethernet and Wi-Fi in one app. For some reason for the Ethernet to work it required the network gateway to supply DHCP address, not static. Then since the bindProcessToNetwork, used in #alijandro's answer is per-process, I decided to split communications with the QX camera into a Service that runs in a separate Process. The main Application (another process) would post images over Ethernet to a local network. I was successfully able to contact the devices on the local network via HTTP over Ethernet while simultaneously triggering the QX over Wi-Fi. Currently, I used Messenger to communicate using IPC to tell the QX triggering Service what methods to call.
Most of android tv boxes can use wifi and ethernet together. In my device, i can enable ethernet from this path ---
Settings -> More ... > Ethernet ---
But your device wont have a menu like that as i understand. So you should make an app to do that. This application needs to access some system specific resources so your device needs to be rooted or application needs to signed with system signature.
Also this topic can help you link
There is an easy way to do this that will answer the OP's original question about how to do this with a single application (not two separate app processes) using ConnectivityManager.requestNetwork().
The docs for ConnectivityManager.requestNetwork() allude to this:
... For example, an application could use this method to obtain a
connected cellular network even if the device currently has a data
connection over Ethernet. This may cause the cellular radio to consume
additional power. Or, an application could inform the system that it
wants a network supporting sending MMSes and have the system let it
know about the currently best MMS-supporting network through the
provided NetworkCallback. ...
For OP's scenario of using Wi-Fi for some traffic and ethernet for other traffic one only needs to call ConnectivityManager.requestNetwork() twice with two separate requests. One for TRANSPORT_WIFI and one for TRANSPORT_ETHERNET. The operative item here is we need a way to uniquely identify these networks. For OP's scenario, we can use transport type.
final NetworkRequest requestForWifi =
new NetworkRequest.Builder()
.addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
.build();
final NetworkRequest requestForEthernet =
new NetworkRequest.Builder()
.addTransportType(NetworkCapabilities.TRANSPORT_ETHERNET)
.build();
final ConnectivityManager connectivityManager = (ConnectivityManager)
context.getSystemService(Context.CONNECTIVITY_SERVICE);
final NetworkCallback networkCallbackWifi = new NetworkCallback() {
#Override
void onAvailable(Network network) {
// Triggers when this network is available so you can bind to it.
}
#Override
void onLost(Network network) {
// Triggers when this network is lost.
}
};
final NetworkCallback networkCallbackEthernet = new NetworkCallback() {
#Override
void onAvailable(Network network) {
// Triggers when this network is available so you can bind to it.
}
#Override
void onLost(Network network) {
// Triggers when this network is lost.
}
};
connectivityManager.requestNetwork(requestForWifi, networkCallbackWifi);
connectivityManager.requestNetwork(requestForEthernet, networkCallbackEthernet);
Then, once the callbacks trigger, you can then in the pertinent code (e.g. OP's code for transferring images), listen for onAvailable(Network network) and use the provided Network with Network.OpenConnection() to connect to an HTTP server using that network.
This would allow you to connect to two separate Networks from the same application.
I am trying to establish tcp socket connection when my app is in background, before I start connect to server, I checked the network state with the code below
ConnectivityManager connectivityManager = (ConnectivityManager)ctx.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo info = connectivityManager.getActiveNetworkInfo();
NetworkInfo.DetailedState state = info.getDetailedState();
and find the state is BLOCKED, which will cause failure for the tcp connection.
I was wondering is there any method to change network state from Blocked to Connected state? Any advice is appreciated, thanks in advance.
PS: I am working on MIUI rom, other roms may not have this issue.
You can't simply force a change of state. This state indicates that the device is simply not allowed to use the network, even though it might be connected. The BLOCKED state typically means that the user of the device has chosen to not allow background data access. (Maybe they have limited data on their plan and need to control access to data usage.)
I'm working on a project which need to connect to a Wi-Fi in a background service, the service running when the device is screen off.
The connecting code is like below:
public boolean connect_android(String ssid) {
List<WifiConfiguration> list = wifiManager.getConfiguredNetworks();
boolean find = false;
for( WifiConfiguration i : list ) {
if(i.SSID != null && i.SSID.equals("\"" + ssid + "\"")) {
wifiManager.enableNetwork(i.networkId, true);
wifiManager.reconnect();
find = true;
break;
}
}
while after the connecting code is executed in the background running service, the device never connect to the Wi-Fi successfully until the screen is turned on. I logged the supplicant state, it is in complete state. As the google docs says:
This state indicates that the supplicant has completed its processing for the association phase and that data connection is fully configured. Note, however, that there may not be any IP address associated with the connection yet. Typically, a DHCP request needs to be sent at this point to obtain an address.
So can i come to the conclusion that, when the screen is turned on, a DHCP request is send the device receives an IP and the connection is complete successfully. But who is in charge of sending the DHCP, the wpa_supplicant or Android framework, is there any docs about this? How can i connect to a Wi-Fi AP without turn on the screen? Thanks in advance!
Maybe because your device use feature turn of wifi when screen of (Settings -> Wireless and network -> WiFi settings -> (menu button) Advanced -> Wifi sleep policy)
Your app will cannot connect to network
I have an android app that tried to connect to a website in an AsyncTask and perform some tasks. My application always seems to crash when there is a change in the network connection i.e The app is connected to a wifi network initially, but loses connection and switches to mobile network. When this happens my Android Application crashes. My code is surrounded within a try catch block, so I'm not sure why the application would crash ? How do I fix my problem ?
Thanks!
WifiInfo info = WifiManager.getConnectionInfo();
if (info.getSSID() != null) {
String ssid = info.getSSID();
...
}
I don't know if it would be overkill to write:
if (info != null && info.getSSID() != null)
Also, the BroadcastReceiver that I need to monitor when a connection is made is WifiManager.SUPPLICANT_CONNECTION_CHANGE_ACTION. It turns out that I had a copy and paste error in my onResume(), and I wasn't really registering WifiManager.SUPPLICANT_CONNECTION_CHANGE_ACTION.
or u can use following link
Android: How to Enable/Disable Wifi or Internet Connection Programmatically
You have to make sure you wait for a network connectivity to be available before continuing your websites connections.
Plus, be aware that if you try to enable a mobile connection without disabling WiFi beforehand, the Android system will automatically shutdown the newly enabled mobile connection (it gives priority to WiFi to sum up). So you need to make sure you do it in the right order :
(WiFi enabled)
(WiFi ready)
Websites connections STARTED
Websites connections STOPPPED
(WiFi disabled)
(WiFi unavailable)
(Mobile enabled)
(Mobile ready)
Websites connections RESUMED