0

I have an app which should execute some root commands. SuperSU version is 1.04. Su version is 1.02. Android 4.1.1. Device is Samsung Galaxy S3 - rooted.

The problem is I cannot get a permission prompt from SuperSU. I've tried many things, but prompt never shows up.

For RootChecker basic, ADB and other apps it shows up. Here is my procedure - maybe I'm doing something wrong.

private static String runShellCommand(String command) {
    DataOutputStream os = null;
    Process process = null;
    try {
        String [] env = {"PATH=/sbin:/vendor/bin:/system/sbin:/system/bin:/system/xbin"}; 
        process = Runtime.getRuntime().exec("su", env, Environment.getExternalStorageDirectory() );
        os = new DataOutputStream(process.getOutputStream());

        InputStreamHandler err = new InputStreamHandler(process.getErrorStream(), false);
        InputStreamHandler out = new InputStreamHandler(process.getInputStream(), false);

        os.writeBytes(command + "\n");
        os.flush();

        os.writeBytes(EXIT);
        os.flush();
        os.close();
        Log.d(LOGTAG, "Waiting on: " + process.waitFor());

        String errOut = err.getOutput();
        String stdOut = out.getOutput(); 

        Log.d(LOGTAG, "Exit code: " + process.exitValue());
        Log.d(LOGTAG, command + " erroutput: [" + errOut + "]");
        Log.d(LOGTAG, command + " output: [" + stdOut + "]");
        if (errOut != null && !errOut.equals(""))
            return errOut;
        else if (stdOut != null&& !stdOut.equals(""))
            return stdOut;
        else 
            return null;
    } catch (Exception e) {
        Log.e(LOGTAG, "runShellCommand error: ", e);
        return null;
    } finally {
        try {
            if (os != null) {
                os.close();
            }
            if (process != null) {
                Log.d(LOGTAG, "Exit val: " + process.exitValue());
                process.destroy();
            }
        } catch (Exception ignored) {}
    }
}

InputStream handler is:

private static class InputStreamHandler extends Thread {
    private final InputStream stream;
    private final boolean devNull;
    StringBuffer output;

    public String getOutput() {
        return output.toString();
    }

    InputStreamHandler(InputStream stream, boolean devNull) {
        this.devNull = devNull;
        this.stream = stream;
        output = new StringBuffer();
        start();
    }

    @Override
    public void run() {
        try {
            if (devNull) {
                while (stream.read() != -1) {}
            } else {
                BufferedReader br = new BufferedReader(new InputStreamReader(stream));
                while (true) {
                    String line = br.readLine();
                    if (line == null) {
                        Log.d(LOGTAG, "Ended with reading!");
                        br.close();
                        return;
                    }
                    output.append(line);
                }
            }
        } catch (IOException ignored) {
            Log.e(LOGTAG, "Error", ignored);
        }
    }
}

Anyone have an idea why does it block so it doesn't show permission window? Thanks.

2 Answers2

0

I'm not exactly sure why this wouldn't work. The first thing that strikes me as odd is passing Environment.getExternalStorageDirectory() to exec. Maybe this (path) is not allowed (to execute from) ?

Why not simply use libsuperuser, written specifically to perform this very task ? It is open source, tiny, fully commented, has an example project, and even a document detailing the common problems you may encounter when trying to do this very operation.

Rapptz
  • 20,807
  • 5
  • 72
  • 86
Jorrit
  • 574
  • 6
  • 4
  • 1
    Even if I use Process.getRuntime().exec("su") it blocks without asking for permission – drake ugly Feb 08 '13 at 21:32
  • I'll give it a go with libsuperuser. Thanks. – drake ugly Feb 08 '13 at 21:34
  • It doesn't help at all. Your code is similar to my code. Problem is still not solved. – drake ugly Feb 10 '13 at 10:41
  • As you state in the other answer (which for some reason I cannot comment on), yes, you need to do all this from a separate thread, as all the documents describe. That should still normally not prevent the popup from showing, unless you are blocking receivers by calling su inside an onReceive, which (also as documented) you should never do. – Jorrit Feb 19 '13 at 07:43
0

I finally figured it out. The trick is to create a process (execute Runtime.getRuntime().exec("su");) separately in another thread. I'm not sure why this works, but it does. Similar way is used in RootTools. This has solved my problem.