I'm looking for best technique to verify internet over WiFi or Cell. Let's say you are connected to some AP but you don't now if internet exists.
Today I have 2 options by using HttpURLConnection:
Download file from cdn server
to send request to trust web page like google.com and get response 200.
Any other ways?
All suggestions would be appreciated.
On some level, 'ability to access internet endpoints' is equivalent to 'having internet access'. You could consider some algorithm:
for (Endpoint site : theEntireInternet) {
if (can connect to site) return true;
}
return false;
which will conclusively establish connectivity. In other words, being able to connect to any one site is sufficient positive proof, but theoretically you would need to enumerate every site to prove non-connectivity. In practice, checking a few major sites is obviously sufficient. Otherwise (without some sort of meta-information about networks, ISPs, etc; which is unavailable) there's no way to conclusively demonstrate "internet" connectivity other than... connecting to the internet.
Of course as you comment, checking various internet-based applications can't hurt either; it's just a different form of an equivalent technique.
See the Telephony Manager and it's getDataSate() method it has four state
DATA_DISCONNECTED
DATA_CONNECTING
DATA_CONNECTED
DATA_SUSPENDED
You can get the instance of telephony manager --
TelephonyManager tm = (TelephonyManager)getSystemService(Telephony_Service);
Here it is:
to see the state of the data connection on the cell network
and for the WIFI, I would use this public class WifiInfo. From there you can use getIpAddress() or getDetailedStateOf(...)
Hope it's helpful.
Related
I usually don't like to post questions because I would rather figure things out myself, but I am ready to pull my hair out with this one. I am trying to interface with a Sony IP Camera using Java. One of the products of the company I work for uses a Sony IP camera (IPela EP550). I have been tasked with writing the new interface. I can connect to the stream using the VLC ActiveX embedded control, but I can't manipulate the PTZ of the camera from in Java. If I type: "http://xxx.xxx.xxx.xxx/command/ptzf.cgi?Move=left,0" in a web browser it will move, but I have tried every bit of code I can find with Google to get it to move with no success. This last thing I tried (because a page on Oracle said all I should have to do is open the connection):
URL url1 = new URL("http://xxx.xxx.xxx.xxx/command/ptzf.cgi?Move=left,0&t="+new Date().getTime());
HttpURLConnection con = (HttpURLConnection)url1.openConnection();
Any help will be appreciated. Thank you.
Joe
Check out whether the camera needs login.
type the url in the browser, get HTTP request header and put header data into your code!
I figured out how to do this. I am posting the solution in case anybody is looking to fix a similar problem. I took the basic idea in this Dr. Dobbs article and used it to get movement from the camera. I don't yet know why I can't get the camera to respond with URLConnection and HttpURLConnection, but using a Socket and PrintWriter to specifically print the GET request to the socket.
Currently I am working with the Schneider Power Logic electrical device. I want to read the data from the device and show the value in my system. So far, I discover J2mod, Jamod and Modbus4Java library. I used all modbus4java to connect and get the device's data.
Actually I still confuse whether I suppose to create Master side or Slave side. Based on my understanding, the device will be Slave and my system will be Master (1st question).
Below is the setting AT MY DEVICE. It indicate that the device in slave mode and its protocol is Modbus RTU. So, I need to create a master apps to communicate with it right which is using the ModbusRTU protocol right ? (2nd question)
Mode: Slave
Protocol: Modbus RTU
Address: 1
Baud Rate: 38400
Parity: None
Below is the code of my apps act as the Master and using the ModbusRTU protocol
public static void main(String[] args) throws ModbusTransportException, ErrorResponseException {
ModbusFactory factory = new ModbusFactory();
SerialParameters params = new SerialParameters();
params.setCommPortId("COM6");
params.setBaudRate(9600);
params.setDataBits(8);
params.setStopBits(1);
params.setParity(0);
ModbusMaster master = factory.createRtuMaster(params);
master.setTimeout(1000);
master.setRetries(0);
long start = System.currentTimeMillis();
try {
master.init();
} catch (Exception e) {
System.out.println( "Modbus Master Init Error: " + e.getMessage());
return;
}
try {
System.out.println("Reg. 1001 Value:" + master.getValue(1, RegisterRange.HOLDING_REGISTER, 3110, DataType.FOUR_BYTE_FLOAT_SWAPPED));
}
finally {
master.destroy();
}
System.out.println("Time elapsed: " + (System.currentTimeMillis() - start) + "ms");
}
This is the code that I get from the sample code provide by the Modbus4Java page. The other thing that concern me is the value of params.setCommPortId("COM6"); What other value than "COM6" that I can put there. Because basically it receive a String value. So am I able to put any String value to it ? And what is the function of this particular setCommPortID. (3rd question)
Looking at the sample code provide by the Modbus4Java page, it does not put the IP address of the device. But in my case, my device got an IP address. And the IP address only use in the Slave apps only. How should my system recognize the IP address of the device ? (4th question).
And after I run this code snippet, I got an error:
Stable Library
Native lib Version = RXTX-2.1-7
Java lib Version = RXTX-2.1-7
Modbus Master Init Error: com.serotonin.io.serial.SerialPortException: gnu.io.NoSuchPortException
Please, please and please help me. I been stuck with this almost a month. Really hope someone out there will be able to help me. Thank you in advance for any kind of help and suggestion.
I'm the maintainer for j2mod, so my answer is going to suggest you look at the test programs which are included with j2mod. You can find j2mod on SourceForge at this URL --
https://sourceforge.net/projects/j2mod/
I'm pretty good about answering questions there, but I also follow stackoverflow, so I can explain more here as well. There are a LOT of questions in here, so I apologize in advance if I've missed anything.
The Schneider device is the slave, or "server" and your application is the master or "client". Modbus is a master/slave protocol, with the master initiating all requests. Your application will be the master and responsible for making all requests of your device.
The exact communications will be provided by the device documentation. In this instance, you indicate that the device uses 38400 baud, and so forth. Those are the parameters you will use to update SerialParameters with the RXTX library (which just so happens to also be used by j2mod).
The value passed to setCommPortId() is the Windows COM port identifier - you should be able to pass any value which is associated with an actual COM port -- "COM1", "COM2", etc. Note that some USB converters change their COM port each time they are used, so you may be chasing port names.
You mentioned that your device also has an IP address. You cannot use the RTU classes and methods to access a Modbus/TCP device. The same is true for jamod and j2mod - most Modbus libraries have different classes for RTU and TCP transports (as well as ASCII and UDP, for libraries which support those other transports).
One of my apps uses a lot of HTTP requests to communicate with its back-end.
I use 2 different implementations to perform these requests:
The library Volley for most cases
A combination of AsyncTask and DefaultHttpClient for few cases
Most of the time, everything works well. But sometimes I have a bunch of network exceptions raised and shown into Crashlytics:
java.net.UnknownHostException: Unable to resolve host "mydomain.com": No address associated with hostname
Caused by: libcore.io.GaiException: getaddrinfo failed: EAI_NODATA (No address associated with hostname)
com.android.volley.ServerError
at com.android.volley.toolbox.BasicNetwork.performRequest(BasicNetwork.java:175)
at com.android.volley.NetworkDispatcher.run(NetworkDispatcher.java:110)
With a bit of research, I found that this is supposed to happen when the device has a really bad 3g/4g or behind a VPN/subnetwork so it can't reach my website.
How do I make sure the device is really connected to internet?
I actually perform these requests only if this function return true:
public static boolean isOnline(Context ctx) {
ConnectivityManager cm = (ConnectivityManager) ctx.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo netInfo = cm.getActiveNetworkInfo();
if (netInfo != null && netInfo.isConnectedOrConnecting()) {
return true;
}
return false;
}
Or should I just let it go and assume it is normal to get up to few hundreds of these warning per month?
In order to see if you have internet you have to do something more than check if you have a network connection. Because if your connected to a slow network, captive portal or a VPN you have a connection to the network but no actual internet or usable internet.
That's why you still need to check if you have internet/usable internet before you make a HTTP request by adding a simple ping to a server or Google (Because Google is up 99,99% of the time). You can also do it periodically or when you catch the first exception, that's up to you.
public Boolean isInternet() {
try {
Process process = java.lang.Runtime.getRuntime().exec("ping -c 1 www.google.com");
int returnVal = process.waitFor();
boolean reachable = (returnVal==0);
return reachable
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return false;
}
You can also use another method but the general idea is the same use something you know is almost always online and check if you can reach it.
However keep handling exceptions, because there is no way to always catch it and having a back up way of handling things can't hurt
How do I make sure the device is really connected to internet?
You have found out. That's what the errors are telling you.
How do I make sure the device is really connected to internet? I actually perform these requests only if this function return true:
I'm not in favour of this sort of thing:
if it tests exactly the same things as the actual request does, it is (i) duplicated work and (ii) not done at the same time
if it doesn't test exactly the same things as the actual request, you are likely to get both false positives and false negatives
in all cases, it's an attempt to predict the future. It might fail now and the request succeed, or succeed now and the request fail.
you have to write the error handling code for the request anyway.
In general the best way to test whether any resource is available is just to try to use it in the normal way, and deal with any adverse consequences as and when they arise.
Or should I just let it go and assume it is normal to get up to few hundreds of these warning per month?
I wouldn't say ServerError is normal. It's possible that the server managed to send that to you over a fully functioning network, so it may be a server or client bug you need to investigate. Network outages on the other hand are 'normal' in any topology and technology.
Yes you should check internet availability before making an HTTP request, it saves a lot for you.
The code you should is very good and far better than "pinging" any domain.
But still in your case your condition isn't going to be sufficient, because the adapter is actually connected but you may not be able to connect to your server due to poor connection.
So you should still handle time-out and IO exceptions that might happen while you're executing your requests.
-- Set time out for your Httpclient -- and i think volley by default has a timeout.
I'm writing a browser add-on (Chrome and Firefox) which, in a nutshell, does "some calculations" based upon the content of each page the user visits (i.e. we're not talking about the user's own pages), presenting the user with a score. In the case of particularly high scores, the page title, page URL, etc. is submitted (automatically) to a central service so that a kind of league table can be shown.
All of this works perfectly, but I want - where possible - to strip out all traffic from the pages of Intranets that our users happen to visit. (We don't store or transmit any page content, nonetheless there are privacy concerns, and we don't want anything to do with internal / corporate documents.)
In theory I can work out (to a reasonable degree of accuracy) whether an IP is likely to be from an intranet # Distinguish the between intranet and official IP addresses, but as the DOM doesn't provide access to the document's host IP, is it practical to try to determine the IP on the fly and then apply those IP rules, given the possibility that lookup services might be down/slow?
Would a simpler alternative - like pattern-matching for the TLD of the document's hostname - be nearly as good?
Any suggestions?
Update:
I was about to answer this myself with "I'll just do the IP check on the server, when the page stats are submitted, and only complete the submission if the IP is not within the internal range - it's much easier." ... unfortunately I can't do this: because my back-end is Google AppEngine [Java] and the InetAddress class is restricted, I can't do arbitrary IP lookups.
You should use nsIDNSService to resolve the host name in Firefox. Along these lines:
var threadManager = Components.classes["#mozilla.org/thread-manager;1"]
.getService(Components.interfaces.nsIThreadManager);
var dnsService = Components.classes["#mozilla.org/network/dns-service;1"]
.createInstance(Components.interfaces.nsIDNSService);
var listener = {
onLookupComplete: function(request, record, status)
{
if (Components.isSuccessCode(status))
alert("Host IP address: " + record.getNextAddrAsString());
else
alert("Lookup failed");
}
};
dnsService.asyncResolve("www.google.com", 0, listener,
threadManager.currentThread);
This is usually a very fast operation because the host name is already cached. Note: if you use the Add-on SDK then you will have to use chrome authority and replace access to Components properties by the respective aliases.
As to Chrome, I doubt that you can solve this problem properly there. As Korvin Szanto notes in his comment, any host name could point to a local address. And Chrome won't let you get the IP address that it talks to.
Is there a relatively simple way in Java to check if a domain is available or not?
I need a reliable method, so only checking if the connection can be made is not enough.
Domain availability depends on having a whois client. Here is a link to an implementation of a whois client in Java:
Java Whois Client
You'll need to parse the results - and depending on what whois server you use, you may (will) have varying formats that are returned. The best thing to do is to pay for a commercial whois/registration service such as OpenSRS. They have an extensive API which you can use as a registered reseller. Here are the API docs:
http://opensrs.com/resources/documentation/opensrs_xmlapi.pdf
HTH,
-aj
There's a good Whois Java client here:
https://github.com/ethauvin/Whois
You can run it from the command line or interface with it directly:
// don't include the www
Whois.main(new String[] {"skytouch.com"});
Another solution is to use Apache Commons lib. Simplified example:
import org.apache.commons.net.whois.WhoisClient;
public String getWhois(String domainName){
WhoisClient whois = new WhoisClient();
whois.setConnectTimeout(10000);
whois.setDefaultTimeout(10000);
whois.connect("whois.verisign-grs.com", 43);
String domainWhois = whois.query(domainName);
whois.disconnect();
return domainWhois;
}
Check if response equals "no match". Whois servers, timeout length and no availability response differ according to extension so you should have prepared additional collections for them.
Whois servers list can be found:
http://www.mit.edu/afs/athena/contrib/potluck/Net-Services/whois-servers.list
https://raw.githubusercontent.com/whois-server-list/whois-server-list/master/whois-server-list.xml
http://www.nirsoft.net/whois_servers_list.html
If you try to make your queries concurrent, you will definitely get whois response "You have reached configured rate limit." or explicit exception in a code so you should repeat queries after some sleep.
Performing a DNS lookup on the domain is the easiest solution. All available domains will have no DNS record, and most registrars assign a default DNS entry upon registration.
WHOIS lookups will be your most reliable solution, particularly behind an ISP that spoofs their own server (with a "domain not found" page filled with ads) for any missing domain name.