The first thing you should do is to log the stderr stream that is available for your process as well. This will give you information about what is wrong with your command.
Your command is not correctly processed as it is seen as one command. The reason is explained in this answer.
The solution is to use a String[] as an argument of exec and explicitly execute the command with the shell. I wrote some code that executes your command, but it is in Java on an unrooted device. Still, it generates output and grep works.
String[] arrayCommand = {"sh", "-c","dumpsys telephony.registry | grep \"permission\""};
Runtime r = Runtime.getRuntime();
Process process = r.exec(arrayCommand);
String stdoutString = convertInputStreamToString(process.getInputStream());
String stderrString = convertInputStreamToString(process.getErrorStream());
Answer from JANO on Stack OverflowFirst, you should wrap calls to exec in a try-catch-clause to catch IOExceptions.
Second, use exec(java.lang.String[]) to execute a command with parameters. For example, similar to
Runtime.getRuntime().exec(new String[]{ "shell", "/system/bin/chmod", "0777", sdCard.getAbsolutePath() + "/" + nativeFile });
The sdcard in an Android system is usually disabled for execution. Therefore even if you correctly execute the chmod command it will fail.
You can test that easily. Start the shell via USB (adb shell) and execute the chmod command. It will fail with an error message like "Bad mode".
Therefore you have to copy the file to a different location where you have write access and then set the executable bit on that copy. You can try to copy the file for example to "/data/local/tmp/" but I am not sure if that path is still usable.
Android java.lang.Process implementation is java.lang.ProcessManager$ProcessImpl and it has field private final int pid;. It can be get from Reflection:
public static int getPid(Process p) {
int pid = -1;
try {
Field f = p.getClass().getDeclaredField("pid");
f.setAccessible(true);
pid = f.getInt(p);
f.setAccessible(false);
} catch (Throwable e) {
pid = -1;
}
return pid;
}
Another way - use toString:
public String toString() {
return "Process[pid=" + pid + "]";
}
You can parse output and get pid without Reflection.
So full method:
public static int getPid(Process p) {
int pid = -1;
try {
Field f = p.getClass().getDeclaredField("pid");
f.setAccessible(true);
pid = f.getInt(p);
f.setAccessible(false);
} catch (Throwable ignored) {
try {
Matcher m = Pattern.compile("pid=(\\d+)").matcher(p.toString());
pid = m.find() ? Integer.parseInt(m.group(1)) : -1;
} catch (Throwable ignored2) {
pid = -1;
}
}
return pid;
}
Will you be using the PID to kill the process? If so, you can simply call destroy() on your Process instance. No need for the PID. Please note that you will need to launch the process using ProcessBuilder, rather than getRuntime().exec(), for this to work.
If you really do need the process ID, you may need to use a shell script. There is no way to get the PID from Java, AFAIK.
EDIT:
Since you need to keep a handle on the Process after leaving your app and returning to it, one solution is to make a static member in the class that spawns the Process:
private static Process myProcess;
Use this member to store the Process that you get back from calling start() on your ProcessBuilder. The static member will stay around as long as your app is in memory — it doesn't have to be visible. It should be possible to kill the process after returning to your app. If the system happens to kill your app to free up resources, then you will have no way to terminate the child process (if it stays running), but this solution should work for most cases.
Redirection (>) is not the OS feature. This is a feature of shell. To make it working from java you have to run something like the following:
/bin/sh yourcommand > yourfile
i.e. in your case:
/bin/sh cat /sdcard/file1.mpg /sdcard/file2.mpg > /sdcard/out.mpg
BUT could you please explain me why are you doeing this? Do you understand that this command is exact equivalent of cp /sdcard/file1.mpg /sdcard/file2.mpg /sdcard/out.mpg that can be coded in pure java without running any command line? Unless you have special reasons go on it! Write pure java code when it is possible. It is easier to debug, support and maintain.
There's absolutely no reason to use 'cat' to do this. It's not a supported or encouraged mechanism on Android, and there's no reason to launch a new executable to do what you can easily do in java code, by reading in one file and writing it out to the other.
For the record, you are trying to do a shell redirection, and that will not work since you are not executing a shell.
The "su -c COMMAND" syntax is not really supported. For better portability, use something like this:
p = Runtime.getRuntime().exec("su");
stream = p.getOutputStream();
stream.write("busybox ifconfig wlan0 add xxxxxxxxxxxx");
The write() command doesn't exists as-is, but I'm sure you'll find how to write your stream to it, maybe encapsulating the output stream in a BufferedOutputWriter or so.
because the process that started with "busybox" is not the same one which started with "su". you should like this:
Process process = Runtime.getRuntime().exec("su");
OutputStream os = process.getOutputStream();
DataOutputStream dos = new DataOutputStream(os);
dos.writeBytes("busybox ifconfig wlan0 add xxxxxxxxxxxx" + "\n");
dos.flush();
You can execute ls with provided path for which folders should be listed
Runtime.getRuntime().exec(new String[] { "ls", "\\tmp"});
The current working directory is associated with the current process. When you exec("cd tmp") you are creating a process, changing its directory to "tmp", and then the process exits. The parent process' working directory doesn't change.
See this for a more general discussion of changing the current working directory in Java.