Android Find devices on local network - java

I am trying to map the local network to see how many devices (particularly a device I have built) there are on the network and what IP addresses they have.
There are a few methods on this that I have found:
List devices on local network with ping
Android Scan Local Subnet
Why does InetAddress.isReachable return false, when I can ping the IP address?
How do I test the availability of the internet in Java?
The last link is the one I have been able to get working, but it is not very reliable (at least not my implementation of it). When I run the code on my phone it will rarely detect my device (only a few out times of dozens of attempts) on the network.
The device is a TI CC3200 that I have setup as a webserver. I am able to reliably ping the CC3200 with my laptop and I can access the webpage on it nearly 100% of the time using my laptop, phone browser, or using WebView in the app.
I have a serial link with the CC3200 and I can see that the app connects to the CC3200 while it is scanning the network.
I am I doing something incorrect? or is there a better method of mapping the local network that I should focus my effort on?
public boolean scan(final String IP) {
Globals success = Globals.getInstance();
success.setDataString(IP);
Thread thread = new Thread(new Runnable() {
#Override
public void run() {
try {
Globals success = Globals.getInstance();
URL url = new URL("http://" + IP);
URLConnection conn = url.openConnection();
conn.setConnectTimeout(2000);
conn.setReadTimeout(2000);
InputStream in = conn.getInputStream();
success.setDataBool(true);
} catch (SocketTimeoutException e) {
Globals success = Globals.getInstance();
success.setDataBool(false);
e.printStackTrace();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
});
thread.start();
//boolean temp2 = success.getDataBool();
return success.getDataBool();
}
}

Related

how to search for network in android studio while using socket?

public void connect() {
final String msg = "";
Thread thread = new Thread(new Runnable() {
#Override
public void run() {
try {
s = new Socket("192.168.1.3", 1337);
textView.setText("Connection acquired");
out = s.getOutputStream();
output = new PrintWriter(out);
output.println(msg);
textView.setText("message sent : " + msg.length());
output.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
});
thread.start();
}
I am using the above code to connect to desired IP [192.168.1.3]... I have created another program at the other end... The problem is that the IP sometimes changes to 192.168.1.4 or 192.168.1.6... and when I use another network it changes to 192.168.43.2... now due to this I have to go every time into the code and change it manually....
Is there any function or any other thing that might search for IPs available then check if desired port exists and then connect... Thanks in advance
That's why DNS names exist. If you use an IP address, you have to use that exact address. If you use DNS, you do a name->IP lookup. Get a dynamic DNS provider and use that to give your server a name.
You really do not want to start port scanning to find open ports. You will be treated as an attacker and kicked off the network, because you really would be doing something attackers do.

How to make sure that my windows system is connected to network

I am creating a utility that also has a list of few ip addresses that are attached to my network.
I need to create a module that keeps refreshing that list so that only alive IP's are present in that list.
I have thought of achieving this by using PING on each of the IP's and remove non responsive ones.
Problem is that I dont want to delete IP's when my System itself is not connected to network as in that case all of the IP's will get deleted for obvious reasons.
How can I be sure that my system is connected to some network?
I am using Java.
I have tried looking over other questions but could not find anything relevant.
[EDIT1]
IP list is manually added set,and server has several more IP's which I dont need to care about.So I cant do a lookup in entire server as suggested by #Hoijf below. Also the IP's change consistently, thats why I need to keep my list updated so that we can replace non responsive servers/IP.
Problem is that I dont want to delete IP's when my System itself is
not connected to network as in that case all of the IP's will get
deleted for obvious reasons.
This is a typical network isolation problem. You should consider cases where your LAN is still up (ipconfig would show NIC's status as UP), but, you've lost internet connectivity (at some upstream router). As a solution, you could consider pinging a reference IP/host that is always supposed to be up.
So, you should create a policy in your program to ping this reference host to check if you should remove the host from your active list.
Scan the network and save the IPs which are active.
Store the IPs in an array and iterate over this array until the user chooses to stop or refresh (back to step 1).
Display the status of each IP.
public class temp
{
static ArrayList<InetAddress> history = new ArrayList<InetAddress>();
static Timer timer;
static InetAddress add;
public static void main(String[] args)
{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int timeout = 25;
timer = new Timer(1000, new ActionListener()
{
#Override
public void actionPerformed(ActionEvent e)
{
for(InetAddress ii : history)
{
try
{
System.out.println(ii+" >> "+ii.isReachable(timeout));
} catch (IOException e1){System.out.println(ii+" >> Failed");}
}
}
});
Thread t = new Thread(new Runnable()
{
#Override
public void run()
{
while(true)
{
try
{
history.add(InetAddress.getByName(br.readLine()));
} catch (UnknownHostException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
});
t.start();
timer.start();
}
}

Client-Server connects while being on the same computer but not while being run on different ones

I'm trying to build a basic client-server application.
When I run both the server and the client on the same computer both manage to connect without a hitch but if I try to do so from different computers (desktop and laptop) the connection doesn't get though. The server isn't even aware that someone tried to connect to it while the client timeouts after a while. At first I assumed that it's a firewall problem but disabling the firewall completely on the server PC did not help. Tried changing ports and checked on multiple computers. Any ideas what could cause this?
I control both the server and the client and can change the code of both if necessary. The server always runs on the same PC and I'm connecting to it directly using hardcoded IP address.
This is the code of the client sending random int to the server.
public static void main(String[] args) {
Socket s = new Socket();
try {
s.connect(new InetSocketAddress("123.45.67.891", 8084), 5000);
s.getOutputStream().write(42);
s.close();
} catch (IOException e) {
e.printStackTrace();
return;
}
}
The server is slightly more complicated but considering the fact that they manage to connect while being run from the same PC I assume that the problem isn't with it.
edit: Server code (Thread per client. There shouldn't be too many of those)
public void run() {
try {
serverSocket = new ServerSocket(listenPort); //integer
} catch (IOException e) { ... }
while (shouldRun) {
try {
Socket clientSocket = serverSocket.accept(); // Blocked here while trying to connect from remote computer
//Never gets here
ConnectionHandler newConnection = connectionHandlerCreator.create(clientSocket);
connectionHandlers.add(newConnection);
newConnection.initialize();
new Thread(newConnection).start();
} catch (IOException e) { ... }
}
}
Initialize consists of the following (which latter used for I/O).
in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
out = new PrintWriter(clientSocket.getOutputStream(), true);
The problem is probably on your server side though: you have to make it respond to all ip's not just local one, by using the constructor:
ServerSocket(int port)
it will default accepting connections on any addresses which is not the case if you specified an IP

How to get and/or set the link key when pairng bluetoth devices using Android(Java)?

I'm really new on this of Android development, so I have many questions. Right now I'm trying to connect two devices via Bluetooth. So far I was able to do this, I have connected two tablets, but now I'm asked to save the LinkKey and use some bytes of it to create a PIN. So, how can I get that LinkKey? I've read that it's saved on both devices for future connections, but I don't know how to get it.
Also, I've read that this devices can delete those LinkKey, what happens then? If they try to connect with each other again, will they use the same LinkKey or a new one is created?
And the last thing. I have to connect a tablet to a device that has neither a display nor a keypad, a normal bluetooth connection is enough? I'm doing this to stablish the connection:
final UUID MY_UUID = UUID.randomUUID();
//tmp = device.createRfcommSocketToServiceRecord(MY_UUID);
Method m = null;
try {
m = device.getClass().getMethod("createRfcommSocket", new Class[] {int.class});
} catch (NoSuchMethodException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
tmp = (BluetoothSocket) m.invoke(device, 1);
mmSocket = tmp;
Thread connectionThread = new Thread(new Runnable(){
public void run() {
// Cancel discovery because it will slow down the connection
mBluetoothAdapter.cancelDiscovery();
try {
// Connect the device through the socket. This will block
// until it succeeds or throws an exception
mmSocket.connect();
} catch (IOException connectException) {
// Unable to connect; close the socket and get out
try {
mmSocket.close();
} catch (IOException closeException) { }
return;
}
// Do work to manage the connection (in a separate thread)
manageConnectedSocket(mmSocket);
}
Thanks.
Link key creation is done on the stack/LMP(Link Manager) level, not on the app level. Bluetooth devices check if the link key exist or not, if exist, it will not go for pairing and bluetooth connection will proceed, if no link key is found on the bluetooth stack, LMP(Link Manager) will initiate a new pairing process , once pairing completed, bluetooth connection will proceed. If link key is deleted, a new link key will be generated for a connection.
Try checking in adb shell (/data/misc/bluetoothd or data/misc/bluetooth) for link key , it will be available in the paired device info.

How to check if internet connection is present in Java?

How do you check if you can connect to the internet via java? One way would be:
final URL url = new URL("http://www.google.com");
final URLConnection conn = url.openConnection();
... if we got here, we should have net ...
But is there something more appropriate to perform that task, especially if you need to do consecutive checks very often and a loss of internet connection is highly probable?
You should connect to the place that your actual application needs. Otherwise you're testing whether you have a connection to somewhere irrelevant (Google in this case).
In particular, if you're trying to talk to a web service, and if you're in control of the web service, it would be a good idea to have some sort of cheap "get the status" web method. That way you have a much better idea of whether your "real" call is likely to work.
In other cases, just opening a connection to a port that should be open may be enough - or sending a ping. InetAddress.isReachable may well be an appropriate API for your needs here.
The code you basically provided, plus a call to connect should be sufficient. So yeah, it could be that just Google's not available but some other site you need to contact is on but how likely is that? Also, this code should only execute when you actually fail to access your external resource (in a catch block to try and figure out what the cause of the failure was) so I'd say that if both your external resource of interest and Google are not available chances are you have a net connectivity problem.
private static boolean netIsAvailable() {
try {
final URL url = new URL("http://www.google.com");
final URLConnection conn = url.openConnection();
conn.connect();
conn.getInputStream().close();
return true;
} catch (MalformedURLException e) {
throw new RuntimeException(e);
} catch (IOException e) {
return false;
}
}
People have suggested using INetAddress.isReachable. The problem is that some sites configure their firewalls to block ICMP Ping messages. So a "ping" might fail even though the web service is accessible.
And of course, the reverse is true as well. A host may respond to a ping even though the webserver is down.
And of course, a machine may be unable to connect directly to certain (or all) web servers due to local firewall restrictions.
The fundamental problem is that "can connect to the internet" is an ill-defined question, and this kind of thing is difficult to test without:
information on the user's machine and "local" networking environment, and
information on what the app needs to access.
So generally, the simplest solution is for an app to just try to access whatever it needs to access, and fall back on human intelligence to do the diagnosis.
If you're on java 6 can use NetworkInterface to check for available network interfaces.
I.e. something like this:
Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces();
while (interfaces.hasMoreElements()) {
NetworkInterface interf = interfaces.nextElement();
if (interf.isUp() && !interf.isLoopback())
return true;
}
Haven't tried it myself, yet.
This code should do the job reliably.
Note that when using the try-with-resources statement we don't need to close the resources.
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.UnknownHostException;
public class InternetAvailabilityChecker
{
public static boolean isInternetAvailable() throws IOException
{
return isHostAvailable("google.com") || isHostAvailable("amazon.com")
|| isHostAvailable("facebook.com")|| isHostAvailable("apple.com");
}
private static boolean isHostAvailable(String hostName) throws IOException
{
try(Socket socket = new Socket())
{
int port = 80;
InetSocketAddress socketAddress = new InetSocketAddress(hostName, port);
socket.connect(socketAddress, 3000);
return true;
}
catch(UnknownHostException unknownHost)
{
return false;
}
}
}
This code:
"127.0.0.1".equals(InetAddress.getLocalHost().getHostAddress().toString());
Returns - to me - true if offline, and false, otherwise. (well, I don't know if this true to all computers).
This works much faster than the other approaches, up here.
EDIT: I found this only working, if the "flip switch" (on a laptop), or some other system-defined option, for the internet connection, is off. That's, the system itself knows not to look for any IP addresses.
InetAddress.isReachable sometime return false if internet connection exist.
An alternative method to check internet availability in java is : This function make a real ICMP ECHO ping.
public static boolean isReachableByPing(String host) {
try{
String cmd = "";
if(System.getProperty("os.name").startsWith("Windows")) {
// For Windows
cmd = "ping -n 1 " + host;
} else {
// For Linux and OSX
cmd = "ping -c 1 " + host;
}
Process myProcess = Runtime.getRuntime().exec(cmd);
myProcess.waitFor();
if(myProcess.exitValue() == 0) {
return true;
} else {
return false;
}
} catch( Exception e ) {
e.printStackTrace();
return false;
}
}
I usually break it down into three steps.
I first see if I can resolve the domain name to an IP address.
I then try to connect via TCP (port 80 and/or 443) and close gracefully.
Finally, I'll issue an HTTP request and check for a 200 response back.
If it fails at any point, I provide the appropriate error message to the user.
URL url=new URL("http://[any domain]");
URLConnection con=url.openConnection();
/*now errors WILL arise here, i hav tried myself and it always shows "connected" so we'll open an InputStream on the connection, this way we know for sure that we're connected to d internet */
/* Get input stream */
con.getInputStream();
Put the above statements in try catch blocks and if an exception in caught means that there's no internet connection established. :-)
The code using NetworkInterface to wait for the network worked for me until I switched from fixed network address to DHCP. A slight enhancement makes it work also with DHCP:
Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces();
while (interfaces.hasMoreElements()) {
NetworkInterface interf = interfaces.nextElement();
if (interf.isUp() && !interf.isLoopback()) {
List<InterfaceAddress> adrs = interf.getInterfaceAddresses();
for (Iterator<InterfaceAddress> iter = adrs.iterator(); iter.hasNext();) {
InterfaceAddress adr = iter.next();
InetAddress inadr = adr.getAddress();
if (inadr instanceof Inet4Address) return true;
}
}
}
This works for Java 7 in openSuse 13.1 for IPv4 network. The problem with the original code is that although the interface was up after resuming from suspend, an IPv4 network address was not yet assigned. After waiting for this assignment, the program can connect to servers. But I have no idea what to do in case of IPv6.
1) Figure out where your application needs to be connecting to.
2) Set up a worker process to check InetAddress.isReachable to monitor the connection to that address.
This code is contained within a jUnit test class I use to test if a connection is available. I always receive a connection, but if you check the content length it should be -1 if not known :
try {
URL url = new URL("http://www.google.com");
URLConnection connection = url.openConnection();
if(connection.getContentLength() == -1){
fail("Failed to verify connection");
}
}
catch (IOException e) {
fail("Failed to open a connection");
e.printStackTrace();
}
public boolean checkInternetConnection()
{
boolean status = false;
Socket sock = new Socket();
InetSocketAddress address = new InetSocketAddress("www.google.com", 80);
try
{
sock.connect(address, 3000);
if(sock.isConnected()) status = true;
}
catch(Exception e)
{
status = false;
}
finally
{
try
{
sock.close();
}
catch(Exception e){}
}
return status;
}
You can simply write like this
import java.net.InetAddress;
import java.net.UnknownHostException;
public class Main {
private static final String HOST = "localhost";
public static void main(String[] args) throws UnknownHostException {
boolean isConnected = !HOST.equals(InetAddress.getLocalHost().getHostAddress().toString());
if (isConnected) System.out.println("Connected");
else System.out.println("Not connected");
}
}
There are (nowadays) APIs for this, but they are platform specific:
On Android ConnectivityManager (https://developer.android.com/training/basics/network-ops/reading-network-state) does everything you need.
On Windows INetworkListManager::GetConnectivity (for which you'll need a JNI)
On generic Linux, you are probably stuck with testing if you have access to a DNS server and Google, as above.
there is probably an Apple way to do this as well
(I'd use the specific tools where available)
This have worked well for me.
try{
InetAddress addr = InetAddress.getByName("google.com" );
}catch(IOException e){
JOptionPane.showMessageDialog(new JFrame(),"No Internet connection.\nTry again later", "Network Error", JOptionPane.ERROR_MESSAGE);
}
There is also a gradle option --offline which maybe results in the behavior you want.
The following piece of code allows us to get the status of the network on our Android device
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
TextView mtv=findViewById(R.id.textv);
ConnectivityManager connectivityManager=
(ConnectivityManager) this.getSystemService(Context.CONNECTIVITY_SERVICE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if(((Network)connectivityManager.getActiveNetwork())!=null)
mtv.setText("true");
else
mtv.setText("fasle");
}
}
}

Categories