简体   繁体   English

为 Android 构建终端模拟器

[英]Building a Terminal Emulator for Android

I've been trying to build a Terminal Emulator for Android.我一直在尝试为 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 :但我更关心的是以下问题:

  1. 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.我想取消这个。
  2. 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'. File.txt是在“/”中创建的,而不是在“/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.到目前为止,为了避免这种情况,我正在跟踪所有 'cd' 命令以找出当前的工作目录是什么。 And I'm hoping that there is a better way around this.我希望有更好的方法来解决这个问题。

I'd be grateful if someone could help me out here.如果有人能在这里帮助我,我将不胜感激。

This a bit late but here a few ways of doing this.这有点晚了,但这里有几种方法可以做到这一点。

1) 1)

Instead of using su as a starting point use /system/bin/sh.不要使用 su 作为起点,而是使用 /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.发出命令后,您应该回显像“---EOF---”这样的魔术行,并在阅读该行后停止读取输入。 If you don't have this you'll end up with the read function from the InputStream blocking.如果你没有这个,你最终会得到来自 InputStream 阻塞的 read 函数。

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. 2) 将数据通过管道传输到您编写的本机进程,该进程只需将数据移动到您的 Android 应用程序,并在末尾附加终止字符或字符串。

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. 3)如果您不需要真正的终端模拟器,那么除了使用本机应用程序打开与伪终端的连接之外,别无他法。

Here's some basic information of how to open a pty : link以下是有关如何打开 pty 的一些基本信息: 链接

Terminal Emulator is a open source project that uses this technique. Terminal Emulator 是一个使用这种技术的开源项目。

Have a look here看看这里

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.不确定您是否仍然需要这个,但这是我一次发出多个命令而不使用“su”来运行它们的方法。

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();
}

Regarding problem 1:关于问题1:

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.我想取消这个。

Thanks to Xonar's suggestion from another answer:感谢 Xonar 从另一个答案中提出的建议:

After you issued a command you should echo a magic line like "---EOF---" and stop reading input after reading that line.发出命令后,您应该回显像“---EOF---”这样的魔术行,并在阅读该行后停止读取输入。

Solution in Kotlin: Kotlin 中的解决方案:

private lateinit var suProcess: Process
private lateinit var outputStream: DataOutputStream

private fun getSu(): Boolean {
    return try {
        suProcess = Runtime.getRuntime().exec("su")
        outputStream = DataOutputStream(suProcess.outputStream)
        true
    } catch (e: Exception) {
        e.printStackTrace()
        false
    }
}

private fun sudo(command: String): List<String>? {
    return try {
        outputStream.writeBytes("$command\n")
        outputStream.flush()

        outputStream.writeBytes("echo ---EOF---\n")
        outputStream.flush()

        val reader = suProcess.inputStream.bufferedReader()
        val result = mutableListOf<String>()
        while (true) {
            val line = reader.readLine()
            if (line == "---EOF---") break
            result += line
        }

        result
    } catch (e: Exception) {
        e.printStackTrace()
        null
    }
}

private fun exitTerminal() {
    try {
        outputStream.writeBytes("exit\n")
        outputStream.flush()

        suProcess.waitFor()
    } catch (e: Exception) {
        e.printStackTrace()
    } finally {
        outputStream.close()
    }
}

//Activity method
override fun onDestroy() {
    super.onDestroy()

    exitTerminal()
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM