We're doing a project coded in Java (compiled for JRE 1.6) and need some help with
a little but apparently complicated feature:
We want to do a certain action when a specific wireless network is connected e.g. when the connected SSID=="myNetworkAtHome" or similar.
After looking through this site, google and the Java documentation we have come a little closer.
After looking at the code here:
http://download.oracle.com/javase/tutorial/networking/nifs/retrieving.html
It seems we were getting close but it hits a deadend, all the interfaces seems to be connected to "net0" through "net13" (on my laptop that is.)
And we're unable to get the SSID out of any interface at all. I do realise the code in the example is only giving the interface names and not connected networks, but it doesn't seem to offer a way of fetching the connected network information.
Any help on this would be extremely helpfull!
You can't access this low-level details of the network in Java. You can get some details of the network interface with the NetworkInterface class but if you see at the provided methods, no one is related to Wifi networks nor any way to get the SSID is provided. As pointed below, you should use some native functionality through calling a native library with JNI or by calling a OS tool with Runtime.
Java is not designed to do that kind of things, is hard to implement in a platform-independent way and any hardware-level detail can not be managed in Java by principle.
Same applies to other networks like 3G, GPRS... the application should not be aware of the connection type nor its details. Java can only manage things at the Transport (TCP) level, not the network (IP) not Link (3G, Wifi, Ethernet...), so you can only manage sockets.
ArrayList<String>ssids=new ArrayList<String>();
ArrayList<String>signals=new ArrayList<String>();
ProcessBuilder builder = new ProcessBuilder(
"cmd.exe", "/c", "netsh wlan show all");
builder.redirectErrorStream(true);
Process p = builder.start();
BufferedReader r = new BufferedReader(new InputStreamReader(p.getInputStream()));
String line;
while (r.read()!=-1) {
line = r.readLine();
if (line.contains("SSID")||line.contains("Signal")){
if(!line.contains("BSSID"))
if(line.contains("SSID")&&!line.contains("name")&&!line.contains("SSIDs"))
{
line=line.substring(8);
ssids.add(line);
}
if(line.contains("Signal"))
{
line=line.substring(30);
signals.add(line);
}
if(signals.size()==7)
{
break;
}
}
}
for (int i=0;i<ssids.size();i++)
{
System.out.println("SSID name == "+ssids.get(i)+" and its signal == "+signals.get(i) );
}
You'll have to resort to a JNI solution. There's something available at http://sourceforge.net/projects/jwlanscan, but that only works for Windows systems. Or you could do it the ugly way and use Runtime.getRuntime().exec(...) and use the command line tools available for your OS (*nix = iwconfig) and resort to parsing.
Related
I am extremely new the Android app development and Stack Overflow. I am trying to recreate traceroute in an Android app since Android devices do not come with traceroute by default. I've encountered a couple stack overflow posts talking about solutions to this, but I have still run into challenges.
Traceroute on android - the top post on this thread links an Android Studio project that implements traceroute using ping. If I understand the algorithm correctly, it continually pings the destination IP, incrementing the time-to-live field to obtain information about intermediary routers. I've tried to recreate this behavior, but for certain values of TTL, the ping stalls and doesn't retrieve any router information. I'm not really sure why this happens. Here's a quick demo function I spun up... at some point in the loop the pings stall.
public static void smallTracerouteDemoShowingThatTheProgramStallsAtCertainTTLs() {
try {
String host = "google.com";
int maxTTL = 20;
for (int i = 1; i < maxTTL; i++) {
// Create a process that executes the ping command
Process p = Runtime.getRuntime().exec("ping -c 1 -t " + i + " " + host);
// Get a buffered reader with the information returned by the ping
BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream()));
// Convert the BufferedReader to a string
String dataReturnedByPing = "";
for (String line; (line = br.readLine()) != null; dataReturnedByPing += "\n"+line);
// Print out information about each TTL
System.out.println("TTL = " + i + " out of " + maxTTL);
System.out.println(dataReturnedByPing);
System.out.println("========================================");
}
} catch (Exception e) {
e.printStackTrace();
}
}
how to run traceroute command through your application? - The solution on this thread suggests using BusyBox. I've not used BusyBox as yet, but it seems like I would have to embed BusyBox into my app to get things to work. After doing some research it looks like BusyBox provides numerous Linux commands through one executable. I'm a bit hesitant to explore this option because I really only need the traceroute command. In addition, I know that Android targets a few different CPU architectures, and I'm not sure if one executable will support them all.
I've also run into a github repository that takes another approach to running traceroute:
https://github.com/wangjing53406/traceroute-for-android - In this repository the author embeds the traceroute source code into the project and uses the NDK to build the source code along with the rest of his app. I really like this approach because it feels the most "correct." It uses a built traceroute instead of a Java-based implementation, so you can't find yourself in a situation where the Java implementation gives you one thing and the actual traceroute gives you another. When I open this project to experiment with it, my build fails. The top line says:
org.gradle.initialization.ReportedException: org.gradle.internal.exceptions.LocationAwareException: A problem occurred configuring root project 'traceroute-for-android-master'.
Any help on why this happens or ways to troubleshoot it would be fantastic.
For reference, the minimum SDK I am targeting is API 21 and I am running on Android Studio 3.3.0.
So, at this point I'm stumped. If you were trying to make an app that would let you execute traceroute commands, how would you do it? I really like the NDK approach because it guarantees you're getting true traceroute behavior. If you have any guides to getting that set up for my Android version/SDK, I would appreciate if you would post them. If you'd take another approach I'd to hear about it as well.
Thank you in advance.
I'm trying to get current network speed like shown in System Monitor on GNOME.
I need this to be in terminal and if possible no installations needed (on most of distros this tool i need should be installed by default with the system).
So i don't want to ping anything or stuff like that, I just want to check speed in simplest way possible without adding new tools.
I hope there is a tool that will show information in terminal like System Monitor -> Resources -> Network history.
EDIT:
if there is a workaround in Java to get this information without using linux commands this would be great
It's difficult to know what tools you already have installed on your system. I'd recommend either bmon, ifstat, or ifstat -S if you want the information printed on the same time.
The above should be in your distro's central repository (aptitude, yum etc) so should be easy to install if they're not aready there.
The Java class InetAddress has an isReachable() method. You could try this:
public long getSpeed() {
InetAddress inet = InetAddress.getByName("stackoverflow.com");
long start = System.currentTimeMillis();
boolean reachable = inet.isReachable(5000);
if (reachable) {
long end = System.currentTimeMillis();
return end - start;
} else {
return -1;
}
}
This will 'sort of' do a ping, but how the isReachable() method is implemented is not really specified. Doing an actual ping command from Java itself is not supported though, so this is (I think) the best you can do.
We know how to force shutdown an computer using Java. For example, the following code works fine for force shutdown:
public static void main(String arg[]) throws IOException{
Runtime runtime = Runtime.getRuntime();
Process proc = runtime.exec("shutdown -s -t 0");
System.exit(0);
}
Now, suppose if I want to force startup a computer (which is in shut down state), at a particular time, is it possible to do in Java or any other language?
You need something to trigger the startup. The best way to trigger this is Wake On Lan.
If you want to do this in Java, this might be a good resource.
In addition to wake on lan, there are IPMI devices that run on some server-grade hardware that is connected to the motherboard and can control power as well as provide serial console output over a network connection. This computer is running all the time, but I'm not familiar with any you can load your own code onto.
You can control this device remotely to power control the server that is off from any language including java.
http://en.wikipedia.org/wiki/Intelligent_Platform_Management_Interface
If your BIOS supports Advanced Power Management (APM) version 1.2 or later, it should be possible to wake it from sleep/standy or hibernation based on a timer. On Windows an end user can do this through Task Scheduler, and if you wish to do it programmatically you can use the Task Scheduler interfaces.
I don't know how you would do this through Java, but here is some example C code that will create a task to wake the computer up 2 minutes in the future:
#include <mstask.h>
#include <time.h>
int main() {
HRESULT hr = CoInitialize(NULL);
if (SUCCEEDED(hr)) {
ITaskScheduler *scheduler;
hr = CoCreateInstance(CLSID_CTaskScheduler, NULL, CLSCTX_INPROC_SERVER, IID_ITaskScheduler, (void**)&scheduler);
if (SUCCEEDED(hr)) {
ITask *task;
hr = scheduler->NewWorkItem(L"Wake Timer", CLSID_CTask, IID_ITask, (LPUNKNOWN*)&task);
if (SUCCEEDED(hr)) {
WORD index;
ITaskTrigger *trigger;
hr = task->CreateTrigger(&index, &trigger);
if (SUCCEEDED(hr)) {
time_t t = time(NULL) + 120;
struct tm *ltime = localtime(&t);
TASK_TRIGGER triggertime;
memset(&triggertime, 0, sizeof(triggertime));
triggertime.cbTriggerSize = sizeof(TASK_TRIGGER);
triggertime.wBeginYear = ltime->tm_year+1900;
triggertime.wBeginMonth = ltime->tm_mon+1;
triggertime.wBeginDay = ltime->tm_mday;
triggertime.wStartHour = ltime->tm_hour;
triggertime.wStartMinute = ltime->tm_min;
triggertime.TriggerType = TASK_TIME_TRIGGER_ONCE;
trigger->SetTrigger(&triggertime);
trigger->Release();
}
task->SetFlags(TASK_FLAG_DELETE_WHEN_DONE|TASK_FLAG_SYSTEM_REQUIRED|TASK_FLAG_RUN_ONLY_IF_LOGGED_ON);
task->SetAccountInformation(L"", NULL);
IPersistFile *file;
hr = task->QueryInterface(IID_IPersistFile, (void**)&file);
if (SUCCEEDED(hr)) {
file->Save(NULL, TRUE);
file->Release();
}
task->Release();
}
scheduler->Release();
}
CoUninitialize();
}
return 0;
}
Assumedly if you can do this on Windows, there must be equivalent APIs for other operating systems.
I did manage to find a similar question floating around on the internet, so I'll post the links here to see if you find it helpful. (this was the thread I found: http://www.coderanch.com/t/440680/gc/interact-Windows-Task-Scheduler-Java)
First of all though, I might add that Java is a language that must run in a Virtual Machine - there are no two ways around it. I'm not well versed in 'low-level' programming, such as programming at closer to BIOS level, which is sort of where we are heading with this.
As the question was explicitly about Java, the best I could come up with from research, is (if you're really wanting to use Java for something), using the JAVA-COM (JACOB) http://sourceforge.net/projects/jacob-project/ which allows you to hook into the Windows Task Scheduler http://msdn.microsoft.com/en-us/library/aa383581%28VS.85%29.aspx via the COM language (AF
As far as I am aware, because Java needs to be in a virtual machine to run, there would be no way of getting it to do an action such as turning on a PC - let's not even get into issues of whether such an action would require administrator or above privileges.
Hope that helps.
I want to implement the expect "interact" command using java. In expect, it's possible to open an ssh session, authenticate and, then, use the "interact" command to give the control back to the user. Is that possible with java? I've tried with expectJ, expect4J and expectForJava but there's little documentation and almost no examples of how to do this. TIA.
Update: for "interact" command reference, please check this out: http://wiki.tcl.tk/3914
"Interact is an Expect command which gives control of the current
process to the user, so that keystrokes are sent to the current
process, and the stdout and stderr of the current process are
returned."
In case anyone is interested, I have added basic interactive loop support to ExpectIt, my own open source Expect for Java implementation (sorry for self-promotion), since version 0.8.
Here is an example of interacting with the system input stream in Java 8:
try (final Expect expect = new ExpectBuilder()
.withInputs(System.in)
.build()) {
expect.interact()
.when(contains("abc")).then(r -> System.out.println("A"))
.when(contains("xyz")).then(r -> System.err.println("B"))
.until(contains("exit"));
System.out.println("DONE!");
}
System.in.close();
These libraries might suit your needs better:
SSHJ
https://github.com/shikhar/sshj
JSCH
http://www.jcraft.com/jsch/
I've run into a known bug with Java 6 on Windows. My understanding is that the normal way to get the netmask is to look up the network prefix length and do some bit shifts. The problem is that on Windows the prefix length is often returned incorrectly, so we get a 128 when we should get a 24 or 20.
In this solution, it is suggested to put -Djava.net.preferIPv4Stack=true on the Java command line. Unfortunately, on Windows 7, adding that as either a VM parameter or on the Java command line seems to have no effect.
(a) Does anyone know any OTHER work-arounds for this problem that might still work on Windows 7?
(b) Alternatively, is there an entirely different way to get the netmask that is reliable?
Thanks!
P.S. Here is the bug report that pertains to this.
The -Djava.net.preferIPv4Stack=true VM option should work under any OS. Alternatively, it can be put into Java code as System.setProperty("java.net.preferIPv4Stack","true");. Unless, something (library or whatever) is resetting its true state.
The code below displays the subnet mask. On a computer with more than one network connection (like a laptop with a wireless and Cat-5 Ethernet connection) it may write the subnet mask twice because there can be two different IP addresses for the client.
String os = System.getProperty("os.name");
try {
if(os.indexOf("Windows 7")>=0) {
Process process = Runtime.getRuntime().exec("ipconfig");
process.waitFor();
InputStream commandOut= process.getInputStream();
BufferedReader in = new BufferedReader(new InputStreamReader(commandOut));
String line;
while((line = in.readLine()) !=null) {
if(line.indexOf("Subnet Mask")>=0) {
int colon = line.indexOf(":");
System.out.println(line.substring(colon+2));
}
}
}
catch(IOException ioe) { }
catch(java.lang.InterruptedException utoh) { }
On my laptop with both a wired and wireless connection active, I get this output:
255.255.254.0
255.255.254.0
When I turn off my wireless connection, I only see one line of output for the wired Ethernet link, as expected.
Since the problem us just in Windows 7, why not look for an OS specific solution?
I know we can launch windows programs from Java, including the windows command line or bat files. There must be a way to re-direct the output of ipconfig to a text file in windows. Your program should be able to get the subnet mask by calling ipconfig and then reading the output.