execute shell command from android

JavaAndroidXmlShellAndroid 4.4-Kitkat

Java Problem Overview


I'm trying to execute this command from the application emulator terminal (you can find it in google play) in this app i write su and press enter, so write:

screenrecord --time-limit 10 /sdcard/MyVideo.mp4

and press again enter and start the recording of the screen using the new function of android kitkat.

so, i try to execute the same code from java using this:

Process su = Runtime.getRuntime().exec("su");
Process execute = Runtime.getRuntime().exec("screenrecord --time-limit 10 /sdcard/MyVideo.mp4");

But don't work because the file is not created. obviously i'm running on a rooted device with android kitkat installed. where is the problem? how can i solve? because from terminal emulator works and in Java not?

Java Solutions


Solution 1 - Java

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 = Runtime.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);
}

Solution 2 - Java

A modification of the code by @CarloCannas:

public static void sudo(String...strings) {
	try{
	    Process su = Runtime.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);
	}
}

Update: 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);
			}
		}
	}
}
}

Solution 3 - Java

Process p;
StringBuffer output = new StringBuffer();
try {
    p = Runtime.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;

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionGiovanni MariottiView Question on Stackoverflow
Solution 1 - JavaCarlo CannasView Answer on Stackoverflow
Solution 2 - Java18446744073709551615View Answer on Stackoverflow
Solution 3 - JavaBalwinder SInghView Answer on Stackoverflow