Added|Changed: Add support to switch to existing session instead of creating duplicate session for RUN_COMMAND intent

This is done via addition of the `com.termux.RUN_COMMAND_SESSION_CREATE_MODE` extra, which currently supports two values.

- `always` to always create a new session every time.
- `no-session-with-name` to create a new session only if no existing session exits with the same terminal session name.

The terminal session name will equal executable basename by default and dashes `-` in the basename will no longer be replaced with spaces when session name as done previously. The `com.termux.RUN_COMMAND_SESSION_NAME` extra can be used to set custom session name.

Usage:

You can use this with `Termux:Tasker` or `Termux:Widget`.

For example for `Termux:Widget`

- Create a wrapper script at `~/.shortcuts/tasks/my-script.sh` with following contents under `tasks` directory so that it runs in background app shell instead of a terminal session. Do not use terminal session runner for wrapper script, since it will open two sessions everytime otherwise, first for wrapper script, then for actual target executable. There would also be conflicts if both wrapper script and target executable have the same basename and it would be incorrectly assumed that session is already running.
- Replace the `bash` executable with actual target executable that you want to run in the terminal session if its not already running.
- Optionally set custom session name. By default it will set to executable basename and not the wrapper script name. To set it to wrapper script name, you can pass `$(basename "$0")`.
- Launch the wrapper script with widget. On first launch, a new terminal session should open but on subsequent launches, same terminal session should open.

Note that you can also pass `com.termux.RUN_COMMAND_SESSION_ACTION` to modify session action behaviour. Check https://github.com/termux/termux-app/wiki/RUN_COMMAND-Intent#run_command-intent-command-extras.

```

am startservice --user 0 -n com.termux/com.termux.app.RunCommandService \
-a com.termux.RUN_COMMAND \
--es com.termux.RUN_COMMAND_PATH '/data/data/com.termux/files/usr/bin/bash' \
--es com.termux.RUN_COMMAND_SESSION_CREATE_MODE 'no-session-with-name' \
--es com.termux.RUN_COMMAND_SESSION_NAME "custom-name"
```
This commit is contained in:
agnostic-apollo
2022-03-18 05:53:35 +05:00
parent ee32ef0c7e
commit 5794ab9a56
5 changed files with 136 additions and 22 deletions

View File

@@ -116,6 +116,8 @@ public class RunCommandService extends Service {
executionCommand.backgroundCustomLogLevel = IntentUtils.getIntegerExtraIfSet(intent, RUN_COMMAND_SERVICE.EXTRA_BACKGROUND_CUSTOM_LOG_LEVEL, null);
executionCommand.sessionAction = intent.getStringExtra(RUN_COMMAND_SERVICE.EXTRA_SESSION_ACTION);
executionCommand.sessionName = IntentUtils.getStringExtraIfSet(intent, RUN_COMMAND_SERVICE.EXTRA_SESSION_NAME, null);
executionCommand.sessionCreateMode = IntentUtils.getStringExtraIfSet(intent, RUN_COMMAND_SERVICE.EXTRA_SESSION_CREATE_MODE, null);
executionCommand.commandLabel = IntentUtils.getStringExtraIfSet(intent, RUN_COMMAND_SERVICE.EXTRA_COMMAND_LABEL, "RUN_COMMAND Execution Intent Command");
executionCommand.commandDescription = IntentUtils.getStringExtraIfSet(intent, RUN_COMMAND_SERVICE.EXTRA_COMMAND_DESCRIPTION, null);
executionCommand.commandHelp = IntentUtils.getStringExtraIfSet(intent, RUN_COMMAND_SERVICE.EXTRA_COMMAND_HELP, null);
@@ -211,6 +213,8 @@ public class RunCommandService extends Service {
execIntent.putExtra(TERMUX_SERVICE.EXTRA_RUNNER, executionCommand.runner);
execIntent.putExtra(TERMUX_SERVICE.EXTRA_BACKGROUND_CUSTOM_LOG_LEVEL, DataUtils.getStringFromInteger(executionCommand.backgroundCustomLogLevel, null));
execIntent.putExtra(TERMUX_SERVICE.EXTRA_SESSION_ACTION, executionCommand.sessionAction);
execIntent.putExtra(TERMUX_SERVICE.EXTRA_SESSION_NAME, executionCommand.sessionName);
execIntent.putExtra(TERMUX_SERVICE.EXTRA_SESSION_CREATE_MODE, executionCommand.sessionCreateMode);
execIntent.putExtra(TERMUX_SERVICE.EXTRA_COMMAND_LABEL, executionCommand.commandLabel);
execIntent.putExtra(TERMUX_SERVICE.EXTRA_COMMAND_DESCRIPTION, executionCommand.commandDescription);
execIntent.putExtra(TERMUX_SERVICE.EXTRA_COMMAND_HELP, executionCommand.commandHelp);

View File

@@ -41,6 +41,7 @@ import com.termux.shared.android.PermissionUtils;
import com.termux.shared.data.DataUtils;
import com.termux.shared.shell.command.ExecutionCommand;
import com.termux.shared.shell.command.ExecutionCommand.Runner;
import com.termux.shared.shell.command.ExecutionCommand.SessionCreateMode;
import com.termux.terminal.TerminalEmulator;
import com.termux.terminal.TerminalSession;
import com.termux.terminal.TerminalSessionClient;
@@ -384,6 +385,8 @@ public final class TermuxService extends Service implements AppShell.AppShellCli
executionCommand.workingDirectory = IntentUtils.getStringExtraIfSet(intent, TERMUX_SERVICE.EXTRA_WORKDIR, null);
executionCommand.isFailsafe = intent.getBooleanExtra(TERMUX_ACTIVITY.EXTRA_FAILSAFE_SESSION, false);
executionCommand.sessionAction = intent.getStringExtra(TERMUX_SERVICE.EXTRA_SESSION_ACTION);
executionCommand.sessionName = IntentUtils.getStringExtraIfSet(intent, TERMUX_SERVICE.EXTRA_SESSION_NAME, null);
executionCommand.sessionCreateMode = IntentUtils.getStringExtraIfSet(intent, TERMUX_SERVICE.EXTRA_SESSION_CREATE_MODE, null);
executionCommand.commandLabel = IntentUtils.getStringExtraIfSet(intent, TERMUX_SERVICE.EXTRA_COMMAND_LABEL, "Execution Intent Command");
executionCommand.commandDescription = IntentUtils.getStringExtraIfSet(intent, TERMUX_SERVICE.EXTRA_COMMAND_DESCRIPTION, null);
executionCommand.commandHelp = IntentUtils.getStringExtraIfSet(intent, TERMUX_SERVICE.EXTRA_COMMAND_HELP, null);
@@ -402,13 +405,13 @@ public final class TermuxService extends Service implements AppShell.AppShellCli
mPendingPluginExecutionCommands.add(executionCommand);
if (Runner.APP_SHELL.equalsRunner(executionCommand.runner))
executeTermuxTaskCommand(executionCommand);
executeTermuxTaskCommand(executionCommand);
else if (Runner.TERMINAL_SESSION.equalsRunner(executionCommand.runner))
executeTermuxSessionCommand(executionCommand);
executeTermuxSessionCommand(executionCommand);
else {
String errmsg = this.getString(R.string.error_termux_service_unsupported_execution_command_runner, executionCommand.runner);
executionCommand.setStateFailed(Errno.ERRNO_FAILED.getCode(), errmsg);
PluginUtils.processPluginExecutionCommandError(this, LOG_TAG, executionCommand, false);
String errmsg = getString(R.string.error_termux_service_unsupported_execution_command_runner, executionCommand.runner);
executionCommand.setStateFailed(Errno.ERRNO_FAILED.getCode(), errmsg);
PluginUtils.processPluginExecutionCommandError(this, LOG_TAG, executionCommand, false);
}
}
@@ -497,16 +500,39 @@ public final class TermuxService extends Service implements AppShell.AppShellCli
private void executeTermuxSessionCommand(ExecutionCommand executionCommand) {
if (executionCommand == null) return;
if (executionCommand.sessionCreateMode == null)
executionCommand.sessionCreateMode = SessionCreateMode.ALWAYS.getMode();
Logger.logDebug(LOG_TAG, "Executing foreground \"" + executionCommand.getCommandIdAndLabelLogString() + "\" TermuxSession command");
String sessionName = null;
// Transform executable path to session name, e.g. "/bin/do-something.sh" => "do something.sh".
if (executionCommand.executable != null) {
sessionName = ShellUtils.getExecutableBasename(executionCommand.executable).replace('-', ' ');
// Transform executable path to session name, e.g. "/bin/do-something.sh" => "do-something.sh".
if (executionCommand.sessionName == null && executionCommand.executable != null) {
executionCommand.sessionName = ShellUtils.getExecutableBasename(executionCommand.executable);
}
TermuxSession newTermuxSession = createTermuxSession(executionCommand, sessionName);
TermuxSession newTermuxSession = null;
if (SessionCreateMode.ALWAYS.equalsMode(executionCommand.sessionCreateMode))
; // Default
else if (SessionCreateMode.NO_SESSION_WITH_NAME.equalsMode(executionCommand.sessionCreateMode))
if (DataUtils.isNullOrEmpty(executionCommand.sessionName)) {
String errmsg = getString(R.string.error_termux_service_execution_command_session_name_unset, executionCommand.sessionCreateMode);
executionCommand.setStateFailed(Errno.ERRNO_FAILED.getCode(), errmsg);
PluginUtils.processPluginExecutionCommandError(this, LOG_TAG, executionCommand, false);
return;
} else {
newTermuxSession = getTermuxSessionForName(executionCommand.sessionName);
if (newTermuxSession != null)
Logger.logInfo(LOG_TAG, "Existing session with \"" + executionCommand.sessionName + "\" session name found");
}
else {
String errmsg = getString(R.string.error_termux_service_unsupported_execution_command_session_create_mode, executionCommand.sessionCreateMode);
executionCommand.setStateFailed(Errno.ERRNO_FAILED.getCode(), errmsg);
PluginUtils.processPluginExecutionCommandError(this, LOG_TAG, executionCommand, false);
return;
}
if (newTermuxSession == null)
newTermuxSession = createTermuxSession(executionCommand);
if (newTermuxSession == null) return;
handleSessionAction(DataUtils.getIntFromString(executionCommand.sessionAction,
@@ -858,6 +884,18 @@ public final class TermuxService extends Service implements AppShell.AppShellCli
return null;
}
public synchronized TermuxSession getTermuxSessionForName(String name) {
if (DataUtils.isNullOrEmpty(name)) return null;
TermuxSession termuxSession;
for (int i = 0, len = mTermuxSessions.size(); i < len; i++) {
termuxSession = mTermuxSessions.get(i);
TerminalSession terminalSession = termuxSession.getTerminalSession();
if (terminalSession.mSessionName != null && terminalSession.mSessionName.equals(name))
return termuxSession;
}
return null;
}
public static synchronized int getNextExecutionId() {

View File

@@ -100,6 +100,8 @@
Grants it from Settings -> Apps -> &TERMUX_APP_NAME; -> Advanced</string>
<string name="error_termux_service_invalid_execution_command_runner">Invalid execution command runner to TermuxService: `%1$s`</string>
<string name="error_termux_service_unsupported_execution_command_runner">Unsupported execution command runner to TermuxService: `%1$s`</string>
<string name="error_termux_service_unsupported_execution_command_session_create_mode">Unsupported execution command session create mode to TermuxService: `%1$s`</string>
<string name="error_termux_service_execution_command_session_name_unset">Session name not set but `%1$s` session create mode passed</string>