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>

View File

@ -105,6 +105,41 @@ public class ExecutionCommand {
}
public enum SessionCreateMode {
/** Always create {@link TerminalSession}. */
ALWAYS("always"),
/** Create session only if no session with {@link #sessionName} found. */
NO_SESSION_WITH_NAME("no-session-with-name");
private final String mode;
SessionCreateMode(final String mode) {
this.mode = mode;
}
public String getMode() {
return mode;
}
public boolean equalsMode(String sessionCreateMode) {
return sessionCreateMode != null && sessionCreateMode.equals(this.mode);
}
/** Get {@link SessionCreateMode} for {@code mode} if found, otherwise {@code null}. */
@Nullable
public static SessionCreateMode modeOf(String mode) {
for (SessionCreateMode v : SessionCreateMode.values()) {
if (v.mode.equals(mode)) {
return v;
}
}
return null;
}
}
/** The optional unique id for the {@link ExecutionCommand}. */
public Integer id;
@ -155,6 +190,11 @@ public class ExecutionCommand {
/** The session name of {@link Runner#TERMINAL_SESSION} commands. */
public String sessionName;
/** The {@link SessionCreateMode} of session for {@link Runner#TERMINAL_SESSION} commands. */
public String sessionCreateMode;
/** The command label for the {@link ExecutionCommand}. */
public String commandLabel;
/** The markdown text for the command description for the {@link ExecutionCommand}. */
@ -349,6 +389,11 @@ public class ExecutionCommand {
if (!ignoreNull || executionCommand.sessionName != null) {
logString.append("\n").append(executionCommand.getSessionNameLogString());
}
if (!ignoreNull || executionCommand.sessionCreateMode != null) {
logString.append("\n").append(executionCommand.getSessionCreateModeLogString());
}
if (!ignoreNull || executionCommand.commandIntent != null)
logString.append("\n").append(executionCommand.getCommandIntentLogString());
@ -441,6 +486,7 @@ public class ExecutionCommand {
markdownString.append("\n").append(MarkdownUtils.getSingleLineMarkdownStringEntry("Session Action", executionCommand.sessionAction, "-"));
markdownString.append("\n").append(MarkdownUtils.getSingleLineMarkdownStringEntry("Session Name", executionCommand.sessionName, "-"));
markdownString.append("\n").append(MarkdownUtils.getSingleLineMarkdownStringEntry("Session Create Mode", executionCommand.sessionCreateMode, "-"));
markdownString.append("\n").append(MarkdownUtils.getSingleLineMarkdownStringEntry("isPluginExecutionCommand", executionCommand.isPluginExecutionCommand, "-"));
@ -534,6 +580,11 @@ public class ExecutionCommand {
public String getSessionNameLogString() {
return Logger.getSingleLineLogStringEntry("Session Name", sessionName, "-");
}
public String getSessionCreateModeLogString() {
return Logger.getSingleLineLogStringEntry("Session Create Mode", sessionCreateMode, "-");
}
public String getCommandDescriptionLogString() {
return Logger.getSingleLineLogStringEntry("Command Description", commandDescription, "-");
}

View File

@ -2,13 +2,16 @@ package com.termux.shared.termux;
import android.annotation.SuppressLint;
import com.termux.shared.shell.command.ExecutionCommand;
import com.termux.shared.shell.command.ExecutionCommand.Runner;
import java.io.File;
import java.util.Arrays;
import java.util.Formatter;
import java.util.List;
/*
* Version: v0.38.0
* Version: v0.39.0
* SPDX-License-Identifier: MIT
*
* Changelog
@ -226,6 +229,10 @@ import java.util.List;
*
* - 0.38.0 (2022-03-16)
* - Added `TERMUX_APP.TERMUX_ACTIVITY.ACTION_NOTIFY_APP_CRASH`.
*
* - 0.39.0 (2022-03-18)
* - Added `TERMUX_APP.TERMUX_SERVICE.EXTRA_SESSION_NAME`, `TERMUX_APP.RUN_COMMAND_SERVICE.EXTRA_SESSION_NAME`,
* `TERMUX_APP.TERMUX_SERVICE.EXTRA_SESSION_CREATE_MODE` and `TERMUX_APP.RUN_COMMAND_SERVICE.EXTRA_SESSION_CREATE_MODE`.
*/
/**
@ -937,15 +944,19 @@ public final class TermuxConstants {
public static final String EXTRA_STDIN = TERMUX_PACKAGE_NAME + ".execute.stdin"; // Default: "com.termux.execute.stdin"
/** Intent {@code String} extra for command current working directory for the TERMUX_SERVICE.ACTION_SERVICE_EXECUTE intent */
public static final String EXTRA_WORKDIR = TERMUX_PACKAGE_NAME + ".execute.cwd"; // Default: "com.termux.execute.cwd"
/** Intent {@code boolean} extra for command background mode for the TERMUX_SERVICE.ACTION_SERVICE_EXECUTE intent */
/** Intent {@code boolean} extra for whether to run command in background {@link Runner#APP_SHELL} or foreground {@link Runner#TERMINAL_SESSION} for the TERMUX_SERVICE.ACTION_SERVICE_EXECUTE intent */
@Deprecated
public static final String EXTRA_BACKGROUND = TERMUX_PACKAGE_NAME + ".execute.background"; // Default: "com.termux.execute.background"
/** Intent {@code boolean} extra for command the {@link com.termux.shared.shell.command.ExecutionCommand.Runner} for the TERMUX_SERVICE.ACTION_SERVICE_EXECUTE intent */
/** Intent {@code String} extra for command the {@link Runner} for the TERMUX_SERVICE.ACTION_SERVICE_EXECUTE intent */
public static final String EXTRA_RUNNER = TERMUX_PACKAGE_NAME + ".execute.runner"; // Default: "com.termux.execute.runner"
/** Intent {@code String} extra for custom log level for background commands defined by {@link com.termux.shared.logger.Logger} for the TERMUX_SERVICE.ACTION_SERVICE_EXECUTE intent */
public static final String EXTRA_BACKGROUND_CUSTOM_LOG_LEVEL = TERMUX_PACKAGE_NAME + ".execute.background_custom_log_level"; // Default: "com.termux.execute.background_custom_log_level"
/** Intent {@code String} extra for session action for foreground commands for the TERMUX_SERVICE.ACTION_SERVICE_EXECUTE intent */
/** Intent {@code String} extra for session action for {@link Runner#TERMINAL_SESSION} commands for the TERMUX_SERVICE.ACTION_SERVICE_EXECUTE intent */
public static final String EXTRA_SESSION_ACTION = TERMUX_PACKAGE_NAME + ".execute.session_action"; // Default: "com.termux.execute.session_action"
/** Intent {@code String} extra for session name for {@link Runner#TERMINAL_SESSION} commands for the TERMUX_SERVICE.ACTION_SERVICE_EXECUTE intent */
public static final String EXTRA_SESSION_NAME = TERMUX_PACKAGE_NAME + ".execute.session_name"; // Default: "com.termux.execute.session_name"
/** Intent {@code String} extra for the {@link ExecutionCommand.SessionCreateMode} for the TERMUX_SERVICE.ACTION_SERVICE_EXECUTE intent. */
public static final String EXTRA_SESSION_CREATE_MODE = TERMUX_PACKAGE_NAME + ".execute.session_create_mode"; // Default: "com.termux.execute.session_create_mode"
/** Intent {@code String} extra for label of the command for the TERMUX_SERVICE.ACTION_SERVICE_EXECUTE intent */
public static final String EXTRA_COMMAND_LABEL = TERMUX_PACKAGE_NAME + ".execute.command_label"; // Default: "com.termux.execute.command_label"
/** Intent markdown {@code String} extra for description of the command for the TERMUX_SERVICE.ACTION_SERVICE_EXECUTE intent */
@ -981,20 +992,23 @@ public final class TermuxConstants {
/** The value for {@link #EXTRA_SESSION_ACTION} extra that will set the new session as
/**
* The value for {@link #EXTRA_SESSION_ACTION} extra that will set the new session as
* the current session and will start {@link TERMUX_ACTIVITY} if its not running to bring
* the new session to foreground.
*/
public static final int VALUE_EXTRA_SESSION_ACTION_SWITCH_TO_NEW_SESSION_AND_OPEN_ACTIVITY = 0;
/** The value for {@link #EXTRA_SESSION_ACTION} extra that will keep any existing session
/**
* The value for {@link #EXTRA_SESSION_ACTION} extra that will keep any existing session
* as the current session and will start {@link TERMUX_ACTIVITY} if its not running to
* bring the existing session to foreground. The new session will be added to the left
* sidebar in the sessions list.
*/
public static final int VALUE_EXTRA_SESSION_ACTION_KEEP_CURRENT_SESSION_AND_OPEN_ACTIVITY = 1;
/** The value for {@link #EXTRA_SESSION_ACTION} extra that will set the new session as
/**
* The value for {@link #EXTRA_SESSION_ACTION} extra that will set the new session as
* the current session but will not start {@link TERMUX_ACTIVITY} if its not running
* and session(s) will be seen in Termux notification and can be clicked to bring new
* session to foreground. If the {@link TERMUX_ACTIVITY} is already running, then this
@ -1002,7 +1016,8 @@ public final class TermuxConstants {
*/
public static final int VALUE_EXTRA_SESSION_ACTION_SWITCH_TO_NEW_SESSION_AND_DONT_OPEN_ACTIVITY = 2;
/** The value for {@link #EXTRA_SESSION_ACTION} extra that will keep any existing session
/**
* The value for {@link #EXTRA_SESSION_ACTION} extra that will keep any existing session
* as the current session but will not start {@link TERMUX_ACTIVITY} if its not running
* and session(s) will be seen in Termux notification and can be clicked to bring
* existing session to foreground. If the {@link TERMUX_ACTIVITY} is already running,
@ -1070,15 +1085,19 @@ public final class TermuxConstants {
public static final String EXTRA_STDIN = TERMUX_PACKAGE_NAME + ".RUN_COMMAND_STDIN"; // Default: "com.termux.RUN_COMMAND_STDIN"
/** Intent {@code String} extra for current working directory of command for the RUN_COMMAND_SERVICE.ACTION_RUN_COMMAND intent */
public static final String EXTRA_WORKDIR = TERMUX_PACKAGE_NAME + ".RUN_COMMAND_WORKDIR"; // Default: "com.termux.RUN_COMMAND_WORKDIR"
/** Intent {@code boolean} extra for whether to run command in background or foreground terminal session for the RUN_COMMAND_SERVICE.ACTION_RUN_COMMAND intent */
/** Intent {@code boolean} extra for whether to run command in background {@link Runner#APP_SHELL} or foreground {@link Runner#TERMINAL_SESSION} for the RUN_COMMAND_SERVICE.ACTION_RUN_COMMAND intent */
@Deprecated
public static final String EXTRA_BACKGROUND = TERMUX_PACKAGE_NAME + ".RUN_COMMAND_BACKGROUND"; // Default: "com.termux.RUN_COMMAND_BACKGROUND"
/** Intent {@code boolean} extra for command the {@link com.termux.shared.shell.command.ExecutionCommand.Runner} for the RUN_COMMAND_SERVICE.ACTION_RUN_COMMAND intent */
/** Intent {@code String} extra for command the {@link Runner} for the RUN_COMMAND_SERVICE.ACTION_RUN_COMMAND intent */
public static final String EXTRA_RUNNER = TERMUX_PACKAGE_NAME + ".RUN_COMMAND_RUNNER"; // Default: "com.termux.RUN_COMMAND_RUNNER"
/** Intent {@code String} extra for custom log level for background commands defined by {@link com.termux.shared.logger.Logger} for the RUN_COMMAND_SERVICE.ACTION_RUN_COMMAND intent */
public static final String EXTRA_BACKGROUND_CUSTOM_LOG_LEVEL = TERMUX_PACKAGE_NAME + ".RUN_COMMAND_BACKGROUND_CUSTOM_LOG_LEVEL"; // Default: "com.termux.RUN_COMMAND_BACKGROUND_CUSTOM_LOG_LEVEL"
/** Intent {@code String} extra for session action of foreground commands for the RUN_COMMAND_SERVICE.ACTION_RUN_COMMAND intent */
/** Intent {@code String} extra for session action of {@link Runner#TERMINAL_SESSION} commands for the RUN_COMMAND_SERVICE.ACTION_RUN_COMMAND intent */
public static final String EXTRA_SESSION_ACTION = TERMUX_PACKAGE_NAME + ".RUN_COMMAND_SESSION_ACTION"; // Default: "com.termux.RUN_COMMAND_SESSION_ACTION"
/** Intent {@code String} extra for session name of {@link Runner#TERMINAL_SESSION} commands for the RUN_COMMAND_SERVICE.ACTION_RUN_COMMAND intent */
public static final String EXTRA_SESSION_NAME = TERMUX_PACKAGE_NAME + ".RUN_COMMAND_SESSION_NAME"; // Default: "com.termux.RUN_COMMAND_SESSION_NAME"
/** Intent {@code String} extra for the {@link ExecutionCommand.SessionCreateMode} for the RUN_COMMAND_SERVICE.ACTION_RUN_COMMAND intent. */
public static final String EXTRA_SESSION_CREATE_MODE = TERMUX_PACKAGE_NAME + ".RUN_COMMAND_SESSION_CREATE_MODE"; // Default: "com.termux.RUN_COMMAND_SESSION_CREATE_MODE"
/** Intent {@code String} extra for label of the command for the RUN_COMMAND_SERVICE.ACTION_RUN_COMMAND intent */
public static final String EXTRA_COMMAND_LABEL = TERMUX_PACKAGE_NAME + ".RUN_COMMAND_COMMAND_LABEL"; // Default: "com.termux.RUN_COMMAND_COMMAND_LABEL"
/** Intent markdown {@code String} extra for description of the command for the RUN_COMMAND_SERVICE.ACTION_RUN_COMMAND intent */