Можно ли выполнять сценарии Shell из приложения Android

Я экспериментировал с Termux, эмулятором терминала Android.

Это отличное приложение, которое позволяет получить доступ к операционной системе Android без необходимости root-доступа.

Чего я хотел бы добиться, так это выполнять сценарии/команды в Termux из другого приложения Android, установленного на том же устройстве.

Я считаю, что Termux раньше позволял выполнять задачи Tasker через намерения, однако сейчас это не так.

Можно ли выполнить скрипт набора команд через Termux (или любое другое подобное приложение) из другого приложения для Android.

или...

Можно ли получить доступ к базовой операционной системе Android и выполнять сценарии из приложения Android?

ОБНОВИТЬ

Когда я выполняю этот код из своего приложения для Android

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

Я получаю это сообщение об ошибке

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) 

Однако com.termux может выполнять такие команды. Как мне получить разрешение на выполнение этих команд в моем приложении?

Просто String[] cmdArray = {"sh", "-c", cmd}; Process p = Runtime.getRuntime().exec(cmdArray); работал у меня на нерутированном бюджетном телефоне, но может не работать на нерутированных новых телефонах.

root 14.07.2019 05:17
9
1
8 176
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Насколько я пробовал, это работает. Я думаю, что так и должно быть, потому что именно так многие приложения с графическим интерфейсом Linux выполняют часть своей работы, выдавая команды оболочки.

Чтобы убедиться, я попытался передать вывод ванильной команды на Logcat на старом низкоуровневом телефоне Android 6.0 без рута, и это сработало (рабочий код ниже).

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

Тем не менее, ваш пробег может сильно различаться здесь. С таким количеством производителей Android я бы ожидал разных версий командной оболочки на разных устройствах, и, таким образом, я бы не ожидал, что каждое устройство Android сможет запускать любую команду, которую я ему подам, если только она не является действительно распространенной.

Кроме того, вы также можете столкнуться с проблемами с системными разрешениями для самих команд, а не для командной оболочки (например, busybox: Permission denied).

Termux — это эмулятор терминала, но он не имеет доступа ко всему в ОС Android. В конце концов, это приложение, и оно столкнется с ограничениями, как и любое другое приложение в Android. APT, pkg и другие установщики пакетов или пакеты устанавливаются внутри эмулятора, но не для всей системы. Также некоторые команды будут иметь ограничения, аналогичные вашему случаю, например, pm могут быть выполнены только с правами root или adb shell, поскольку их идентификаторы пользователей могут выполнять такие действия, а другим приложениям — нет. Это означает, что запуск команды pm install -r -t someapp.apk выдаст ошибку в Termux, хотя она, безусловно, будет работать при использовании adb shell или наличии прав root.

Чтобы еще больше прояснить ситуацию, запуск команды echo $PATH в Termux покажет каталоги, чьи команды Termux только включены, и это не команды ОС Android, а скомпилированные пакеты, которые могут работать в ОС Android. Это хороший способ запуска вещей на топовом Android без необходимости иметь дело с множеством ограничений, больше похожий на изолированную среду. Установка определенных пакетов, которые необходимо удалить из песочницы, может столкнуться с проблемами, поэтому помните об этом.

Другие вопросы по теме