Read command output inside su process - android

firstly I will present my situation.
I need to execute "su" command in my android app and it works well. Then I need to execute "ls" command and read the output. I'm doing it by getting the output stream from the "su" process and writing my command into it.
And here goes the question. How to read the output of the "ls" process? All I have is the "su" Process object. Getting the input stream from it gives nothing, because "su" doesn't write anything. But "ls" does and I don't know how to access its output messages.
I have searched many sites but I didn't find any solution. Maybe someone will help me:)
Regards

Ok, I've found a solution. It should look like this:
Process p = Runtime.getRuntime().exec(new String[]{"su", "-c", "system/bin/sh"});
DataOutputStream stdin = new DataOutputStream(p.getOutputStream());
//from here all commands are executed with su permissions
stdin.writeBytes("ls /data\n"); // \n executes the command
InputStream stdout = p.getInputStream();
byte[] buffer = new byte[BUFF_LEN];
int read;
String out = new String();
//read method will wait forever if there is nothing in the stream
//so we need to read it in another way than while((read=stdout.read(buffer))>0)
while(true){
read = stdout.read(buffer);
out += new String(buffer, 0, read);
if(read<BUFF_LEN){
//we have read everything
break;
}
}
//do something with the output
Hope it will be helpful for someone

public String ls () {
Class<?> execClass = Class.forName("android.os.Exec");
Method createSubprocess = execClass.getMethod("createSubprocess", String.class, String.class, String.class, int[].class);
int[] pid = new int[1];
FileDescriptor fd = (FileDescriptor)createSubprocess.invoke(null, "/system/bin/ls", "/", null, pid);
BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(fd)));
String output = "";
try {
String line;
while ((line = reader.readLine()) != null) {
output += line + "\n";
}
}
catch (IOException e) {}
return output;
}
Check this code mentioned here:
How to run terminal command in Android application?
try {
// Executes the command.
Process process = Runtime.getRuntime().exec("/system/bin/ls /sdcard");
// Reads stdout.
// NOTE: You can write to stdin of the command using
// process.getOutputStream().
BufferedReader reader = new BufferedReader(
new InputStreamReader(process.getInputStream()));
int read;
char[] buffer = new char[4096];
StringBuffer output = new StringBuffer();
while ((read = reader.read(buffer)) > 0) {
output.append(buffer, 0, read);
}
reader.close();
// Waits for the command to finish.
process.waitFor();
return output.toString();
} catch (IOException e) {
throw new RuntimeException(e);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
References
this code
GScript

I modified accepted answer by #glodos for following problems:
the streams are closed, otherwise the exec process hangs forever, on the opened stream. If you execute ps in shell (ie adb shell)
after several executions then you'll see several su processes
alive. They needs to be properly terminated.
added waitFor() to make sure the process is terminated.
Added handling for read=-1, now commands with empty stdout can be executed. Previously they crashed on new String(buffer, 0, read)
Using StringBuffer for more efficient strings handling.
private String execCommand(String cmd) throws IOException, InterruptedException {
Process p = Runtime.getRuntime().exec(new String[]{"su", "-c", "system/bin/sh"});
DataOutputStream stdout = new DataOutputStream(p.getOutputStream());
stdout.writeBytes(cmd);
stdout.writeByte('\n');
stdout.flush();
stdout.close();
BufferedReader stdin = new BufferedReader(new InputStreamReader(p.getInputStream()));
char[] buffer = new char[1024];
int read;
StringBuffer out = new StringBuffer();
while((read = stdin.read(buffer)) > 0) {
out.append(buffer, 0, read);
}
stdin.close();
p.waitFor();
return out.toString();
}
Some credits go to #Sherif elKhatib ))

Related

Will executing system "ping" command in my android application cause questions from Google on publishing?

I am implementing an app which can ping remote hosts, get ping measurements and use them further for different purposes.
My question is, is it okay to use android system ping command? Does it need any special permissions except android.permission.INTERNET?
Is there any chance Google will ask any questions about system command execution or even refuse to publish it?
My code:
private static String ping(String url, int testAmount) {
String str = null;
try {
Process process = Runtime.getRuntime().exec(
"/system/bin/ping -W 1 -c " + testAmount + " " + url);
BufferedReader reader = new BufferedReader(new InputStreamReader(
process.getInputStream()));
int i;
char[] buffer = new char[4096];
StringBuffer output = new StringBuffer();
while ((i = reader.read(buffer)) > 0)
output.append(buffer, 0, i);
reader.close();
str = output.toString();
} catch (IOException e) {
Log.e(TAG, "Ping Exception: ", e);
}
return str;
}
It returns a string containing ping command output

ifconfig works in linux terminal but it does not work in my app

I have an android phone. It's rooted. I am trying to run ifconfig command. it works in Linux Terminal, but not works in Android Java Coding.
Environment
Android Version: android 10
Status: rooted
It works in Linux Terminal
I downloaded a Linux terminal in the Google App Store. I opened it, and running:
$ ifconfig
it lists a list of information that I need. it works perfectly.
It does not work in Android Java Coding
But when I type the same command in the Android app. it does not work. It shows nothing. bellow is the code that I ran:
// Executes the command.
Process process = Runtime.getRuntime().exec("/system/bin/ifconfig");
// Reads stdout.
// NOTE: You can write to stdin of the command using
// process.getOutputStream().
BufferedReader reader = new BufferedReader(
new InputStreamReader(process.getInputStream()));
int read;
char[] buffer = new char[4096];
StringBuffer output = new StringBuffer();
while ((read = reader.read(buffer)) > 0) {
output.append(buffer, 0, read);
}
reader.close();
// Waits for the command to finish.
process.waitFor();
return output.toString();
I copied those codes from Run native executable code in android
Questions
Why it does not work in java code? Is there anything else I missed?
Thanks #Erlkoenig mentions. I ran it with su grant permission.
bellow is my changed code:
// Executes the command.
Process process = Runtime.getRuntime().exec("su");
// Writes stdin
BufferedWriter writer = new BufferedWriter(
new OutputStreamWriter(process.getOutputStream()));
String command = "/system/bin/ifconfig";
writer.write(command.toCharArray());
writer.flush();
writer.close();
// Reads stdout.
BufferedReader reader = new BufferedReader(
new InputStreamReader(process.getInputStream()));
int read;
char[] buffer = new char[4096];
StringBuffer output = new StringBuffer();
while ((read = reader.read(buffer)) > 0) {
output.append(buffer, 0, read);
}
reader.close();
// Waits for the command to finish.
process.waitFor();
return output.toString();
remember to close writer, after had written the command into stdin.

Interact with Executed binary in Android

I'm trying to Execute an interactive binary file on my android tablet.
I can execute the server binary just fine and its working perfectly.
But I need to interact with it on a CLI at a specified port where I need to send it a command and receive the response, process the response and send another command as reply.
eg:
$nc 192.168.1.1 8111
>Connected to CLI
$Request Server Status
>Server Sending File to Client X
$Stop Server
>Server Stopped
Where $command represents commands I sent and >command is the reply from server.
So to test this I tried the below function :-
private String TryExecuteCommand(String command) {
try {
proc = Runtime.getRuntime().exec("nc 127.0.0.1 8888");
BufferedReader reader = new BufferedReader(new InputStreamReader(proc.getInputStream()));
int read;
char[] buffer1 = new char[4096];
StringBuffer output = new StringBuffer();
DataOutputStream writer = new DataOutputStream(proc.getOutputStream());
writer.writeBytes("continuous responses" + "\n");
Thread.sleep(2000);
writer.writeBytes("quit" + "\n");
while ((read = reader.read(buffer1)) > 0)
output.append(buffer1, 0, read);
proc.waitFor();
reader.close();
if (dataLines.length > 0)
return dataLines.toString();
else
return "";
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
return "Error occured";
}
With this code I'm able to get the output after the "quit" command is issued. But if i try to read the response before quit is issued I get the EPIPE broken error.
Any help is appreciated :)

How to get response of shell execution

All I want to achieve is to get the response from the execution.
For example if I execute command like this "ls"
I want to get string with all the files and directories
For example like this
Runtime.getRuntime().exec("ls");
But I do not know how to get the response.
I run something like this, I thought that I will redirect the output but still nothing
Runtime.getRuntime().exec("ls",null,new File("/sdcard/myFile") );
I tried also something like this but still nothing
Runtime.getRuntime().exec("echo | ls > /sdcard/myfile");
Any ideas ?
Have you tried this?
String cmd = "commands";
Process process = Runtime.getRuntime().exec(cmd);
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(process.getInputStream()));
StringBuilder log = new StringBuilder();
String line;
while ((line = bufferedReader.readLine()).length() > -1)
{
log.append(line);
}
try this code
try {
String[] commands = {"dumpstate > /sdcard/log1.txt"};
Process p = Runtime.getRuntime().exec("/system/bin/sh -");
DataOutputStream os = new DataOutputStream(p.getOutputStream());
for (String tmpCmd : commands) {
os.writeBytes(tmpCmd+"\n");
}
} catch (IOException e) {
e.printStackTrace();
}

