mirror of https://github.com/termux/termux-app
Updated RunCommandService javadocs.
Documentation has been moved to https://github.com/termux/termux-app/wiki/RUN_COMMAND-Intent
This commit is contained in:
parent
71dfefd4b7
commit
62a2104adc
|
@ -1,7 +1,5 @@
|
|||
package com.termux.app;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.IntentService;
|
||||
import android.app.Notification;
|
||||
import android.app.NotificationManager;
|
||||
import android.app.Service;
|
||||
|
@ -23,250 +21,11 @@ import com.termux.shared.data.DataUtils;
|
|||
import com.termux.app.models.ExecutionCommand;
|
||||
|
||||
/**
|
||||
* Third-party apps that are not part of termux world can run commands in termux context by either
|
||||
* sending an intent to RunCommandService or becoming a plugin host for the termux-tasker plugin
|
||||
* client.
|
||||
*
|
||||
* For the {@link RUN_COMMAND_SERVICE#ACTION_RUN_COMMAND} intent to work, here are the requirements:
|
||||
*
|
||||
* 1. `com.termux.permission.RUN_COMMAND` permission (Mandatory)
|
||||
* The Intent sender/third-party app must request the `com.termux.permission.RUN_COMMAND`
|
||||
* permission in its `AndroidManifest.xml` and it should be granted by user to the app through the
|
||||
* app's `App Info` `Permissions` page in Android Settings, likely under `Additional Permissions`.
|
||||
* This is a security measure to prevent any other apps from running commands in `Termux` context
|
||||
* which do not have the required permission granted to them.
|
||||
*
|
||||
* For `Tasker` you can grant it with:
|
||||
* `Android Settings` -> `Apps` -> `Tasker` -> `Permissions` -> `Additional permissions` ->
|
||||
* `Run commands in Termux environment`.
|
||||
*
|
||||
* 2. `allow-external-apps` property (Mandatory)
|
||||
* The `allow-external-apps` property must be set to "true" in `~/.termux/termux.properties` in
|
||||
* Termux app, regardless of if the executable path is inside or outside the `~/.termux/tasker/`
|
||||
* directory. Check https://github.com/termux/termux-tasker#allow-external-apps-property-optional
|
||||
* for more info.
|
||||
*
|
||||
* 3. `Draw Over Apps` permission (Optional)
|
||||
* For android `>= 10` there are new
|
||||
* [restrictions](https://developer.android.com/guide/components/activities/background-starts)
|
||||
* that prevent activities from starting from the background. This prevents the background
|
||||
* {@link TermuxService} from starting a terminal session in the foreground and running the
|
||||
* commands until the user manually clicks `Termux` notification in the status bar dropdown
|
||||
* notifications list. This only affects commands that are to be executed in a terminal
|
||||
* session and not the background ones. `Termux` version `>= 0.100`
|
||||
* requests the `Draw Over Apps` permission so that users can bypass this restriction so
|
||||
* that commands can automatically start running without user intervention.
|
||||
* You can grant `Termux` the `Draw Over Apps` permission from its `App Info` activity:
|
||||
* `Android Settings` -> `Apps` -> `Termux` -> `Advanced` -> `Draw over other apps`.
|
||||
*
|
||||
* 4. `Storage` permission (Optional)
|
||||
* Termux app must be granted `Storage` permission if the executable is accessing or working
|
||||
* directory is set to path in external shared storage. The common paths which usually refer to
|
||||
* it are `~/storage`, `/sdcard`, `/storage/emulated/0` etc.
|
||||
* You can grant `Termux` the `Storage` permission from its `App Info` activity:
|
||||
* For Android version < 11:
|
||||
* `Android Settings` -> `Apps` -> `Termux` -> `Permissions` -> `Storage`.
|
||||
* For Android version >= 11
|
||||
* `Android Settings` -> `Apps` -> `Termux` -> `Permissions` -> `Files and media` ->
|
||||
* `Allowed management of all files`.
|
||||
* NOTE: For Android version >= 11, sometimes you will get `Permission Denied` errors for
|
||||
* external shared storage even when you have granted `Files and media` permission. To solve
|
||||
* this, Deny the permission and then Allow it again and restart Termux.
|
||||
* Also check https://wiki.termux.com/wiki/Termux-setup-storage
|
||||
*
|
||||
* 5. Battery Optimizations (May be mandatory depending on device)
|
||||
* Some devices kill apps aggressively or prevent apps from starting from background.
|
||||
* If Termux is running into such problems, then exempt it from such restrictions.
|
||||
* The user may also disable battery optimizations for Termux to reduce the chances of Termux
|
||||
* being killed by Android even further due to violation of not being able to call
|
||||
* `startForeground()` within ~5s of service start in android >= 8.
|
||||
* Check https://dontkillmyapp.com/ for device specfic info to opt-out of battery optimiations.
|
||||
*
|
||||
* You may also want to check https://github.com/termux/termux-tasker
|
||||
*
|
||||
*
|
||||
*
|
||||
* The {@link RUN_COMMAND_SERVICE#ACTION_RUN_COMMAND} intent expects the following extras:
|
||||
*
|
||||
* 1. The **mandatory** {@code String} {@link RUN_COMMAND_SERVICE#EXTRA_COMMAND_PATH} extra for
|
||||
* absolute path of command.
|
||||
* 2. The {@code String[]} {@link RUN_COMMAND_SERVICE#EXTRA_ARGUMENTS} extra for any arguments to
|
||||
* pass to command.
|
||||
* 3. The {@code String} {@link RUN_COMMAND_SERVICE#EXTRA_WORKDIR} extra for current working directory
|
||||
* of command. This defaults to {@link TermuxConstants#TERMUX_HOME_DIR_PATH}.
|
||||
* 4. The {@code boolean} {@link RUN_COMMAND_SERVICE#EXTRA_BACKGROUND} extra whether to run command
|
||||
* in background or foreground terminal session. This defaults to {@code false}.
|
||||
* 5. The {@code String} {@link RUN_COMMAND_SERVICE#EXTRA_SESSION_ACTION} extra for for session action
|
||||
* of foreground commands. This defaults to
|
||||
* {@link TERMUX_SERVICE#VALUE_EXTRA_SESSION_ACTION_SWITCH_TO_NEW_SESSION_AND_OPEN_ACTIVITY}.
|
||||
* 6. The {@code String} {@link RUN_COMMAND_SERVICE#EXTRA_COMMAND_LABEL} extra for label of the command.
|
||||
* 7. The markdown {@code String} {@link RUN_COMMAND_SERVICE#EXTRA_COMMAND_DESCRIPTION} extra for
|
||||
* description of the command. This should ideally be get short.
|
||||
* 8. The markdown {@code String} {@link RUN_COMMAND_SERVICE#EXTRA_COMMAND_HELP} extra for help of
|
||||
* the command. This can add details about the command. 3rd party apps can provide more info
|
||||
* to users for setting up commands. Ideally a url link should be provided that goes into full
|
||||
* details.
|
||||
* 9. The {@code Parcelable} {@link RUN_COMMAND_SERVICE#EXTRA_PENDING_INTENT} extra containing the
|
||||
* pending intent with which result of commands should be returned to the caller. The results
|
||||
* will be sent in the {@link TERMUX_SERVICE#EXTRA_PLUGIN_RESULT_BUNDLE} bundle. This is optional
|
||||
* and only needed if caller wants the results back.
|
||||
*
|
||||
*
|
||||
* The {@link RUN_COMMAND_SERVICE#EXTRA_COMMAND_PATH} and {@link RUN_COMMAND_SERVICE#EXTRA_WORKDIR}
|
||||
* can optionally be prefixed with "$PREFIX/" or "~/" if an absolute path is not to be given.
|
||||
* The "$PREFIX/" will expand to {@link TermuxConstants#TERMUX_PREFIX_DIR_PATH} and
|
||||
* "~/" will expand to {@link TermuxConstants#TERMUX_HOME_DIR_PATH}, followed by a forward slash "/".
|
||||
*
|
||||
*
|
||||
* The `EXTRA_COMMAND_*` extras are used for logging and are their values are provided to users in case
|
||||
* of failure in a popup. The popup shown is in commonmark-spec markdown using markwon library so
|
||||
* make sure to follow its formatting rules. Also make sure to end lines with 2 blank spaces to prevent
|
||||
* word-wrap wherever needed.
|
||||
* It's the users and 3rd party apps responsibility to use them wisely. There are also android
|
||||
* internal intent size limits (roughly 500KB) that must not exceed when sending intents so make sure
|
||||
* the combined size of ALL extras is less than that.
|
||||
* There are also limits on the arguments size you can pass to commands or the full command string
|
||||
* length that can be run, which is likely equal to 131072 bytes or 128KB on an android device.
|
||||
* Check https://github.com/termux/termux-tasker#arguments-and-result-data-limits for more details.
|
||||
*
|
||||
*
|
||||
*
|
||||
* If your third-party app is targeting sdk 30 (android 11), then it needs to add `com.termux`
|
||||
* package to the `queries` element or request `QUERY_ALL_PACKAGES` permission in its
|
||||
* `AndroidManifest.xml`. Otherwise it will get `PackageSetting{...... com.termux/......} BLOCKED`
|
||||
* errors in logcat and `RUN_COMMAND` won't work.
|
||||
* https://developer.android.com/training/basics/intents/package-visibility#package-name
|
||||
*
|
||||
*
|
||||
* Its probably wiser for apps to import the {@link TermuxConstants} class and use the variables
|
||||
* provided for actions and extras instead of using hardcoded string values.
|
||||
*
|
||||
* Sample code to run command "top" with java:
|
||||
* ```
|
||||
* intent.setClassName("com.termux", "com.termux.app.RunCommandService");
|
||||
* intent.setAction("com.termux.RUN_COMMAND");
|
||||
* intent.putExtra("com.termux.RUN_COMMAND_PATH", "/data/data/com.termux/files/usr/bin/top");
|
||||
* intent.putExtra("com.termux.RUN_COMMAND_ARGUMENTS", new String[]{"-n", "5"});
|
||||
* intent.putExtra("com.termux.RUN_COMMAND_WORKDIR", "/data/data/com.termux/files/home");
|
||||
* intent.putExtra("com.termux.RUN_COMMAND_BACKGROUND", false);
|
||||
* intent.putExtra("com.termux.RUN_COMMAND_SESSION_ACTION", "0");
|
||||
* startService(intent);
|
||||
* ```
|
||||
*
|
||||
* Sample code to run command "top" with "am startservice" command:
|
||||
* ```
|
||||
* 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/top' \
|
||||
* --esa com.termux.RUN_COMMAND_ARGUMENTS '-n,5' \
|
||||
* --es com.termux.RUN_COMMAND_WORKDIR '/data/data/com.termux/files/home' \
|
||||
* --ez com.termux.RUN_COMMAND_BACKGROUND 'false' \
|
||||
* --es com.termux.RUN_COMMAND_SESSION_ACTION '0'
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
* The {@link RUN_COMMAND_SERVICE#ACTION_RUN_COMMAND} intent returns the following extras
|
||||
* in the {@link TERMUX_SERVICE#EXTRA_PLUGIN_RESULT_BUNDLE} bundle if a pending intent is sent by the
|
||||
* called in {@code Parcelable} {@link RUN_COMMAND_SERVICE#EXTRA_PENDING_INTENT} extra:
|
||||
*
|
||||
* For foreground commands ({@link RUN_COMMAND_SERVICE#EXTRA_BACKGROUND} is `false`):
|
||||
* - {@link TERMUX_SERVICE#EXTRA_PLUGIN_RESULT_BUNDLE_STDOUT} will contain session transcript.
|
||||
* - {@link TERMUX_SERVICE#EXTRA_PLUGIN_RESULT_BUNDLE_STDERR} will be null since its not used.
|
||||
* - {@link TERMUX_SERVICE#EXTRA_PLUGIN_RESULT_BUNDLE_EXIT_CODE} will contain exit code of session.
|
||||
|
||||
* For background commands ({@link RUN_COMMAND_SERVICE#EXTRA_BACKGROUND} is `true`):
|
||||
* - {@link TERMUX_SERVICE#EXTRA_PLUGIN_RESULT_BUNDLE_STDOUT} will contain stdout of commands.
|
||||
* - {@link TERMUX_SERVICE#EXTRA_PLUGIN_RESULT_BUNDLE_STDERR} will contain stderr of commands.
|
||||
* - {@link TERMUX_SERVICE#EXTRA_PLUGIN_RESULT_BUNDLE_EXIT_CODE} will contain exit code of command.
|
||||
*
|
||||
* The {@link TERMUX_SERVICE#EXTRA_PLUGIN_RESULT_BUNDLE_STDOUT_ORIGINAL_LENGTH} and
|
||||
* {@link TERMUX_SERVICE#EXTRA_PLUGIN_RESULT_BUNDLE_STDERR_ORIGINAL_LENGTH} will contain
|
||||
* the original length of stdout and stderr respectively. This is useful to detect cases where
|
||||
* stdout and stderr was too large to be sent back via an intent, otherwise
|
||||
*
|
||||
* The internal errors raised by termux outside the shell will be sent in the the
|
||||
* {@link TERMUX_SERVICE#EXTRA_PLUGIN_RESULT_BUNDLE_ERR} and {@link TERMUX_SERVICE#EXTRA_PLUGIN_RESULT_BUNDLE_ERRMSG}
|
||||
* extras. These will contain errors like if starting a termux command failed or if the user manually
|
||||
* exited the termux sessions or android killed the termux service before the commands had finished executing.
|
||||
* The err value will be {@link Activity#RESULT_OK}(-1) if no internal errors are raised.
|
||||
*
|
||||
* Note that if stdout or stderr are too large in length, then a {@link android.os.TransactionTooLargeException}
|
||||
* exception will be raised when the pending intent is sent back containing the results, But it cannot
|
||||
* be caught by the intent sender and intent will silently fail with logcat entries for the exception
|
||||
* raised internally by android os components. To prevent this, the stdout and stderr sent
|
||||
* back will be truncated from the start to max 100KB combined. The original length of stdout and
|
||||
* stderr will be provided in
|
||||
* {@link TERMUX_SERVICE#EXTRA_PLUGIN_RESULT_BUNDLE_STDOUT_ORIGINAL_LENGTH} and
|
||||
* {@link TERMUX_SERVICE#EXTRA_PLUGIN_RESULT_BUNDLE_STDERR_ORIGINAL_LENGTH} extras respectively, so
|
||||
* that the caller can check if either of them were truncated. The errmsg will also be truncated
|
||||
* from end to max 25KB to preserve start of stacktraces.
|
||||
*
|
||||
*
|
||||
*
|
||||
* If your app (not shell) wants to receive termux session command results, then put the
|
||||
* pending intent for your app like for an {@link IntentService} in the "com.termux.RUN_COMMAND_PENDING_INTENT"
|
||||
* extra.
|
||||
* ```
|
||||
* // Create intent for your IntentService class
|
||||
* Intent pluginResultsServiceIntent = new Intent(MainActivity.this, PluginResultsService.class);
|
||||
* // Create PendingIntent that will be used by termux service to send result of commands back to PluginResultsService
|
||||
* PendingIntent pendingIntent = PendingIntent.getService(context, 1, pluginResultsServiceIntent, PendingIntent.FLAG_ONE_SHOT);
|
||||
* intent.putExtra("com.termux.RUN_COMMAND_PENDING_INTENT", pendingIntent);
|
||||
* ```
|
||||
*
|
||||
*
|
||||
* Declare `PluginResultsService` entry in AndroidManifest.xml
|
||||
* ```
|
||||
* <service android:name=".PluginResultsService" />
|
||||
* ```
|
||||
*
|
||||
*
|
||||
* Define the `PluginResultsService` class
|
||||
* ```
|
||||
* public class PluginResultsService extends IntentService {
|
||||
*
|
||||
* public static final String PLUGIN_SERVICE_LABEL = "PluginResultsService";
|
||||
*
|
||||
* private static final String LOG_TAG = "PluginResultsService";
|
||||
*
|
||||
* public PluginResultsService(){
|
||||
* super(PLUGIN_SERVICE_LABEL);
|
||||
* }
|
||||
*
|
||||
* @Override
|
||||
* protected void onHandleIntent(@Nullable Intent intent) {
|
||||
* if (intent == null) return;
|
||||
*
|
||||
* if(intent.getComponent() != null)
|
||||
* Log.d(LOG_TAG, PLUGIN_SERVICE_LABEL + " received execution result from " + intent.getComponent().toString());
|
||||
*
|
||||
*
|
||||
* final Bundle resultBundle = intent.getBundleExtra("result");
|
||||
* if (resultBundle == null) {
|
||||
* Log.e(LOG_TAG, "The intent does not contain the result bundle at the \"result\" key.");
|
||||
* return;
|
||||
* }
|
||||
*
|
||||
* Log.d(LOG_TAG, "stdout:\n```\n" + resultBundle.getString("stdout", "") + "\n```\n" +
|
||||
* "stdout_original_length: `" + resultBundle.getString("stdout_original_length") + "`\n" +
|
||||
* "stderr:\n```\n" + resultBundle.getString("stderr", "") + "\n```\n" +
|
||||
* "stderr_original_length: `" + resultBundle.getString("stderr_original_length") + "`\n" +
|
||||
* "exitCode: `" + resultBundle.getInt("exitCode") + "`\n" +
|
||||
* "errCode: `" + resultBundle.getInt("err") + "`\n" +
|
||||
* "errmsg: `" + resultBundle.getString("errmsg", "") + "`");
|
||||
* }
|
||||
*
|
||||
* }
|
||||
*```
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
* A service that receives {@link RUN_COMMAND_SERVICE#ACTION_RUN_COMMAND} intent from third party apps and
|
||||
* plugins that contains info on command execution and forwards the extras to {@link TermuxService}
|
||||
* for the actual execution.
|
||||
*
|
||||
* Check https://github.com/termux/termux-app/wiki/RUN_COMMAND-Intent for more info.
|
||||
*/
|
||||
public class RunCommandService extends Service {
|
||||
|
||||
|
|
Loading…
Reference in New Issue