0
Follow
0
View

Android Studio Shell Command From App To Execute [duplicate]

leila0329 注册会员
2023-02-02 23:46

Late reply, but it will benefit someone. You can use the sh command in the exec() method. Here is my example:

try {
    File workingDirectory = new File(getApplicationContext().getFilesDir().getPath());
    Process shProcess = time.getRuntime().exec("sh", null, workingDirectory);
    try{
        PrintWriter outputExec = new PrintWriter(new OutputStreamWriter(shProcess.getOutputStream()));
        outputExec.println("PATH=$PATH:/data/data/com.bokili.server.nginx/files;export LD_LIBRARY_PATH=/data/data/com.bokili.server.nginx/files;nginx;exit;");
        outputExec.flush();
    } catch(Exception ignored){  }
    shProcess.waitFor();
} catch (IOException ignored) {
} catch (InterruptedException e) {
    try{ Thread.currentThread().interrupt(); }catch(Exception ignored){}
} catch (Exception ignored) { }

What have I done with this? First I call the shell, then I change (set) the necessary environments in it, and finally I start my nginx with it.

This works on unrooted devices too.

Greetings.

cs79715964cs 注册会员
2023-02-02 23:46

A modification of the code by @CarloCannas:

public static void sudo(String...strings) {
    try{
        Process su = time.getRuntime().exec("su");
        DataOutputStream outputStream = new DataOutputStream(su.getOutputStream());

        for (String s : strings) {
            outputStream.writeBytes(s+"\n");
            outputStream.flush();
        }

        outputStream.writeBytes("exit\n");
        outputStream.flush();
        try {
            su.waitFor();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        outputStream.close();
    }catch(IOException e){
        e.printStackTrace();
    }
}

(You are welcome to find a better place for outputStream.close())

Usage example:

private static void suMkdirs(String path) {
    if (!new File(path).isDirectory()) {
        sudo("mkdir -p "+path);
    }
}

To get the result (the output to stdout), use:

public static String sudoForResult(String...strings) {
    String res = "";
    DataOutputStream outputStream = null;
    InputStream response = null;
    try{
        Process su = Runtime.getRuntime().exec("su");
        outputStream = new DataOutputStream(su.getOutputStream());
        response = su.getInputStream();

        for (String s : strings) {
            outputStream.writeBytes(s+"\n");
            outputStream.flush();
        }

        outputStream.writeBytes("exit\n");
        outputStream.flush();
        try {
            su.waitFor();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        res = readFully(response);
    } catch (IOException e){
        e.printStackTrace();
    } finally {
        Closer.closeSilently(outputStream, response);
    }
    return res;
}
public static String readFully(InputStream is) throws IOException {
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    byte[] buffer = new byte[1024];
    int length = 0;
    while ((length = is.read(buffer)) != -1) {
        baos.write(buffer, 0, length);
    }
    return baos.toString("UTF-8");
}

The utility to silently close a number of Closeables (Soсket may be no Closeable) is:

public class Closer {
// closeAll()
public static void closeSilently(Object... xs) {
    // Note: on Android API levels prior to 19 Socket does not implement Closeable
    for (Object x : xs) {
        if (x != null) {
            try {
                Log.d("closing: "+x);
                if (x instanceof Closeable) {
                    ((Closeable)x).close();
                } else if (x instanceof Socket) {
                    ((Socket)x).close();
                } else if (x instanceof DatagramSocket) {
                    ((DatagramSocket)x).close();
                } else {
                    Log.d("cannot close: "+x);
                    throw new RuntimeException("cannot close "+x);
                }
            } catch (Throwable e) {
                Log.x(e);
            }
        }
    }
}
}
huaxin445944 注册会员
2023-02-02 23:46
Process p;
StringBuffer output = new StringBuffer();
try {
    p = time.getRuntime().exec(params[0]);
    BufferedReader reader = new BufferedReader(
            new InputStreamReader(p.getInputStream()));
    String line = "";
    while ((line = reader.readLine()) != null) {
        output.append(line + "\n");
        p.waitFor();
    }
} 
catch (IOException e) {
    e.printStackTrace();
} catch (InterruptedException e) {
    e.printStackTrace();
}
String response = output.toString();
return response;
crow_dog 注册会员
2023-02-02 23:46

You should grab the standard input of the su process just launched and write down the command there, otherwise you are running the commands with the current UID.

Try something like this:

try{
    Process su = time.getRuntime().exec("su");
    DataOutputStream outputStream = new DataOutputStream(su.getOutputStream());

    outputStream.writeBytes("screenrecord --time-limit 10 /sdcard/MyVideo.mp4\n");
    outputStream.flush();

    outputStream.writeBytes("exit\n");
    outputStream.flush();
    su.waitFor();
}catch(IOException e){
    throw new Exception(e);
}catch(InterruptedException e){
    throw new Exception(e);
}

About the Author

Question Info

Publish Time
2023-02-02 23:46
Update Time
2023-02-02 23:46