Recently I added "adb devices" in the nano ./bash_profile so that I can run it from any directory.
I used one java application to run
public static void main(String [] args) {
executeCmd("adb devices");
}
private static void executeCmd(String string) {
InputStream pipedOut = null;
try {
Process aProcess = Runtime.getRuntime().exec(string);
// These two thread shall stop by themself when the process end
Thread pipeThread = new Thread(new StreamGobber(aProcess.getInputStream()));
Thread errorThread = new Thread(new StreamGobber(aProcess.getErrorStream()));
pipeThread.start();
errorThread.start();
aProcess.waitFor();
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException ie) {
ie.printStackTrace();
}
}
class StreamGobber implements Runnable {
private InputStream Pipe;
public StreamGobber(InputStream pipe) {
if(pipe == null) {
throw new NullPointerException("bad pipe");
}
Pipe = pipe;
}
public void run() {
try {
byte buffer[] = new byte[2048];
int read = Pipe.read(buffer);
while(read >= 0) {
System.out.write(buffer, 0, read);
read = Pipe.read(buffer);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if(Pipe != null) {
try {
Pipe.close();
} catch (IOException e) {
}
}
}
when I run any other commands such as "ls" it's working fine!!
I'm using mac ..
thanks :)
Maybe global path problem on mac. You can try run with absolute adb program path as command.
Related
I have to create a simple rotating proxy application where 100 requests get evenly distributed to 10 devices. I've got the following structure:
WebServer with a Java-SocketServer running. All Android devices are connected to this Socket-Server to be able to know which devices are currently online and for determining which device should be used for the next request.
10 Android devices in different networks. They are connected to the Socket Server and are waiting for requests that should be forwarded to the remote address and then sent back to the SocketServer.
In easy words: I basically have to create an application similar like Honeygain, Peer2Profit or IPRoyal Pawns so that I can later do requests like this:
//Use "-x" to set Proxy-IP and Proxy-Port
curl -x ANDROID_DEVICE_IP:PORT -L https://www.google.com
I managed to have an always running proxy service in an Android application. It basically looks like this and just forwards HTTP-Requests from Port 1440 to the desired remote address and then sends the response back to the original client. The Proxy basically works fine.
public class ProxyServerThread extends Thread {
public static void main(String[] args) {
(new ProxyServerThread()).run();
}
public ProxyServerThread() {
super("Server Thread");
}
#Override
public void run() {
try (ServerSocket serverSocket = new ServerSocket(1440)) {
Socket socket;
try {
while ((socket = serverSocket.accept()) != null) {
(new Handler(socket)).start();
}
} catch (IOException e) {
e.printStackTrace(); // TODO: implement catch
}
} catch (IOException e) {
e.printStackTrace(); // TODO: implement catch
return;
}
}
public static class Handler extends Thread {
public static final Pattern CONNECT_PATTERN = Pattern.compile("CONNECT (.+):(.+) HTTP/(1\\.[01])", Pattern.CASE_INSENSITIVE);
private final Socket clientSocket;
private boolean previousWasR = false;
public Handler(Socket clientSocket) {
this.clientSocket = clientSocket;
}
#Override
public void run() {
try {
String request = readLine(clientSocket);
System.out.println(request);
Matcher matcher = CONNECT_PATTERN.matcher(request);
if (matcher.matches()) {
String header;
do {
header = readLine(clientSocket);
} while (!"".equals(header));
OutputStreamWriter outputStreamWriter = new OutputStreamWriter(clientSocket.getOutputStream(), "ISO-8859-1");
final Socket forwardSocket;
try {
forwardSocket = new Socket(matcher.group(1), Integer.parseInt(matcher.group(2)));
System.out.println(forwardSocket);
} catch (IOException | NumberFormatException e) {
e.printStackTrace(); // TODO: implement catch
outputStreamWriter.write("HTTP/" + matcher.group(3) + " 502 Bad Gateway\r\n");
outputStreamWriter.write("Proxy-agent: Simple/0.1\r\n");
outputStreamWriter.write("\r\n");
outputStreamWriter.flush();
return;
}
try {
outputStreamWriter.write("HTTP/" + matcher.group(3) + " 200 Connection established\r\n");
outputStreamWriter.write("Proxy-agent: Simple/0.1\r\n");
outputStreamWriter.write("\r\n");
outputStreamWriter.flush();
Thread remoteToClient = new Thread() {
#Override
public void run() {
forwardData(forwardSocket, clientSocket);
}
};
remoteToClient.start();
try {
if (previousWasR) {
int read = clientSocket.getInputStream().read();
if (read != -1) {
if (read != '\n') {
forwardSocket.getOutputStream().write(read);
}
forwardData(clientSocket, forwardSocket);
} else {
if (!forwardSocket.isOutputShutdown()) {
forwardSocket.shutdownOutput();
}
if (!clientSocket.isInputShutdown()) {
clientSocket.shutdownInput();
}
}
} else {
forwardData(clientSocket, forwardSocket);
}
} finally {
try {
remoteToClient.join();
} catch (InterruptedException e) {
e.printStackTrace(); // TODO: implement catch
}
}
} finally {
forwardSocket.close();
}
}
} catch (IOException e) {
e.printStackTrace(); // TODO: implement catch
} finally {
try {
clientSocket.close();
} catch (IOException e) {
e.printStackTrace(); // TODO: implement catch
}
}
}
private static void forwardData(Socket inputSocket, Socket outputSocket) {
try {
InputStream inputStream = inputSocket.getInputStream();
try {
OutputStream outputStream = outputSocket.getOutputStream();
try {
byte[] buffer = new byte[4096];
int read;
do {
read = inputStream.read(buffer);
if (read > 0) {
outputStream.write(buffer, 0, read);
if (inputStream.available() < 1) {
outputStream.flush();
}
}
} while (read >= 0);
} finally {
if (!outputSocket.isOutputShutdown()) {
outputSocket.shutdownOutput();
}
}
} finally {
if (!inputSocket.isInputShutdown()) {
inputSocket.shutdownInput();
}
}
} catch (IOException e) {
e.printStackTrace(); // TODO: implement catch
}
}
private String readLine(Socket socket) throws IOException {
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
int next;
readerLoop:
while ((next = socket.getInputStream().read()) != -1) {
if (previousWasR && next == '\n') {
previousWasR = false;
continue;
}
previousWasR = false;
switch (next) {
case '\r':
previousWasR = true;
break readerLoop;
case '\n':
break readerLoop;
default:
byteArrayOutputStream.write(next);
break;
}
}
return byteArrayOutputStream.toString("ISO-8859-1");
}
}
}
Here comes the Problem:
Everything works fine but only on the local network. I cannot manage to get this to work without port forwarding. Since all devices are on their mobile cellular data I need a way to be able to connect to the device anyway.
How do the mentioned apps manage to connect to the devices?
I want to open an application during run time in Mac using netbeans i used the following code but it throws exception. I used this code for windows with few changes i used it in Mac. Can anyone pls suggest me the correct code.
else
{
try {
Runtime r = Runtime.getRuntime();
p = Runtime.getRuntime().exec("/Applications/TextEdit.app /Users/apple/Documents/java files/scratch files/hi.rtf");
A4 a4sObj = new A4(new String[]{jComboBox2.getSelectedItem().toString()});
} catch (IOException ex) {
Logger.getLogger(serialportselection.class.getName()).log(Level.SEVERE, null, ex);
}
}
Okay, so that took a little bit of digging. It seems the preferred way to run a .app bundle is to use the open command. In order to get the app to open a file, you have to use the -a parameter, for example...
import java.io.IOException;
import java.io.InputStream;
public class Test {
public static void main(String[] args) {
String cmd = "/Applications/TextEdit.app";
//String cmd = "/Applications/Sublime Text 2.app";
String fileToEdit = "/Users/.../Documents/Test.txt";
System.out.println("Cmd = " + cmd);
ProcessBuilder pb = new ProcessBuilder("open", "-a", cmd, fileToEdit);
pb.redirectErrorStream(true);
try {
Process p = pb.start();
Thread t = new Thread(new InputStreamConsumer(p.getInputStream()));
t.start();
int exitCode = p.waitFor();
t.join();
System.out.println("Exited with " + exitCode);
} catch (IOException | InterruptedException ex) {
ex.printStackTrace();
}
}
public static class InputStreamConsumer implements Runnable {
private InputStream is;
public InputStreamConsumer(InputStream is) {
this.is = is;
}
#Override
public void run() {
int read = -1;
try {
while ((read = is.read()) != -1) {
System.out.print((char)read);
}
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
}
How to make sure process (java.lang.Process) is alive in Java 1.7. In Java 1.8, there is isAlive() method. How can it be done in Java 1.7.
Thank you!
Probably wait too late, but since I faced the same problem, here is my solution:
Just copy the implementation of the Process.isAlive() method from Java 8:
public boolean isAlive() {
try {
exitValue();
return false;
} catch(IllegalThreadStateException e) {
return true;
}
}
with out knowing about the context of need of the Process. But in general, we could use Threads with Executors framework..
Executors.newCachedThreadPool()
Then submit Tasks to it...
I used the following for monitoring multiple processes launched through a Swing application. It follows the same logic mentioned by #mastah. See whether it helps.
package snippet;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
public class ProcessMonitor extends Thread {
private Process process;
private int exitCode;
public ProcessMonitor(Process process) {
this.process = process;
start();
}
#Override public void run() {
try {
exitCode = process.waitFor();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public void setOutputStream(final OutputStream s) {
new Thread(new Runnable() {
#Override public void run() {
InputStream is = process.getInputStream();
int c ;
try {
while((c = is.read()) >= 0) {
s.write(c);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
}
public void setErrorStream(final OutputStream s) {
new Thread(new Runnable() {
#Override public void run() {
InputStream is = process.getErrorStream();
int c ;
try {
while((c = is.read()) >= 0) {
s.write(c);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
}
public int getExitCode() {
return exitCode;
}
public static void main(String[] args) throws IOException, InterruptedException {
if(args.length == 1) {
System.err.println("In child process.. going to sleep for 1 second");
Thread.sleep(1000);
System.err.println("In child process.. done sleep exiting...");
System.exit(-1);
}
String[] pbArgs = new String[] {
"java", "-cp", System.getProperty("java.class.path"), ProcessMonitor.class.getName(), "arg"
};
ProcessBuilder pb = new ProcessBuilder(pbArgs);
pb.redirectErrorStream(true);
System.out.println("Starting process: " + pb.command());
final Process process = pb.start();
ProcessMonitor pm = new ProcessMonitor(process);
pm.setOutputStream(System.err);
while (pm.isAlive()) {
System.out.println("Process is still alive");
Thread.sleep(1000);
}
System.out.println("Process exited with: " + pm.getExitCode());
}
}
I want to launch a child proces and read its output until EOF or until an internal flag is cleared.
My first attempt was to call InputStream.close() in another thread, but although it works for sockets, it doesn't work with the result of Process.getInputStream(): the main thread is still waiting in read() and the killer thread either hangs in close0() (windows) or continues with no effect (linux).
Then I tried to check InputStream.available(), but it doesn't detect EOF: it returns 0.
public class BbbTest extends TestCase {
private Process proc;
private InputStream getStream() throws IOException {
//if ("".length() == 0) return new java.net.Socket("intra", 80).getInputStream();
String[] cmd;
if (System.getProperty("os.name").toLowerCase().startsWith("windows")) {
cmd = new String[] { "cmd", "/c", "more & more" };
} else {
cmd = new String[] { "sh", "-c", "cat; cat" };
}
Process proc = Runtime.getRuntime().exec(cmd);
return proc.getInputStream();
}
public void testB() throws Exception {
final InputStream in = getStream();
final Thread readingThread = Thread.currentThread();
Thread t = new Thread("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx") {
#Override
public void run() {
try {
sleep(1000);
if (proc != null) proc.destroy(); // this won't help
readingThread.interrupt(); // this won't help either
in.close(); // this will do nothing and may even hang
} catch (RuntimeException e) {
throw e;
} catch (Exception e) {
throw new RuntimeException ( );
}
}
};
t.setDaemon(true);
t.start();
try {
in.read();
assertTrue(false);
} catch (IOException e) {
// nothing
}
}
}
My last hope is to steal the channel from the returned stream and use nio
In windows , this Command will not terminate.
cmd = new String[] { "cmd", "/c", "more & more" };
Instead of try this simple command
cmd = new String[] { "cmd", "/c", "dir" };
And if you want to read your stream
public static void slurp(final InputStream is, final int bufferSize)
{
try(final Reader in = new InputStreamReader(is, "UTF-8");
BufferedReader br = new BufferedReader(in);){
String line;
while ((line = br.readLine()) != null) {
System.out.println(line);
}
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
Call this method by passing stream like this.
final BbbTest bbTest = new BbbTest();
Thread t = new Thread("xsdfds") {
#Override
public void run() {
try {
slurp(bbTest.getStream());
} catch (RuntimeException e) {
throw e;
} catch (Exception e) {
throw new RuntimeException ( );
}
}
};
t.start();
If you want to kill the process from child thread.
Create setter and getter method for Process in BbbTest like this
public class BbbTest {
private Process proc;
/**
* #return the proc
*/
public Process getProc() {
return proc;
}
/**
* #param proc the proc to set
*/
public void setProc(Process proc) {
this.proc = proc;
}
private InputStream getStream() throws IOException {
String[] cmd;
if (System.getProperty("os.name").toLowerCase().startsWith("windows")) {
// cmd = new String[] { "cmd", "/c", "more & more" };
cmd = new String[] { "cmd", "/c", "dir" };
} else {
cmd = new String[] { "sh", "-c", "cat; cat" };
}
proc = Runtime.getRuntime().exec(cmd);
return proc.getInputStream();
}
}
Now using process you can destroy
bbTest.getProc().destroy();
If you want to kill the process based on output of other stream, you can add logic in slurp method by checking line content and terminate using destroy
UPDATE
Simple Demo
public class BbbTest {
private Process startProcess(String[] commands) throws IOException {
Process proc = Runtime.getRuntime().exec(commands);
return proc;
}
public static void slurp(final InputStream is)
{
try(final Reader in = new InputStreamReader(is, "UTF-8");
BufferedReader br = new BufferedReader(in);){
String line;
while ((line = br.readLine()) != null) {
System.out.println(line);
if (line.equals("end")){
break;
}
}
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String args[]) throws Exception {
final BbbTest bbTest = new BbbTest();
final Process process = bbTest.startProcess(new String[] { "cmd", "/c", "more" });
Thread t = new Thread("xsdfds") {
#Override
public void run() {
try {
slurp(process.getInputStream());
process.destroy();
} catch (RuntimeException e) {
throw e;
} catch (Exception e) {
throw new RuntimeException ( );
}
}
};
t.start();
try(OutputStream out = process.getOutputStream();
BufferedOutputStream outStream = new BufferedOutputStream(out);){
outStream.write("Test".getBytes());
outStream.write("\n".getBytes());
outStream.write("end".getBytes());
outStream.write("\n".getBytes());
outStream.flush();
}
}
}
Look at this sample : You should have some condition to terminate the child thread ( reading prcoess) like if the stream writes "end" / or End of EOF ( process closed inputstream )
We have a windows application, which was tested on Windows XP, 7, 8, 8.1. Application consists of 2 parts: Bootstrap and main application. Bootstrap assures updates of the main app, and updates main app at a particular point. But users were able to force stop Boostrap process via the Task Manager (Ctrl+Shift+ESC->processes) by killing a process named javaw. In that case main app would not update and elder version would be launched. To avoid such issue we introduced interface of Bootstrap with main application via Socket. Here are the VM parameters of Bootstrap when it starts:
javaw.exe -Xms75M -Xmx90M -Xincgc -jar bootstrap.jar
There is a class SocketServer in the bootstrap:
public class Provider {
ServerSocket providerSocket;
Socket connection = null;
ObjectOutputStream out;
ObjectInputStream in;
String message;
public Provider() {
}
public void run() {
try{
providerSocket = new ServerSocket(54345);
connection = providerSocket.accept();
out = new ObjectOutputStream(connection.getOutputStream());
out.flush();
in = new ObjectInputStream(connection.getInputStream());
sendMessage("Connection successful");
do {
try {
message = (String)in.readObject();
if (message.equals("bye")) {
sendMessage("bye");
}
} catch(ClassNotFoundException cnfe) {
cnfe.printStackTrace();
}
} while (!message.equals("bye"));
} catch(IOException ioe) {
ioe.printStackTrace();
} finally {
try {
in.close();
out.close();
providerSocket.close();
} catch(IOException ioef) {
ioef.printStackTrace();
}
}
}
public void sendMessage(String msg) {
try {
out.writeObject(msg);
out.flush();
} catch(IOException ioe) {
ioe.printStackTrace();
}
}
public void stop() {
if (providerSocket != null && in != null && out != null && !providerSocket.isClosed()) {
try {
in.close();
out.close();
providerSocket.close();
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
}
}
Main app is being started by Bootstrap via ProcessBuilder like so:
public static void communicate(Process process) {
final BufferedReader stdOut = new BufferedReader(new InputStreamReader(process.getInputStream(), Charset.forName("Windows-1251")));
final BufferedReader stdErr = new BufferedReader(new InputStreamReader(process.getErrorStream(), Charset.forName("Windows-1251")));
//InputStream
new Thread() {
#Override
public void run() {
String line;
try {
while ((line = stdOut.readLine()) != null) {
debugOut(line);
}
} catch (Exception e) {
e.printStackTrace();
}
try {
stdOut.close();
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
}.start();
//ErrorStream
new Thread() {
#Override
public void run() {
String line;
try {
while ((line = stdErr.readLine()) != null) {
debugOut(line);
}
} catch (Exception e) {
e.printStackTrace();
}
try {
stdErr.close();
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
}.start();
try {
final Provider provider = new Provider();
ExecutorService pEexec = Executors.newCachedThreadPool();
Future<Void> FPExec = pEexec.submit(new Callable<Void>() {
#Override
public Void call() throws Exception {
while (!Thread.currentThread().isInterrupted()) {
provider.run();
}
return null;
}
});
pEexec.shutdown();
process.waitFor();
debugOut("[MainApp] Exit");
provider.stop();
FPExec.cancel(true);
debug("Destroy process");
process.destroy();
} catch (Exception e) {
e.printStackTrace();
}
}
public static void startApp() {
try {
ArrayList<String> params = new ArrayList<String>();
...
params.add("-Xms32M");
params.add("-Xmx48M");
params.add("-Xincgc");
params.add("-cp");
params.add(new File(pathToJar, "mainapp.jar").getPath());
params.add("net.craftwork.mainapp.AppStart");
params.add(licCode());
ProcessBuilder procBuild = new ProcessBuilder(params);
debugOut("[MainApp] Start");
Process proc = procBuild.start();
communicate(proc);
} catch (Exception e) {
e.printStackTrace();
}
}
There is a class SocketClient in the main app:
public class Requester {
Socket requestSocket;
ObjectOutputStream out;
ObjectInputStream in;
String message;
static Future<Void> oExec;
Requester() {
}
void run() {
try {
requestSocket = new Socket("localhost", 54345);
out = new ObjectOutputStream(requestSocket.getOutputStream());
out.flush();
in = new ObjectInputStream(requestSocket.getInputStream());
do {
try {
message = (String)in.readObject();
sendMessage("bye");
} catch(ClassNotFoundException cnfe) {
cnfe.printStackTrace();
}
} while (!message.equals("bye"));
} catch(UnknownHostException uhe) {
uhe.printStackTrace();
} catch(IOException ioe) {
ioe.printStackTrace();
oExec.cancel(true);
CommonUtils.debug("Bootstrap not found. Exit.");
System.exit(0);
} finally {
try {
in.close();
out.close();
requestSocket.close();
} catch(IOException ioef) {
ioef.printStackTrace();
}
}
}
void sendMessage(String msg) {
try {
out.writeObject(msg);
out.flush();
} catch(IOException ioe) {
ioe.printStackTrace();
}
}
public static void main() {
final Requester client = new Requester();
ExecutorService exec = Executors.newCachedThreadPool();
oExec = exec.submit(new Callable<Void>() {
#Override
public Void call() throws Exception {
while (!Thread.currentThread().isInterrupted()) {
client.run();
Thread.sleep(1000);
}
return null;
}
});
exec.shutdown();
}
}
Socket Client is called when main application starts
public class AppStart {
public static void main(final String[] args) {
Requester.main();
EventQueue.invokeLater(new Runnable() {
public void run() {
...
}
});
}
}
This is all to it I do believe. Whole setup worked perfectly fine, even on slower computers. Problem is that after introduction of Socket interface we had major complaints from some users, reporting crashes. Took us some time to figure out the issue, but here is what we found: computers with Intel processors are perfectly fine, only ones with AMD processors crash. Crash normally happens within 3 to 15 minutes from the start of Bootstrap. When crash occurs resources of the computer are not fully used, processor workload is about 20-50% and RAM is quite free as well. When crash occurs user is only able to reset computer using hardware reset or power button, nothing else responds. All users have latest JAVA 1.7.0_51. Whether system is 32 or 64 bit does both crash (or not crash if it is Intel based). Please share your thoughts. May be someone had identical issues and could help me to figure this out.