I'm using HttpClient to post then retrieve something in Android, which works great, but when I dont have a internet connection it forces close, is their a way to catch UnknownHostException when making an HttpPost? I know I could make sure its connected to the internet before making the request, but what about if the phone just doesn't have service?
UnknownHostException is a Subclass of IOException, so you should be able to catch/manage it simply catching IOException or something more specific (NoRoute, ConnectTimeout, etc.)
Also consider adding connection check before doing network calls with ConnectivityManager
you can check for your intenet connection with
ConnectivityManager cm = (ConnectivityManager)this.getSystemService(Context.CONNECTIVITY_SERVICE);
if (cm.getNetworkInfo(ConnectivityManager.TYPE_MOBILE).isConnected() || cm.getNetworkInfo(ConnectivityManager.TYPE_WIFI).isConnected()) {
//connected
} else {
//not connected
}
And set the permissions in AndroidManifest
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
Related
I have a deployed app that is failing on Android 9. Part of its function is to configure a module over an Access Point network to allow that that module to connect to the users home network.
I have code that detects and connects to the correct WIFI network, but when I attempt to open a socket to the device, it fails - only on Android 9 and only if mobile data is enabled. If I manually disable mobile data on the device everything runs fine.
Socket open() {
Socket sock = new Socket(Proxy.NO_PROXY);
try {
sock.bind(new InetSocketAddress(localIpAddress(), 50000));
} catch (IOException e) {
activity.logContent("Warning: Failed to bind socket : " + e.toString());
}
try {
sock.connect(new InetSocketAddress("192.168.17.1", 5555), (int)5000);
} catch (IOException e) {
// This catch fires when Mobile Data is on.
activity.logContent("Connected to " + activity.mWifiManager.getConnectionInfo().getSSID());
activity.logContent("Couldn't open socket : " + e.toString());
}
return sock;
}
I have tried this with and without the Proxy.NO_PROXY and with and without the bind() call. If the bind call is missing the error implies that the socket is attempting to connect over the cell network. (Note: activity.logContent() is an on-screen log so it is easier to see what is happening when not connected to a debugger).
Any ideas what is going wrong?
After a few days of imprecations I believe I have come to the identification of the problem and therefore to the solution:
The problem occurs due to some changes in the version of android (I presume to be 9.0 even if other changes had occurred on API 21), in particular on the creation of the socket, if the system detects that there is a "better" network (access to internet, high signal, etc, etc) socket creation refers to that network and no longer to the wifi network you would like.
I looked for ways to force the creation of the socket on the wifi network (which is the network I want) and the only way I found is this:
Simply put instead of:
Socket sock = new Socket ();
Do:
ConnectivityManager connectivity = (ConnectivityManager) MyApp.getContext().getSystemService(Context.CONNECTIVITY_SERVICE);
if (connectivity != null)
{
for (Network network : connectivity.getAllNetworks())
{
NetworkInfo networkInfo = connectivity.getNetworkInfo(network);
if (networkInfo != null && networkInfo.getType() == ConnectivityManager.TYPE_WIFI)
{
if (networkInfo.isConnected())
{
Socket sock = network.getSocketFactory().createSocket();
}
}
}
}
Practically browse the networks present in the device and when you find your active wifi you do nothing but take advantage of this function to get the right socket for sure:
getSocketFactory().createSocket()
Now you have the working socket!
In my case it now works perfectly, if someone finds better solutions, it is welcome, but for now it is the only way I have found to make everything work as in the previous version of android.
In Android 9 there a security config about network: Android security config
Adding your domain in network_security_config might solve your problem. I had this in my network_security_config.xml:
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<domain-config cleartextTrafficPermitted="true">
<domain includeSubdomains="true">119.xxx.xxx.xxx</domain>
</domain-config>
</network-security-config>
I am not sure about the exact reason of why this is happening. However, when you are turning on your mobile data and you are only connected to the internet using your mobile data (considering your wifi is turned off), it gets the IP address from the cellular network which is no more connected in your home network. Hence, this is trivial to expect such timeout scenarios, because, it cannot reach the private IP addresses of your home network starting with 192.168.....
Now my confusion is that even if the mobile data is turned on, and both wifi and mobile data is turned on at the same time, the device should connect to the wifi as a default behavior.
Hence I would like to suggest you check the following.
Android 9 (Pie) introduces special Wifi preference, which prevents connecting to public networks automatically. You might consider checking the settings.
Please check the IP address of your device and check if it has some IP address starting with 192.168..... If not, then definitely, you are getting your IP address from your cellular network and hence it cannot reach your private IP addresses of the home network.
I've made a ListView with devices currently paired to my phone so that I can select one of them and connect to it. To determine which device was selected, I'm storing their MAC Addresses in an array so that I can get a device by its address. When I select a device, the app freezes for a bit then restores with no success of connecting. I cannot find the solution anywhere and I'm stuck. I'm still a beginner and do not understand much. An exception occurs that goes like:
java.io.IOException: read failed, socket might be closed or timeout, read ret: -1
Here is my code.
// If the UUID is incorrect then this one does not work as well
// 00001101-0000-1000-8000-00805f9b34fb
private static final UUID CONNECTION_UUID = UUID.fromString("0000110E-0000-1000-8000-00805F9B34FB");
public static boolean connectDevice(final int a) {
try {
BluetoothDevice mBluetoothDevice = btAdapter.getRemoteDevice(deviceAddress[a]);
BluetoothSocket mBluetoothSocket = mBluetoothDevice.createInsecureRfcommSocketToServiceRecord(CONNECTION_UUID);
btAdapter.cancelDiscovery();
mBluetoothSocket.connect();
mmOutputStream = new DataOutputStream(mBluetoothSocket.getOutputStream());
mmInputStream = new DataInputStream(mBluetoothSocket.getInputStream());
mBluetoothSocket.close();
} catch (NullPointerException e) {
e.printStackTrace();
return false;
} catch (Exception e) {
e.printStackTrace();
return false;
}
return true;
}
From the CONNECTION_UUID that you provided in your code, I assume that you are connecting with a Bluetooth serial board. I am not sure about the problem yet, however, I thought of writing this answer to provide a probable solution that might solve your issue.
I think in case of the paired devices, you need to initiate the connection with a secure channel. Currently, you are using an insecure channel.
From the documentation...
The communication channel will not have an authenticated link key i.e
it will be subject to man-in-the-middle attacks. For Bluetooth 2.1
devices, the link key will be encrypted, as encryption is mandatory.
For legacy devices (pre Bluetooth 2.1 devices) the link key will be
not be encrypted. Use createRfcommSocketToServiceRecord(UUID) if an
encrypted and authenticated communication channel is desired.
Hence you might consider using createRfcommSocketToServiceRecord() for your case.
Instead of this
BluetoothSocket mBluetoothSocket = mBluetoothDevice.createInsecureRfcommSocketToServiceRecord(CONNECTION_UUID);
Use this...
BluetoothSocket mBluetoothSocket = mBluetoothDevice.createRfcommSocketToServiceRecord(CONNECTION_UUID);
I hope that solves your problem.
From the comment below - The UUID that actually worked here is 00001101-0000-1000-8000-00805f9b34fb
I am developing a Tango Application with Unity and the Tango SDK, however, I need to be able to check the device's Wifi connectivity and connect to a Wifi Network accordingly.
With that in mind I started working on an Android Unity Network Plugin, but I am having troubles checking the device's connectivity; even though Wifi is on and the Device is indeed connected to a Wifi network, getActiveNetwork keeps returning null.
I spent a couple of days searching for a workaround, or an alternative implementation, but I couldn't find anything that works, below is the code I ended up using to perform the check after looking through the many Android Connectivity related questions I looked at, as well as all the permissions I am using in the Manifest.
(I would like to point out that I am currently returning an integer as a means to quickly debug the function when called via Unity C# Scripts, and right now the function always returns 0.)
public int IsConnectedToWifi(){
//SCCActivity activity = new SCCActivity();
ConnectivityManager cm = (ConnectivityManager) this.getApplicationContext().getSystemService(Context.CONNECTIVITY_SERVICE);
if(cm == null) return -2;
NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
if (activeNetwork != null) { // connected to the internet
if (activeNetwork.getType() == ConnectivityManager.TYPE_WIFI) {
// connected to wifi
DebugToast(activeNetwork.getTypeName());
return 1;
//return activeNetwork.isConnected();
} else if (activeNetwork.getType() == ConnectivityManager.TYPE_MOBILE) {
// connected to the mobile provider's data plan
DebugToast(activeNetwork.getTypeName());
return 2;
//return false;
}
}
else {
DebugToast("There is no active Network");
return 0;
//return false;
}
DebugToast("Failed to get a Connectivity Manager");
return -1;
//return false;
}
In AndroidManifest file:
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/>
I would really appreciate any advice or guidance, thank you.
I is a bit old but maybe it helps someone. In my case when I changed the order of permissions in manifest in a way that ACCESS_NETWORK_STATE is before INTERNET then it worked
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
strange but works
Hey I don't know if you really want to check that is phone is connected to WIFI or MOBILE_INTERNET.
But if you just want to check that if mobile have connectivity
than below code works fine for me
public static final boolean isNetworkAvailable(Context context) {
boolean connected = false;
ConnectivityManager connectivityManager =
(ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo nf = connectivityManager.getActiveNetworkInfo();
if (nf != null && (nf.isConnected() || nf.isConnectedOrConnecting())) {
// we are connected to a network
connected = true;
} else
connected = false;
return connected;
}
I have been using this successfully in devices with kitkat and later:
public static boolean isConnectedWifi(Context context){
NetworkInfo info = Connectivity.getNetworkInfo(context);
return (info != null && info.isConnected() && info.getType() == ConnectivityManager.TYPE_WIFI);
}
I have also compared it to ConnectivityManager.TYPE_MOBILE in the past but can't remember how good or bad it worked.
Upon further debugging and looking through similar cases, I found and solved the issue.
I will leave my solution here in case someone else comes across a similar problem.
Basically, getActiveNetwork wasn't really returning null at all, it turns out that even though the permission was listed on the xml, "android.permission.ACCESS_NETWORK_STATE" was never granted and the function was throwing up an exception. The cause of the problem was the fact that, as I mentioned before, I am working on a Tango Application using the Tango SDK for Unity, and the xml provided by the Tango SDK was overwriting the xml from the Java plugin.
The solution was simple; I just added the permissions to the Tango SDK's xml instead.
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 7 years ago.
Improve this question
I want make a application that work with Internet and a Server and Web service, I create a method to check network available, I use bellow method:
private boolean isNetworkConnect() {
ConnectivityManager cm = (ConnectivityManager)getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo netinfo = cm.getActiveNetworkInfo();
if (netinfo != null && netinfo.isConnected()) {
netType = netinfo.getTypeName();
return true;
} else {
return false;
}
}
This method just specify that WiFi of Mobile network in Android is Enable or Disable, But this is not sufficient to Internet Access, because if I disable my Laptop WiFi, but my android app in Emulator said Internet in Access because WiFi or Mobile Network is Enable, But if open browser and search any sites is not Access.!
I How to check internet access, that I search on browser, read from server and others. What is best solution ?
Your code is looking good. I already using this code on my own app.
This problem comes because you are using emulator for test your app.
If you test your app on real device isConnected() method work correctly.
If you want to get false return for your isNetworkConnect() method on emulator go to
Settings > Wireless & network > Mobile network And uncheck "Data enabled"
Your approach is generally what is used for isOnline method. It does not work by sending packets, thereby verifying connectivity. Its based on the state i.e., whether you are connected to WiFi or Mobile network. Now, as in your case, there may not be any actual connectivity.
To specifically answer your question, this is the best you could do. However, it does not ensure real connectivity.
Try This(edit as you want)
public void testURL() throws Exception {
String strUrl = "http://stackoverflow.com/about";
try {
URL url = new URL(strUrl);
HttpURLConnection urlConn = (HttpURLConnection) url.openConnection();
urlConn.connect();
assertEquals(HttpURLConnection.HTTP_OK, urlConn.getResponseCode());
} catch (IOException e) {
System.err.println("Error creating HTTP connection");
e.printStackTrace();
throw e;
}
}
Why do I get this error...
java.net.UnknownHostException: http://google.com
...when I do this in my Activity -> onCreate?
try {
Socket socket = new Socket("http://google.com", 80);
} catch(Exception e) {
Log.e(tag, e.toString());
return;
}
And yes, I do have the Internet permission set in my manifest.
<uses-permission android:name="android.permission.INTERNET" />
This is being tested on a physical Nexus S phone
Use www.google.com, without the http:// part.
Is it throwing an UnknownException or UnknownHostException?
UnknownHostException means there is a problem with the hostname lookup. Try it without the "http://" and if that doesn't work, try it with the direct IP address.
Its not your app permissions that is failing, otherwise it would throw a SecurityException.
Socket throws an
UnknownHostException - if the IP address of the host could not be determined.
Do you have Internet Access enabled? Try it with another host or with the IP and/or try restarting your phone.