12

I've been experimenting with Termux, the Android terminal emulator.

It is an excellent application that allows access to the Android operating system without requiring root access.

What I would like to be able to achieve is execute scripts/commands within Termux from within another Android application installed on the same device.

I believe Termux used to allow Tasker tasks to be executed via intents, however this doesnt appear to be the case now.

Is it possible to execute a script of set of commands via Termux (or any other such app) from another Android application.

or...

Is it possible to access the underlying Android operation system and execute scripts from within an Android app?

UPDATE

When I execute this code from my Android application

    try {
        ProcessBuilder pb = new ProcessBuilder("pkg", "install -y", "ffmpeg python");
        final Process p = pb.start();
        BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream()));
        String line;
        while ((line = br.readLine()) != null) {
            Log.d(TAG, "onCreate(2): " + line);
        }
    } catch (Exception ex) {
        Log.e(TAG, "onCreate: ", ex);
    }

I get this error message

java.io.IOException: Cannot run program "pkg": error=13, Permission denied
        at java.lang.ProcessBuilder.start(ProcessBuilder.java:1050)
        at org.home.assignment.shell.MainActivity.commandThree(MainActivity.java:32)
        at org.home.assignment.shell.MainActivity.onCreate(MainActivity.java:21)
        at android.app.Activity.performCreate(Activity.java:7802)
        at android.app.Activity.performCreate(Activity.java:7791)
        at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1299)
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3243)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3407)
        at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:83)
        at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
        at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2016)
        at android.os.Handler.dispatchMessage(Handler.java:107)
        at android.os.Looper.loop(Looper.java:214)
        at android.app.ActivityThread.main(ActivityThread.java:7343)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:933)
     Caused by: java.io.IOException: error=13, Permission denied
        at java.lang.UNIXProcess.forkAndExec(Native Method)
        at java.lang.UNIXProcess.<init>(UNIXProcess.java:133)
        at java.lang.ProcessImpl.start(ProcessImpl.java:141)
        at java.lang.ProcessBuilder.start(ProcessBuilder.java:1029)
        at org.home.assignment.shell.MainActivity.commandThree(MainActivity.java:32) 
        at org.home.assignment.shell.MainActivity.onCreate(MainActivity.java:21) 
        at android.app.Activity.performCreate(Activity.java:7802) 
        at android.app.Activity.performCreate(Activity.java:7791) 
        at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1299) 
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3243) 
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3407) 
        at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:83) 
        at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135) 
        at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95) 
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2016) 
        at android.os.Handler.dispatchMessage(Handler.java:107) 
        at android.os.Looper.loop(Looper.java:214) 
        at android.app.ActivityThread.main(ActivityThread.java:7343) 
        at java.lang.reflect.Method.invoke(Native Method) 
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492) 
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:933) 

However com.termux can execute commands like this. How do I get permission to execute these commands in my applicatgion?

1
  • Just plain String[] cmdArray = {"sh", "-c", cmd}; Process p = Runtime.getRuntime().exec(cmdArray); worked for me on an unrooted low-end phone, but may not work on unrooted new phones. Commented Jul 14, 2019 at 3:17

2 Answers 2

9
+50

So far as I have tried, it works. I think it is supposed to, because that is how many Linux GUI apps do some of their work, by issuing shell commands.

To make sure, I tried issuing a vanilla command's output over to Logcat on an old, low-end, unrooted Android 6.0 phone, and it worked (working code below).

public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        String[] cmd = new String[]{"ls", "-la", "/"};

        try {
            // These two lines are what we care about
            Process process = Runtime.getRuntime().exec(cmd);
            InputStream iStream = process.getInputStream();

            // This is how we check whether it works
            tryWriteProcessOutput(iStream);
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    private void tryWriteProcessOutput(InputStream iStream) throws IOException {
            BufferedReader reader = new BufferedReader(new InputStreamReader(iStream));

            String output = "";
            String line;

            try {
                while ((line = reader.readLine()) != null) {
                    output += line + "\n";
                }
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                reader.close();
            }

        Log.d("cmdOutput", output);
    }
}

However, your mileage might vary wildly here. With so many Android manufacturers, I would expect different versions of the command shell on different devices, and thus I wouldn't expect every Android device to be able to run just any command I threw at it, unless it's a really common one.

Besides, you might also run into problems with system permissions with the commands themselves rather than the command shell (ie. busybox: Permission denied).

Sign up to request clarification or add additional context in comments.

Comments

3

Termux is a terminal emulator but doesn't have access to everything in the Android OS. Eventually its an app and will face restrictions as any other app does in the Android. APT, pkg and other package installers or packages are installed within the emulator but not as system wide. Also certain commands will have restrictions similar to your case for example pm can only be executed with root or an adb shell since their user IDs are allowed to perform such actions while other apps are not. Meaning running the command pm install -r -t someapp.apk will give an error in Termux while it would certainly work if using adb shell or having root permissions.

To make things even more clear, running the command echo $PATH in Termux will show directories whose Termux commands are only included, and they are not Android OS commands but compiled packages that can run on Android OS. It is a nice way of like running things on top Android without having to deal with a lot of restrictions, more like a sand-boxed environment. Installing certain packages that need to go out of the sandbox will face issues so be mindful of that.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.