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;
}
}
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
We have an app we are making that needs to switch to cellular for some requests even when WiFi is connected.
According to the ConnectionManager documentation these following methods are now deprecated, but is not so clear on what to use instead.
public void useMobileNetworkMode(Context context) {
ConnectivityManager cm = (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE);
cm.setNetworkPreference(ConnectivityManager.TYPE_MOBILE);
}
public void useDefaultNetworkMode(Context context) {
ConnectivityManager cm = (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE);
cm.setNetworkPreference(ConnectivityManager.DEFAULT_NETWORK_PREFERENCE);
}
Do these methods still work in android 5/6? and if anyone has info or something to replace these methods with I would be very grateful!
Ok little bit more on the problem :)
I have managed to investigate ConnectivityManager and can see the networks using :
Network networkToUse = null;
Network[] networks;
networks = cm.getAllNetworks();
for (Network network : networks) {
NetworkInfo ni = cm.getNetworkInfo(network);
Log.e("NETWORKINFO", ni.getType() + " " + ni.getExtraInfo());
if (ni.getType()== ConnectivityManager.TYPE_WIFI) {
Log.e("NETWORKINFO", "isWifi");
if (ni.isConnected()) {
Log.e("NETWORKINFO", "and is connected");
if (networkToUse == null) {
networkToUse = network;
}
}
}
if (ni.getType()== ConnectivityManager.TYPE_MOBILE) {
Log.e("NETWORKINFO", "HasMobile");
if (ni.isConnected()) {
Log.e("NETWORKINFO", "and is connected");
networkToUse = network;
}
}
}
It is here I kind of get stuck because I can't logically see a way of telling the app to use one of these networks when performing a HttpsURLConnection from URL.openLink();.
UPDATE:
I have just noticed that the mobile one disappears shortly after WiFi connects. There is a moment where I get both but not for long.
I have also tried this:
final ConnectivityManager connection_manager =
(ConnectivityManager)httpsClient.getCheckoutController().getCheckout().getCurrentActivity().getApplication().getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkRequest.Builder request = new NetworkRequest.Builder();
request.addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR);
connection_manager.registerNetworkCallback(request.build(), new ConnectivityManager.NetworkCallback() {
#Override
public void onAvailable(Network network) {
Log.e("NETWORKINFO", "FOUND A CELLULAR NETWORK " + connection_manager.getNetworkInfo(network));
}
});
request = new NetworkRequest.Builder();
request.addTransportType(NetworkCapabilities.TRANSPORT_WIFI);
connection_manager.registerNetworkCallback(request.build(), new ConnectivityManager.NetworkCallback() {
#Override
public void onAvailable(Network network) {
Log.e("NETWORKINFO", "FOUND A WIFI NETWORK "+connection_manager.getNetworkInfo(network));
}
});
but as with the "list" of networks" in previous try I only ever 1 callback, even if mobile data is on as well.
UPDATE;
Ok I seem to see mobile sometimes using above method. but it seems to create API level spaghetti hell. It sometimes also takes a very long time for the mobile callback to fire. I wonder if this is because it has to wake up the cellular modem and wait for it's handshake or something?
UPDATE;
I had another possible suggestion using Sockets (something I have little experience with..)
Does anyone know if it is possible to build a CELLULAR SSL connection socket to do https requests using HttpsURLConnection.getSocketFactory() and SSLSocket ?
Any info would be very welcome in this week long quest :D
UPDATE:
Found a good and categorical answer from someone at google:
How to stay connected through mobile network after WIFI is connected on Android?
However after implementation, i get a network callback for the mobile but when i open URL connection and perform a request it seems to get stuck for ages (about 4 minutes) before i get the response.
I have a Huawei 5.0.1 phone, which is the highest i have available. Obviously this is not good. However it is not tested on 5.1 galaxy S6 and works.. so could be the phone.
According to the Android documentation it is no longer working in Android version 5 and above.
This method was deprecated in API level 21.
Functionality has been removed as it no longer makes sense, with many more >than two networks - we'd need an array to express preference. Instead we >use dynamic network properties of the networks to describe their >precedence.
Found a good and categorical answer from someone at google: How to stay connected through mobile network after WIFI is connected on Android?
(Link is in edited info above)
However after implementation, i get a network callback for the mobile but when i open URL connection and perform a request it seems to get stuck for ages (about 4 minutes) before i get the response.
I have a Huawei 5.0.1 phone, which is the highest i have available. Obviously this is not good. However it is not tested on 5.1 galaxy S6 and works.. so could be the phone.
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 8 years ago.
Improve this question
I was attempting to detect any device (desktop, mobile, tablet, etc.,) that logs into an enterprise network. This is a very dirty code I wrote. The code continuously checks for the connected devices and prints the new ones by checking against a set.
public class DeviceDetectAgent {
private static Set<String> connectedDevicesPast = new HashSet<String>();
private static void detectNewDevices() {
private Set<String> connectedDevicesPresent = new HashSet<String>(); // saves all devices detected in the previous poll
InetAddress localhost = InetAddress.getLocalHost();
byte[] iPAddress = localhost.getAddress();
for (int i=1; i<=254; i++) {
iPAddress[3] = (byte) i;
InetAddress inetAddress = InetAddress.getByAddress(iPAddress);
if (inetAddress.isReachable(1000)) {
String device = inetAddress.toString();
if (!connectedDevicesPast.contains(device)) {
System.out.println("New device " + device + "found.");
}
connectedDevicesPresent.add(device);
}
}
connectedDevicesPast = connectedDevicesPresent;
}
public static void main(String[] args) {
while (true) {
detectNewDevices();
Thread.sleep(1000);
}
}
}
My objective is to create an agent that detects a device logging into the network. Are there any improvements I can do in my code? I believe my code is too trivial.
Your solution has the following limitations.
First, device can close ICMP using its personal firewall. In this case it will not respond on ping and you will not see it.
Second, your solution is very slow. Ping may take a second, so you will spend ~4 minutes to complete your loop. Fortunately this problem can be fixed using NIO. Take a look on this code as an example or check other examples of asynchronous ping.
Fixing the first problem is not trivial. Generally you can think about 2 strategies:
try to discover device using other ports and protocols
try to catch device when it performs some kind of network activity.
Using other protocols is a bit complicated. Take a look on nmap - tool that already does this.
Catching other network activity can be done using PCAP or if you are implementing this in java JPCAP. You should however locate your spy in "correct" location in the network. The best is to use network mirroring.
I am using this code to check if a WiFi or mobile network is connected.
private boolean isOnline() {
ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo netInfo = cm.getActiveNetworkInfo();
if (netInfo != null && netInfo.isConnected()) {
return true;
}
return false;
}
This works fine. But what if my user is on a prepaid plan but doesn't have any credit for data? This method will still return true if data is enabled but my app will crash when it tries to download data from a server. How can I check for something like this?
I guess there are also other things that can halt my app accessing a server even when a wifi/mobile network is available.
You shouldn't crash anyway. Your download code should use try-catch to handle such problems. Communication problems during download are possible as well.
As a mobile platform, internet access on Android is inherently unreliable. As you are starting to realise, you should be writing your app so it is tolerant of intermittent data access.
You are catching some exceptions, but not handling them - that means that your app will continue past the exception as though it didn't happen, and then crashes because your httpClient object is in an invalid state and is likely throwing new exceptions, which you are not catching.