1

我正在尝试在 Android 中做这个简单的 unix ls:

cd /data

然后

ls

它应该返回 /data 文件夹的所有内容。

我有这个编码:

try {
       String line;
       Process p = Runtime.getRuntime().exec(new String[] { "ls /data"});
       BufferedReader in = new BufferedReader(
               new InputStreamReader(p.getInputStream()) );
       while ((line = in.readLine()) != null) {
         Log.d("debugging", line);
       }
       in.close();
     }
     catch (Exception e) {
       e.printStackTrace();
     }

我目前面临的问题是我一次只能执行一个命令。例如,如果我写ls /data它什么都不返回。看来他不喜欢空格。

如果我只写一个像“ls”这样返回根目录列表的单词,一切都会正常工作:

03-19 22:51:59.241: D/debugging(16274): acct
03-19 22:51:59.241: D/debugging(16274): cache
03-19 22:51:59.241: D/debugging(16274): config
03-19 22:51:59.241: D/debugging(16274): crashtag
03-19 22:51:59.241: D/debugging(16274): d
03-19 22:51:59.241: D/debugging(16274): data
03-19 22:51:59.241: D/debugging(16274): default.prop
03-19 22:51:59.241: D/debugging(16274): dev
03-19 22:51:59.241: D/debugging(16274): etc
03-19 22:51:59.241: D/debugging(16274): fstab
03-19 22:51:59.241: D/debugging(16274): init
03-19 22:51:59.241: D/debugging(16274): init.clrdex.sh
03-19 22:51:59.241: D/debugging(16274): init.goldfish.rc
03-19 22:51:59.241: D/debugging(16274): init.hostapd.sh
03-19 22:51:59.241: D/debugging(16274): init.rc
03-19 22:51:59.241: D/debugging(16274): init.semc.rc
03-19 22:51:59.241: D/debugging(16274): init.usbmode.sh
03-19 22:51:59.241: D/debugging(16274): logo.rle
03-19 22:51:59.241: D/debugging(16274): mnt
03-19 22:51:59.241: D/debugging(16274): mr.log
03-19 22:51:59.241: D/debugging(16274): proc
03-19 22:51:59.241: D/debugging(16274): root
03-19 22:51:59.241: D/debugging(16274): sbin
03-19 22:51:59.241: D/debugging(16274): sdcard
03-19 22:51:59.241: D/debugging(16274): sys
03-19 22:51:59.241: D/debugging(16274): system
03-19 22:51:59.241: D/debugging(16274): ueventd.goldfish.rc
03-19 22:51:59.241: D/debugging(16274): ueventd.rc
03-19 22:51:59.241: D/debugging(16274): ueventd.semc.rc
03-19 22:51:59.241: D/debugging(16274): vendor

正如有人提到的那样,我已经尝试用多个命令填充该数组,但它什么也没返回。空白的。

{"ls","ls"} //this should return twice ls result.

任何想法如何在 Android 运行时“连接”一个命令?

4

3 回答 3

2

我认为您需要 root 访问权限才能执行ls /data命令,因此您应该首先获取 su shell 然后执行命令,例如:

// run command with su rights and return output of that command(inside su
// shell)
// command = "ls /data"
public static void suOutputExecute(String command) {
    try {
        int BUFF_LEN = 1024;
        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(command + "\n"); // \n executes the command
        InputStream stdout = p.getInputStream();
        byte[] buffer = new byte[BUFF_LEN];
        int read;
        String out = new String();
        // while((read=stdout.read(buffer))>0) won't work here
        while (true) {
            read = stdout.read(buffer);
            out += new String(buffer, 0, read);
            if (read < BUFF_LEN) {
                // we have read everything
                break;
            }
        }
        stdout.close();
        Log.e("ROOT", out);
        p.waitFor();
    } catch (Exception e) {
        Log.e("ROOT", "Error", e);
    }
}

您需要有根设备。对于模拟器,您仍然必须安装超级用户。

对于不需要 su 以下代码的命令应该可以工作(我现在无法测试它):

public static void shExecute(String[] commands) {
    Process shell = null;
    DataOutputStream out = null;
    BufferedReader in = null;

    try {
        // Acquire sh
        Log.i(LOG_TAG, "Starting exec of sh");
        shell = Runtime.getRuntime().exec("sh");//su if needed
        out = new DataOutputStream(shell.getOutputStream());

        in = new BufferedReader(new InputStreamReader(shell.getInputStream()));

        // Executing commands without root rights
        Log.i(LOG_TAG, "Executing commands...");
        for (String command : commands) {
            Log.i(LOG_TAG, "Executing: " + command);
            out.writeBytes(command + "\n");
            out.flush();
        }

        out.writeBytes("exit\n");
        out.flush();
        String line;
        StringBuilder sb = new StringBuilder();
        while ((line = in.readLine()) != null) {
            sb.append(line).append("\n");
        }
        Log.i(LOG_TAG, sb.toString());
        shell.waitFor();

    } catch (Exception e) {
        Log.e(LOG_TAG, "ShellRoot#shExecute() finished with error", e);
    } finally {
        try {
            if (out != null) {
                out.close();
            }
            if(in != null){
                in.close();
            }
            // shell.destroy();
        } catch (Exception e) {
            // hopeless
        }
    }
}
于 2013-03-19T22:30:14.877 回答
0

我认为你的问题是

Process p = Runtime.getRuntime().exec(new String[] { "ls /data"});

您应该使用 exec(String command) 或将“ls /data”分成两个字符串

Runtime.getRuntime().exec(new String[] { "ls", "/data"});
于 2013-03-19T22:05:53.890 回答
0

您是否为 java 运行时探索过这个 exec 命令,使用要“cd”到的路径创建一个文件对象,然后将其作为 exec 方法的第三个参数输入。

public Process exec(String command,
                String[] envp,
                File dir)
         throws IOException

在具有指定环境和工作目录的单独进程中执行指定的字符串命令。

这是一种方便的方法。exec(command, envp, dir) 形式的调用与调用 exec(cmdarray, envp, dir) 的行为方式完全相同,其中 cmdarray 是命令中所有标记的数组。

更准确地说,使用由调用 new StringTokenizer(command) 创建的 StringTokenizer 将命令字符串分解为标记,而无需进一步修改字符类别。标记器生成的标记然后以相同的顺序放置在新的字符串数组 cmdarray 中。

Parameters:
    command - a specified system command.
    envp - array of strings, each element of which has environment variable settings in the format name=value, or null if the subprocess should inherit the environment of the current process.
    dir - the working directory of the subprocess, or null if the subprocess should inherit the working directory of the current process. 
Returns:
    A new Process object for managing the subprocess 
Throws:
    SecurityException - If a security manager exists and its checkExec method doesn't allow creation of the subprocess 
    IOException - If an I/O error occurs 
    NullPointerException - If command is null, or one of the elements of envp is null 
    IllegalArgumentException - If command is empty
于 2014-07-18T07:25:31.237 回答