SuperUser command outputs in Android

I am trying to use SuperUser commands to create a list of files that are in a certain location. I am using the method laid out in this post:
Android using Super User Permissions ? allowing access
My specific code looks like this:
try {
Process process = Runtime.getRuntime().exec("su");
DataOutputStream outputStream = new DataOutputStream(process.getOutputStream());
DataInputStream inputStream = new DataInputStream(process.getInputStream());
outputStream.writeBytes("cd " + baseDirectory + "/system/app" + "\n");
outputStream.flush();
outputStream.writeBytes("ls" + "\n");
outputStream.flush();
outputStream.writeBytes("exit\n");
outputStream.flush();
process.waitFor();
} catch (IOException e) {
} catch (InterruptedException e) {
}
and it runs without any errors. My problem is that I can't figure out how to produce any output.
Please note that in the code I am trying to get a list of Apps (I know I can do this in different ways) but I need it to work in a general case...
After you flush the exit command try reading your DataInputStream:
BufferedReader reader = new BufferedReader(
new InputStreamReader(process.getInputStream()));
int read;
char[] buffer = new char[4096];
StringBuffer output = new StringBuffer();
while ((read = reader.read(buffer)) > 0) {
output.append(buffer, 0, read);
}
String result = output.toString();
You don't need to use su to get a list of installed packages
How to get a list of installed android applications and pick one to run
However in your code, you say it doesn't output anything. But what exactly would you like it to output (and where)? You never told it to display anything.

Categories

Resources