问题
I've been trying to build a Terminal Emulator for Android. Being pretty new to this, my idea was to execute each command and store the output in a file, whose contents would be displayed after each execution. Pseudo Code :
public Boolean execCommands(String command) {
try {
rt = Runtime.getRuntime();
process = rt.exec("su");
DataOutputStream os = new DataOutputStream(process.getOutputStream());
os.writeBytes("echo $ \""+command+ "\" >> /sdcard/Android/data/terminalemulatorlog.txt\n\n\n");
/**** Note : String command = (EditText)findViewById(R.id.command).getText().toString(); ****/
os.flush();
os.writeBytes("exit\n");
os.flush();
process.waitFor();
}
// Error Handling
displayOutput(); //Loads and displays the Text File (/sdcard/Android/data/terminalemulatorlog.txt)
return true;
}
This piece of code works except for a few special commands (Eg. 'clear'). But what I'm more concerned about are the following problems :
- Each time a command is to be executed, I end up seeking SuperUser permissions (second line of code). And I'd like to do away with this.
In cases when the user enters one command followed by another,
Such as :cd /sdcard touch File.txt
The File.txt is created in '/' and not in '/sdcard'. As of now to avoid this, I'm keeping a track of all the 'cd' commands to figure out what the present working directory is. And I'm hoping that there is a better way around this.
I'd be grateful if someone could help me out here.
回答1:
Not sure if you are still needing this or not, but here is how I am issuing multiple commands at one time and not using "su" to have them run.
try {
String[] commands = {
"dumpstate > /sdcard/LogFiles/dumpstate.txt",
"dumpsys > /sdcard/LogFiles/dumpsys.txt",
"logcat -d > /sdcard/LogFiles/log.txt",
"cat /sdcard/LogFiles/dumpstate.txt /sdcard/LogFiles/dumpsys.txt /sdcard/LogFiles/log.txt > /sdcard/LogFiles/bugreport.rtf" };
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();
}
回答2:
This a bit late but here a few ways of doing this.
1)
Instead of using su as a starting point use /system/bin/sh.
and after calling
rt.exec("/system/bin/sh");
You should hold onto the Output Stream and Input Stream to give further commands.
After you issued a command you should echo a magic line like "---EOF---" and stop reading input after reading that line. If you don't have this you'll end up with the read function from the InputStream blocking.
2) Pipe the data to a native process you've written that simply moves the data on to your Android Application with a terminating character or string attached to the end.
I am not entirely sure how to do this, but it is essentially the same as the previous method just relies on you native application as a middle man.
This will get you close to a functioning "Terminal Emulator".
3)If you wan't a true Ternimal Emulator then there's no other way to do it than : using a native application that opens a connection to a psuedoterminal.
Here's some basic information of how to open a pty : link
Terminal Emulator is a open source project that uses this technique.
Have a look here
来源:https://stackoverflow.com/questions/8673016/building-a-terminal-emulator-for-android