Android su commands do not work programmatically

I need my application to execute some su commands programmatically (the phone is rooted).

After using adb, the commands work.

For example: su -c "mkdir /sdcard/testdir" creates the / testdir directory in / sdcard.

When i call:

  p = Runtime.getRuntime().exec("su -c \"mkdir /sdcard/testdir\""); p.waitFor(); 

It simply moves and no changes occur.

I tried reading the input:

 DataInputStream dis = new DataInputStream(p.getInputStream()); while((temp = dis.readLine())!=null) Log.d(ctx.TAG,"shell:"+temp); 

But it does not report anything (the loop performs 0 iterations).

Has anyone ever encountered this problem before? How can this be solved? Of course, non-su commands work with this method programmatically.

Note. As an example, I gave mkdir (I know that this does not necessarily require su). I need a lot of different commands to be executed under su

Thanks!

EDIT: when I call su -c "id" programmatically, we deduce that uid = 0.

+3
source share
4 answers

I can get stuck on the problem for several days, and at the moment when I'm going to boldly ask about it in StackOverflow, it is solved in a few minutes.

Correction:

  p=Runtime.getRuntime().exec("su"); DataOutputStream dos = new DataOutputStream(p.getOutputStream()); dos.writeBytes("mkdir /sdcard/testdir\n"); dos.writeBytes("exit\n"); dos.flush(); dos.close(); p.waitFor(); 

Do not forget \n at the end of each command that you write to DataOutputStream , as it will not work without it.

+11
source

You wrote that you "need different commands that must be run under su." Note that using "Runtime.exec ()" is not recommended by Chainfire, the developer of the most famous root application SuperSU.

It is tempting to use Runtime.getRuntime (). exec ("su -c [command]"); but you should be aware that [command] should be the only parameter and therefore a quote may be required. Unfortunately, both quoting the [command] parameter and passing parameters as separate variables to Runtime.exec () or ProcessBuilder do not work sequentially in all versions of Android, and therefore this construction should be completely excluded. It is impossible to do it right - but there is a high risk of problems.

See How to execute SU Document. Therefore, you can follow his recommendations here:

3.2. Making a call

A common method for calling su, which avoids the known problems listed above, is to create interactive shell and pipe commands for it. This is accomplished by calling Runtime.getRuntime (). Exec ("su") ;, and receiving input and output streams from the returned process object. This is a fairly simple piece of code, but it includes debug logs and checks it several times to reproduce here.

The kernel code is here: [libsuperuser :: Shell.java @GitHub] . Shell.run () is a generic call to run shell code, the following more specific (static) utility functions are those that you probably end up using:

 List<String> Shell.SH.run(String command) List<String> Shell.SH.run(List<String> commands) List<String> Shell.SH.run(String[] commands) List<String> Shell.SU.run(String command) List<String> Shell.SU.run(List<String> commands) List<String> Shell.SU.run(String[] commands) 

SH variants are used for a non-root shell, where SU variants are used for a root shell. These calls return a list containing shell command output. If there is no output, the list is empty but not equal to zero. The result is only null if an error occurs - including a user who does not provide access to your application. This is call blocking.

Note that in debug compilers, the entire STDIN / STDOUT / STDERR command will be logged in logcat, and these calls (intentionally) cause your application to crash if called from the main thread. The reason for this will be discussed in section 4. When to call su.

+5
source

If you use double quotes, it will work:

 su -c ""command with args"" 
+1
source

Perhaps you are calling Runtime.getRuntime().exec() in the main thread, and p.waitFor() makes your main thread wait until it executes. Try calling another thread, such as the following snippet.

 new Thread(){ @override public void run(){ p = Runtime.getRuntime().exec("su -c \"mkdir /sdcard/testdir\""); p.waitFor(); }.start(); } 
-one
source

All Articles