Changed: Move com.termux.app.utils.PluginUtils to com.termux.shared.termux.plugins.TermuxPluginUtils

This will allow plugins and `termux-shared` library to trigger plugin error notifications too and process plugin command results.
This commit is contained in:
agnostic-apollo
2022-04-08 22:44:34 +05:00
parent 007f9cd7f1
commit cc981d8a03
8 changed files with 145 additions and 63 deletions

View File

@@ -12,6 +12,7 @@ import android.os.IBinder;
import com.termux.R; import com.termux.R;
import com.termux.shared.data.DataUtils; import com.termux.shared.data.DataUtils;
import com.termux.shared.data.IntentUtils; import com.termux.shared.data.IntentUtils;
import com.termux.shared.termux.plugins.TermuxPluginUtils;
import com.termux.shared.termux.file.TermuxFileUtils; import com.termux.shared.termux.file.TermuxFileUtils;
import com.termux.shared.file.filesystem.FileType; import com.termux.shared.file.filesystem.FileType;
import com.termux.shared.errors.Errno; import com.termux.shared.errors.Errno;
@@ -22,7 +23,6 @@ import com.termux.shared.termux.TermuxConstants.TERMUX_APP.TERMUX_SERVICE;
import com.termux.shared.file.FileUtils; import com.termux.shared.file.FileUtils;
import com.termux.shared.logger.Logger; import com.termux.shared.logger.Logger;
import com.termux.shared.notification.NotificationUtils; import com.termux.shared.notification.NotificationUtils;
import com.termux.app.utils.PluginUtils;
import com.termux.shared.shell.command.ExecutionCommand; import com.termux.shared.shell.command.ExecutionCommand;
import com.termux.shared.shell.command.ExecutionCommand.Runner; import com.termux.shared.shell.command.ExecutionCommand.Runner;
@@ -75,7 +75,7 @@ public class RunCommandService extends Service {
if (!RUN_COMMAND_SERVICE.ACTION_RUN_COMMAND.equals(intent.getAction())) { if (!RUN_COMMAND_SERVICE.ACTION_RUN_COMMAND.equals(intent.getAction())) {
errmsg = this.getString(R.string.error_run_command_service_invalid_intent_action, intent.getAction()); errmsg = this.getString(R.string.error_run_command_service_invalid_intent_action, intent.getAction());
executionCommand.setStateFailed(Errno.ERRNO_FAILED.getCode(), errmsg); executionCommand.setStateFailed(Errno.ERRNO_FAILED.getCode(), errmsg);
PluginUtils.processPluginExecutionCommandError(this, LOG_TAG, executionCommand, false); TermuxPluginUtils.processPluginExecutionCommandError(this, LOG_TAG, executionCommand, false);
return stopService(); return stopService();
} }
@@ -110,7 +110,7 @@ public class RunCommandService extends Service {
if (Runner.runnerOf(executionCommand.runner) == null) { if (Runner.runnerOf(executionCommand.runner) == null) {
errmsg = this.getString(R.string.error_run_command_service_invalid_execution_command_runner, executionCommand.runner); errmsg = this.getString(R.string.error_run_command_service_invalid_execution_command_runner, executionCommand.runner);
executionCommand.setStateFailed(Errno.ERRNO_FAILED.getCode(), errmsg); executionCommand.setStateFailed(Errno.ERRNO_FAILED.getCode(), errmsg);
PluginUtils.processPluginExecutionCommandError(this, LOG_TAG, executionCommand, false); TermuxPluginUtils.processPluginExecutionCommandError(this, LOG_TAG, executionCommand, false);
return stopService(); return stopService();
} }
@@ -137,10 +137,10 @@ public class RunCommandService extends Service {
// user knows someone tried to run a command in termux context, since it may be malicious // user knows someone tried to run a command in termux context, since it may be malicious
// app or imported (tasker) plugin project and not the user himself. If a pending intent is // app or imported (tasker) plugin project and not the user himself. If a pending intent is
// also sent, then its creator is also logged and shown. // also sent, then its creator is also logged and shown.
errmsg = PluginUtils.checkIfAllowExternalAppsPolicyIsViolated(this, LOG_TAG); errmsg = TermuxPluginUtils.checkIfAllowExternalAppsPolicyIsViolated(this, LOG_TAG);
if (errmsg != null) { if (errmsg != null) {
executionCommand.setStateFailed(Errno.ERRNO_FAILED.getCode(), errmsg); executionCommand.setStateFailed(Errno.ERRNO_FAILED.getCode(), errmsg);
PluginUtils.processPluginExecutionCommandError(this, LOG_TAG, executionCommand, true); TermuxPluginUtils.processPluginExecutionCommandError(this, LOG_TAG, executionCommand, true);
return stopService(); return stopService();
} }
@@ -150,7 +150,7 @@ public class RunCommandService extends Service {
if (executionCommand.executable == null || executionCommand.executable.isEmpty()) { if (executionCommand.executable == null || executionCommand.executable.isEmpty()) {
errmsg = this.getString(R.string.error_run_command_service_mandatory_extra_missing, RUN_COMMAND_SERVICE.EXTRA_COMMAND_PATH); errmsg = this.getString(R.string.error_run_command_service_mandatory_extra_missing, RUN_COMMAND_SERVICE.EXTRA_COMMAND_PATH);
executionCommand.setStateFailed(Errno.ERRNO_FAILED.getCode(), errmsg); executionCommand.setStateFailed(Errno.ERRNO_FAILED.getCode(), errmsg);
PluginUtils.processPluginExecutionCommandError(this, LOG_TAG, executionCommand, false); TermuxPluginUtils.processPluginExecutionCommandError(this, LOG_TAG, executionCommand, false);
return stopService(); return stopService();
} }
@@ -164,7 +164,7 @@ public class RunCommandService extends Service {
false); false);
if (error != null) { if (error != null) {
executionCommand.setStateFailed(error); executionCommand.setStateFailed(error);
PluginUtils.processPluginExecutionCommandError(this, LOG_TAG, executionCommand, false); TermuxPluginUtils.processPluginExecutionCommandError(this, LOG_TAG, executionCommand, false);
return stopService(); return stopService();
} }
@@ -185,7 +185,7 @@ public class RunCommandService extends Service {
false, true); false, true);
if (error != null) { if (error != null) {
executionCommand.setStateFailed(error); executionCommand.setStateFailed(error);
PluginUtils.processPluginExecutionCommandError(this, LOG_TAG, executionCommand, false); TermuxPluginUtils.processPluginExecutionCommandError(this, LOG_TAG, executionCommand, false);
return stopService(); return stopService();
} }
} }

View File

@@ -13,7 +13,7 @@ import android.os.ParcelFileDescriptor;
import android.provider.MediaStore; import android.provider.MediaStore;
import android.webkit.MimeTypeMap; import android.webkit.MimeTypeMap;
import com.termux.app.utils.PluginUtils; import com.termux.shared.termux.plugins.TermuxPluginUtils;
import com.termux.shared.data.DataUtils; import com.termux.shared.data.DataUtils;
import com.termux.shared.data.IntentUtils; import com.termux.shared.data.IntentUtils;
import com.termux.shared.net.uri.UriUtils; import com.termux.shared.net.uri.UriUtils;
@@ -204,7 +204,7 @@ public class TermuxOpenReceiver extends BroadcastReceiver {
} }
// If TermuxConstants.PROP_ALLOW_EXTERNAL_APPS property to not set to "true", then throw exception // If TermuxConstants.PROP_ALLOW_EXTERNAL_APPS property to not set to "true", then throw exception
String errmsg = PluginUtils.checkIfAllowExternalAppsPolicyIsViolated(getContext(), LOG_TAG); String errmsg = TermuxPluginUtils.checkIfAllowExternalAppsPolicyIsViolated(getContext(), LOG_TAG);
if (errmsg != null) { if (errmsg != null) {
throw new IllegalArgumentException(errmsg); throw new IllegalArgumentException(errmsg);
} }

View File

@@ -20,7 +20,7 @@ import androidx.annotation.Nullable;
import com.termux.R; import com.termux.R;
import com.termux.app.terminal.TermuxTerminalSessionClient; import com.termux.app.terminal.TermuxTerminalSessionClient;
import com.termux.app.utils.PluginUtils; import com.termux.shared.termux.plugins.TermuxPluginUtils;
import com.termux.shared.data.IntentUtils; import com.termux.shared.data.IntentUtils;
import com.termux.shared.net.uri.UriUtils; import com.termux.shared.net.uri.UriUtils;
import com.termux.shared.errors.Errno; import com.termux.shared.errors.Errno;
@@ -286,7 +286,7 @@ public final class TermuxService extends Service implements AppShell.AppShellCli
ExecutionCommand executionCommand = pendingPluginExecutionCommands.get(i); ExecutionCommand executionCommand = pendingPluginExecutionCommands.get(i);
if (!executionCommand.shouldNotProcessResults() && executionCommand.isPluginExecutionCommandWithPendingResult()) { if (!executionCommand.shouldNotProcessResults() && executionCommand.isPluginExecutionCommandWithPendingResult()) {
if (executionCommand.setStateFailed(Errno.ERRNO_CANCELLED.getCode(), this.getString(com.termux.shared.R.string.error_execution_cancelled))) { if (executionCommand.setStateFailed(Errno.ERRNO_CANCELLED.getCode(), this.getString(com.termux.shared.R.string.error_execution_cancelled))) {
PluginUtils.processPluginExecutionCommandResult(this, LOG_TAG, executionCommand); TermuxPluginUtils.processPluginExecutionCommandResult(this, LOG_TAG, executionCommand);
} }
} }
} }
@@ -367,7 +367,7 @@ public final class TermuxService extends Service implements AppShell.AppShellCli
if (Runner.runnerOf(executionCommand.runner) == null) { if (Runner.runnerOf(executionCommand.runner) == null) {
String errmsg = this.getString(R.string.error_termux_service_invalid_execution_command_runner, executionCommand.runner); String errmsg = this.getString(R.string.error_termux_service_invalid_execution_command_runner, executionCommand.runner);
executionCommand.setStateFailed(Errno.ERRNO_FAILED.getCode(), errmsg); executionCommand.setStateFailed(Errno.ERRNO_FAILED.getCode(), errmsg);
PluginUtils.processPluginExecutionCommandError(this, LOG_TAG, executionCommand, false); TermuxPluginUtils.processPluginExecutionCommandError(this, LOG_TAG, executionCommand, false);
return; return;
} }
@@ -411,7 +411,7 @@ public final class TermuxService extends Service implements AppShell.AppShellCli
else { else {
String errmsg = getString(R.string.error_termux_service_unsupported_execution_command_runner, executionCommand.runner); String errmsg = getString(R.string.error_termux_service_unsupported_execution_command_runner, executionCommand.runner);
executionCommand.setStateFailed(Errno.ERRNO_FAILED.getCode(), errmsg); executionCommand.setStateFailed(Errno.ERRNO_FAILED.getCode(), errmsg);
PluginUtils.processPluginExecutionCommandError(this, LOG_TAG, executionCommand, false); TermuxPluginUtils.processPluginExecutionCommandError(this, LOG_TAG, executionCommand, false);
} }
} }
@@ -454,7 +454,7 @@ public final class TermuxService extends Service implements AppShell.AppShellCli
Logger.logError(LOG_TAG, "Failed to execute new TermuxTask command for:\n" + executionCommand.getCommandIdAndLabelLogString()); Logger.logError(LOG_TAG, "Failed to execute new TermuxTask command for:\n" + executionCommand.getCommandIdAndLabelLogString());
// If the execution command was started for a plugin, then process the error // If the execution command was started for a plugin, then process the error
if (executionCommand.isPluginExecutionCommand) if (executionCommand.isPluginExecutionCommand)
PluginUtils.processPluginExecutionCommandError(this, LOG_TAG, executionCommand, false); TermuxPluginUtils.processPluginExecutionCommandError(this, LOG_TAG, executionCommand, false);
else else
Logger.logErrorExtended(LOG_TAG, executionCommand.toString()); Logger.logErrorExtended(LOG_TAG, executionCommand.toString());
return null; return null;
@@ -483,7 +483,7 @@ public final class TermuxService extends Service implements AppShell.AppShellCli
// If the execution command was started for a plugin, then process the results // If the execution command was started for a plugin, then process the results
if (executionCommand != null && executionCommand.isPluginExecutionCommand) if (executionCommand != null && executionCommand.isPluginExecutionCommand)
PluginUtils.processPluginExecutionCommandResult(this, LOG_TAG, executionCommand); TermuxPluginUtils.processPluginExecutionCommandResult(this, LOG_TAG, executionCommand);
mTermuxTasks.remove(termuxTask); mTermuxTasks.remove(termuxTask);
} }
@@ -517,7 +517,7 @@ public final class TermuxService extends Service implements AppShell.AppShellCli
if (DataUtils.isNullOrEmpty(executionCommand.sessionName)) { if (DataUtils.isNullOrEmpty(executionCommand.sessionName)) {
String errmsg = getString(R.string.error_termux_service_execution_command_session_name_unset, executionCommand.sessionCreateMode); String errmsg = getString(R.string.error_termux_service_execution_command_session_name_unset, executionCommand.sessionCreateMode);
executionCommand.setStateFailed(Errno.ERRNO_FAILED.getCode(), errmsg); executionCommand.setStateFailed(Errno.ERRNO_FAILED.getCode(), errmsg);
PluginUtils.processPluginExecutionCommandError(this, LOG_TAG, executionCommand, false); TermuxPluginUtils.processPluginExecutionCommandError(this, LOG_TAG, executionCommand, false);
return; return;
} else { } else {
newTermuxSession = getTermuxSessionForName(executionCommand.sessionName); newTermuxSession = getTermuxSessionForName(executionCommand.sessionName);
@@ -527,7 +527,7 @@ public final class TermuxService extends Service implements AppShell.AppShellCli
else { else {
String errmsg = getString(R.string.error_termux_service_unsupported_execution_command_session_create_mode, executionCommand.sessionCreateMode); String errmsg = getString(R.string.error_termux_service_unsupported_execution_command_session_create_mode, executionCommand.sessionCreateMode);
executionCommand.setStateFailed(Errno.ERRNO_FAILED.getCode(), errmsg); executionCommand.setStateFailed(Errno.ERRNO_FAILED.getCode(), errmsg);
PluginUtils.processPluginExecutionCommandError(this, LOG_TAG, executionCommand, false); TermuxPluginUtils.processPluginExecutionCommandError(this, LOG_TAG, executionCommand, false);
return; return;
} }
@@ -575,7 +575,7 @@ public final class TermuxService extends Service implements AppShell.AppShellCli
Logger.logError(LOG_TAG, "Failed to execute new TermuxSession command for:\n" + executionCommand.getCommandIdAndLabelLogString()); Logger.logError(LOG_TAG, "Failed to execute new TermuxSession command for:\n" + executionCommand.getCommandIdAndLabelLogString());
// If the execution command was started for a plugin, then process the error // If the execution command was started for a plugin, then process the error
if (executionCommand.isPluginExecutionCommand) if (executionCommand.isPluginExecutionCommand)
PluginUtils.processPluginExecutionCommandError(this, LOG_TAG, executionCommand, false); TermuxPluginUtils.processPluginExecutionCommandError(this, LOG_TAG, executionCommand, false);
else else
Logger.logErrorExtended(LOG_TAG, executionCommand.toString()); Logger.logErrorExtended(LOG_TAG, executionCommand.toString());
return null; return null;
@@ -621,7 +621,7 @@ public final class TermuxService extends Service implements AppShell.AppShellCli
// If the execution command was started for a plugin, then process the results // If the execution command was started for a plugin, then process the results
if (executionCommand != null && executionCommand.isPluginExecutionCommand) if (executionCommand != null && executionCommand.isPluginExecutionCommand)
PluginUtils.processPluginExecutionCommandResult(this, LOG_TAG, executionCommand); TermuxPluginUtils.processPluginExecutionCommandResult(this, LOG_TAG, executionCommand);
mTermuxSessions.remove(termuxSession); mTermuxSessions.remove(termuxSession);

View File

@@ -3,7 +3,6 @@ package com.termux.app.models;
public enum UserAction { public enum UserAction {
ABOUT("about"), ABOUT("about"),
PLUGIN_EXECUTION_COMMAND("plugin execution command"),
REPORT_ISSUE_FROM_TRANSCRIPT("report issue from transcript"); REPORT_ISSUE_FROM_TRANSCRIPT("report issue from transcript");
private final String name; private final String name;

View File

@@ -121,8 +121,6 @@
<!-- Miscellaneous --> <!-- Miscellaneous -->
<string name="error_allow_external_apps_ungranted">%1$s requires `allow-external-apps`
property to be set to `true` in `%2$s` file.</string>
<string name="error_termux_service_start_failed_general">Failed to start TermuxService. Check logcat for exception message.</string> <string name="error_termux_service_start_failed_general">Failed to start TermuxService. Check logcat for exception message.</string>
<string name="error_termux_service_start_failed_bg">Failed to start TermuxService while app is in background due to android bg restrictions.</string> <string name="error_termux_service_start_failed_bg">Failed to start TermuxService while app is in background due to android bg restrictions.</string>

View File

@@ -2,7 +2,8 @@ package com.termux.shared.termux.models;
public enum UserAction { public enum UserAction {
CRASH_REPORT("crash report"); CRASH_REPORT("crash report"),
PLUGIN_EXECUTION_COMMAND("plugin execution command");
private final String name; private final String name;

View File

@@ -1,14 +1,15 @@
package com.termux.app.utils; package com.termux.shared.termux.plugins;
import android.app.Notification; import android.app.Notification;
import android.app.NotificationManager; import android.app.NotificationManager;
import android.app.PendingIntent; import android.app.PendingIntent;
import android.content.Context; import android.content.Context;
import android.graphics.drawable.Icon;
import android.os.Environment; import android.os.Environment;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import com.termux.R; import com.termux.shared.R;
import com.termux.shared.activities.ReportActivity; import com.termux.shared.activities.ReportActivity;
import com.termux.shared.file.FileUtils; import com.termux.shared.file.FileUtils;
import com.termux.shared.termux.file.TermuxFileUtils; import com.termux.shared.termux.file.TermuxFileUtils;
@@ -17,6 +18,7 @@ import com.termux.shared.shell.command.result.ResultData;
import com.termux.shared.errors.Errno; import com.termux.shared.errors.Errno;
import com.termux.shared.errors.Error; import com.termux.shared.errors.Error;
import com.termux.shared.notification.NotificationUtils; import com.termux.shared.notification.NotificationUtils;
import com.termux.shared.termux.models.UserAction;
import com.termux.shared.termux.notification.TermuxNotificationUtils; import com.termux.shared.termux.notification.TermuxNotificationUtils;
import com.termux.shared.termux.settings.preferences.TermuxPreferenceConstants; import com.termux.shared.termux.settings.preferences.TermuxPreferenceConstants;
import com.termux.shared.shell.command.result.ResultSender; import com.termux.shared.shell.command.result.ResultSender;
@@ -30,14 +32,13 @@ import com.termux.shared.termux.settings.preferences.TermuxPreferenceConstants.T
import com.termux.shared.models.ReportInfo; import com.termux.shared.models.ReportInfo;
import com.termux.shared.termux.settings.properties.TermuxAppSharedProperties; import com.termux.shared.termux.settings.properties.TermuxAppSharedProperties;
import com.termux.shared.shell.command.ExecutionCommand; import com.termux.shared.shell.command.ExecutionCommand;
import com.termux.app.models.UserAction;
import com.termux.shared.data.DataUtils; import com.termux.shared.data.DataUtils;
import com.termux.shared.markdown.MarkdownUtils; import com.termux.shared.markdown.MarkdownUtils;
import com.termux.shared.termux.TermuxUtils; import com.termux.shared.termux.TermuxUtils;
public class PluginUtils { public class TermuxPluginUtils {
private static final String LOG_TAG = "PluginUtils"; private static final String LOG_TAG = "TermuxPluginUtils";
/** /**
* Process {@link ExecutionCommand} result. * Process {@link ExecutionCommand} result.
@@ -92,9 +93,8 @@ public class PluginUtils {
sendPluginCommandErrorNotification(context, logTag, null, sendPluginCommandErrorNotification(context, logTag, null,
ResultData.getErrorsListMinimalString(resultData), ResultData.getErrorsListMinimalString(resultData),
ExecutionCommand.getExecutionCommandMarkdownString(executionCommand), ExecutionCommand.getExecutionCommandMarkdownString(executionCommand),
false, true, TermuxUtils.AppInfoMode.TERMUX_AND_CALLING_PACKAGE, false, true, TermuxUtils.AppInfoMode.TERMUX_AND_CALLING_PACKAGE,true,
executionCommand.resultConfig.resultPendingIntent != null ? executionCommand.resultConfig.resultPendingIntent.getCreatorPackage(): null, executionCommand.resultConfig.resultPendingIntent != null ? executionCommand.resultConfig.resultPendingIntent.getCreatorPackage(): null);
true);
} }
} }
@@ -173,9 +173,8 @@ public class PluginUtils {
sendPluginCommandErrorNotification(context, logTag, null, sendPluginCommandErrorNotification(context, logTag, null,
ResultData.getErrorsListMinimalString(resultData), ResultData.getErrorsListMinimalString(resultData),
ExecutionCommand.getExecutionCommandMarkdownString(executionCommand), ExecutionCommand.getExecutionCommandMarkdownString(executionCommand),
forceNotification, true, TermuxUtils.AppInfoMode.TERMUX_AND_CALLING_PACKAGE, forceNotification, true, TermuxUtils.AppInfoMode.TERMUX_AND_CALLING_PACKAGE, true,
executionCommand.resultConfig.resultPendingIntent != null ? executionCommand.resultConfig.resultPendingIntent.getCreatorPackage(): null, executionCommand.resultConfig.resultPendingIntent != null ? executionCommand.resultConfig.resultPendingIntent.getCreatorPackage(): null);
true);
} }
/** Set variables which will be used by {@link ResultSender#sendCommandResultData(Context, String, String, ResultConfig, ResultData, boolean)} /** Set variables which will be used by {@link ResultSender#sendCommandResultData(Context, String, String, ResultConfig, ResultData, boolean)}
@@ -208,11 +207,75 @@ public class PluginUtils {
/** /**
* Send an error notification for {@link TermuxConstants#TERMUX_PLUGIN_COMMAND_ERRORS_NOTIFICATION_CHANNEL_ID} * Send a plugin error report notification for {@link TermuxConstants#TERMUX_PLUGIN_COMMAND_ERRORS_NOTIFICATION_CHANNEL_ID}
* and {@link TermuxConstants#TERMUX_PLUGIN_COMMAND_ERRORS_NOTIFICATION_CHANNEL_NAME}. * and {@link TermuxConstants#TERMUX_PLUGIN_COMMAND_ERRORS_NOTIFICATION_CHANNEL_NAME}.
* *
* @param context The {@link Context} for operations. * @param currentPackageContext The {@link Context} of current package.
* @param logTag The log tag to use for logging.
* @param title The title for the error report and notification.
* @param message The message for the error report.
* @param throwable The {@link Throwable} for the error report.
*/
public static void sendPluginCommandErrorNotification(final Context currentPackageContext, String logTag,
CharSequence title, String message, Throwable throwable) {
sendPluginCommandErrorNotification(currentPackageContext, logTag,
title, message,
MarkdownUtils.getMarkdownCodeForString(Logger.getMessageAndStackTraceString(message, throwable), true),
false, false, true);
}
/**
* Send a plugin error report notification for {@link TermuxConstants#TERMUX_PLUGIN_COMMAND_ERRORS_NOTIFICATION_CHANNEL_ID}
* and {@link TermuxConstants#TERMUX_PLUGIN_COMMAND_ERRORS_NOTIFICATION_CHANNEL_NAME}.
*
* @param currentPackageContext The {@link Context} of current package.
* @param logTag The log tag to use for logging.
* @param title The title for the error report and notification.
* @param notificationTextString The text of the notification.
* @param message The message for the error report.
*/
public static void sendPluginCommandErrorNotification(final Context currentPackageContext, String logTag,
CharSequence title, String notificationTextString,
String message) {
sendPluginCommandErrorNotification(currentPackageContext, logTag,
title, notificationTextString, message,
false, false, true);
}
/**
* Send a plugin error report notification for {@link TermuxConstants#TERMUX_PLUGIN_COMMAND_ERRORS_NOTIFICATION_CHANNEL_ID}
* and {@link TermuxConstants#TERMUX_PLUGIN_COMMAND_ERRORS_NOTIFICATION_CHANNEL_NAME}.
*
* @param currentPackageContext The {@link Context} of current package.
* @param logTag The log tag to use for logging.
* @param title The title for the error report and notification.
* @param notificationTextString The text of the notification.
* @param message The message for the error report.
* @param forceNotification If set to {@code true}, then a notification will be shown
* regardless of if pending intent is {@code null} or
* {@link TermuxPreferenceConstants.TERMUX_APP#KEY_PLUGIN_ERROR_NOTIFICATIONS_ENABLED}
* is {@code false}.
* @param showToast If set to {@code true}, then a toast will be shown for {@code notificationTextString}.
* @param addDeviceInfo If set to {@code true}, then device info should be appended to the message.
*/
public static void sendPluginCommandErrorNotification(final Context currentPackageContext, String logTag,
CharSequence title, String notificationTextString,
String message, boolean forceNotification,
boolean showToast,
boolean addDeviceInfo) {
sendPluginCommandErrorNotification(currentPackageContext, logTag,
title, notificationTextString, "## " + title + "\n\n" + message + "\n\n",
forceNotification, showToast, TermuxUtils.AppInfoMode.TERMUX_AND_PLUGIN_PACKAGE, addDeviceInfo, null);
}
/**
* Send a plugin error notification for {@link TermuxConstants#TERMUX_PLUGIN_COMMAND_ERRORS_NOTIFICATION_CHANNEL_ID}
* and {@link TermuxConstants#TERMUX_PLUGIN_COMMAND_ERRORS_NOTIFICATION_CHANNEL_NAME}.
*
* @param currentPackageContext The {@link Context} of current package.
* @param logTag The log tag to use for logging.
* @param title The title for the error report and notification. * @param title The title for the error report and notification.
* @param notificationTextString The text of the notification. * @param notificationTextString The text of the notification.
* @param message The message for the error report. * @param message The message for the error report.
@@ -223,21 +286,30 @@ public class PluginUtils {
* @param showToast If set to {@code true}, then a toast will be shown for {@code notificationTextString}. * @param showToast If set to {@code true}, then a toast will be shown for {@code notificationTextString}.
* @param appInfoMode The {@link TermuxUtils.AppInfoMode} to use to add app info to the message. * @param appInfoMode The {@link TermuxUtils.AppInfoMode} to use to add app info to the message.
* Set to {@code null} if app info should not be appended to the message. * Set to {@code null} if app info should not be appended to the message.
* @param addDeviceInfo If set to {@code true}, then device info should be appended to the message.
* @param callingPackageName The optional package name of the app for which the plugin command * @param callingPackageName The optional package name of the app for which the plugin command
* was run. * was run.
* @param addDeviceInfo If set to {@code true}, then device info should be appended to the message.
*/ */
public static void sendPluginCommandErrorNotification(Context context, String logTag, public static void sendPluginCommandErrorNotification(Context currentPackageContext, String logTag,
CharSequence title, CharSequence title,
String notificationTextString, String notificationTextString,
String message, boolean forceNotification, String message, boolean forceNotification,
boolean showToast, boolean showToast,
TermuxUtils.AppInfoMode appInfoMode, TermuxUtils.AppInfoMode appInfoMode,
String callingPackageName, boolean addDeviceInfo,
boolean addDeviceInfo) { String callingPackageName) {
if (context == null) return; // Note: Do not change currentPackageContext or termuxPackageContext passed to functions or things will break
TermuxAppSharedPreferences preferences = TermuxAppSharedPreferences.build(context); if (currentPackageContext == null) return;
String currentPackageName = currentPackageContext.getPackageName();
final Context termuxPackageContext = TermuxUtils.getTermuxPackageContext(currentPackageContext);
if (termuxPackageContext == null) {
Logger.logWarn(LOG_TAG, "Ignoring call to sendPluginCommandErrorNotification() since failed to get \"" + TermuxConstants.TERMUX_PACKAGE_NAME + "\" package context from \"" + currentPackageName + "\" context");
return;
}
TermuxAppSharedPreferences preferences = TermuxAppSharedPreferences.build(termuxPackageContext);
if (preferences == null) return; if (preferences == null) return;
// If user has disabled notifications for plugin commands, then just return // If user has disabled notifications for plugin commands, then just return
@@ -247,7 +319,7 @@ public class PluginUtils {
logTag = DataUtils.getDefaultIfNull(logTag, LOG_TAG); logTag = DataUtils.getDefaultIfNull(logTag, LOG_TAG);
if (showToast) if (showToast)
Logger.showToast(context, notificationTextString, true); Logger.showToast(currentPackageContext, notificationTextString, true);
// Send a notification to show the error which when clicked will open the ReportActivity // Send a notification to show the error which when clicked will open the ReportActivity
// to show the details of the error // to show the details of the error
@@ -259,48 +331,49 @@ public class PluginUtils {
StringBuilder reportString = new StringBuilder(message); StringBuilder reportString = new StringBuilder(message);
if (appInfoMode != null) if (appInfoMode != null)
reportString.append("\n\n").append(TermuxUtils.getAppInfoMarkdownString(context, appInfoMode, callingPackageName)); reportString.append("\n\n").append(TermuxUtils.getAppInfoMarkdownString(currentPackageContext, appInfoMode,
callingPackageName != null ? callingPackageName : currentPackageName));
if (addDeviceInfo) if (addDeviceInfo)
reportString.append("\n\n").append(AndroidUtils.getDeviceInfoMarkdownString(context)); reportString.append("\n\n").append(AndroidUtils.getDeviceInfoMarkdownString(currentPackageContext));
String userActionName = UserAction.PLUGIN_EXECUTION_COMMAND.getName(); String userActionName = UserAction.PLUGIN_EXECUTION_COMMAND.getName();
ReportInfo reportInfo = new ReportInfo(userActionName, logTag, title.toString()); ReportInfo reportInfo = new ReportInfo(userActionName, logTag, title.toString());
reportInfo.setReportString(reportString.toString()); reportInfo.setReportString(reportString.toString());
reportInfo.setReportStringSuffix("\n\n" + TermuxUtils.getReportIssueMarkdownString(context)); reportInfo.setReportStringSuffix("\n\n" + TermuxUtils.getReportIssueMarkdownString(currentPackageContext));
reportInfo.setAddReportInfoHeaderToMarkdown(true); reportInfo.setAddReportInfoHeaderToMarkdown(true);
reportInfo.setReportSaveFileLabelAndPath(userActionName, reportInfo.setReportSaveFileLabelAndPath(userActionName,
Environment.getExternalStorageDirectory() + "/" + Environment.getExternalStorageDirectory() + "/" +
FileUtils.sanitizeFileName(TermuxConstants.TERMUX_APP_NAME + "-" + userActionName + ".log", true, true)); FileUtils.sanitizeFileName(TermuxConstants.TERMUX_APP_NAME + "-" + userActionName + ".log", true, true));
ReportActivity.NewInstanceResult result = ReportActivity.newInstance(context, reportInfo); ReportActivity.NewInstanceResult result = ReportActivity.newInstance(termuxPackageContext, reportInfo);
if (result.contentIntent == null) return; if (result.contentIntent == null) return;
// Must ensure result code for PendingIntents and id for notification are unique otherwise will override previous // Must ensure result code for PendingIntents and id for notification are unique otherwise will override previous
int nextNotificationId = TermuxNotificationUtils.getNextNotificationId(context); int nextNotificationId = TermuxNotificationUtils.getNextNotificationId(termuxPackageContext);
PendingIntent contentIntent = PendingIntent.getActivity(context, nextNotificationId, result.contentIntent, PendingIntent.FLAG_UPDATE_CURRENT); PendingIntent contentIntent = PendingIntent.getActivity(termuxPackageContext, nextNotificationId, result.contentIntent, PendingIntent.FLAG_UPDATE_CURRENT);
PendingIntent deleteIntent = null; PendingIntent deleteIntent = null;
if (result.deleteIntent != null) if (result.deleteIntent != null)
deleteIntent = PendingIntent.getBroadcast(context, nextNotificationId, result.deleteIntent, PendingIntent.FLAG_UPDATE_CURRENT); deleteIntent = PendingIntent.getBroadcast(termuxPackageContext, nextNotificationId, result.deleteIntent, PendingIntent.FLAG_UPDATE_CURRENT);
// Setup the notification channel if not already set up // Setup the notification channel if not already set up
setupPluginCommandErrorsNotificationChannel(context); setupPluginCommandErrorsNotificationChannel(termuxPackageContext);
// Use markdown in notification // Use markdown in notification
CharSequence notificationTextCharSequence = MarkdownUtils.getSpannedMarkdownText(context, notificationTextString); CharSequence notificationTextCharSequence = MarkdownUtils.getSpannedMarkdownText(termuxPackageContext, notificationTextString);
//CharSequence notificationTextCharSequence = notificationTextString; //CharSequence notificationTextCharSequence = notificationTextString;
// Build the notification // Build the notification
Notification.Builder builder = getPluginCommandErrorsNotificationBuilder(context, title, Notification.Builder builder = getPluginCommandErrorsNotificationBuilder(currentPackageContext, termuxPackageContext,
notificationTextCharSequence, notificationTextCharSequence, contentIntent, deleteIntent, title, notificationTextCharSequence, notificationTextCharSequence, contentIntent, deleteIntent,
NotificationUtils.NOTIFICATION_MODE_VIBRATE); NotificationUtils.NOTIFICATION_MODE_VIBRATE);
if (builder == null) return; if (builder == null) return;
// Send the notification // Send the notification
NotificationManager notificationManager = NotificationUtils.getNotificationManager(context); NotificationManager notificationManager = NotificationUtils.getNotificationManager(termuxPackageContext);
if (notificationManager != null) if (notificationManager != null)
notificationManager.notify(nextNotificationId, builder.build()); notificationManager.notify(nextNotificationId, builder.build());
} }
@@ -309,7 +382,8 @@ public class PluginUtils {
* Get {@link Notification.Builder} for {@link TermuxConstants#TERMUX_PLUGIN_COMMAND_ERRORS_NOTIFICATION_CHANNEL_ID} * Get {@link Notification.Builder} for {@link TermuxConstants#TERMUX_PLUGIN_COMMAND_ERRORS_NOTIFICATION_CHANNEL_ID}
* and {@link TermuxConstants#TERMUX_PLUGIN_COMMAND_ERRORS_NOTIFICATION_CHANNEL_NAME}. * and {@link TermuxConstants#TERMUX_PLUGIN_COMMAND_ERRORS_NOTIFICATION_CHANNEL_NAME}.
* *
* @param context The {@link Context} for operations. * @param currentPackageContext The {@link Context} of current package.
* @param termuxPackageContext The {@link Context} of termux package.
* @param title The title for the notification. * @param title The title for the notification.
* @param notificationText The second line text of the notification. * @param notificationText The second line text of the notification.
* @param notificationBigText The full text of the notification that may optionally be styled. * @param notificationBigText The full text of the notification that may optionally be styled.
@@ -319,11 +393,15 @@ public class PluginUtils {
* @return Returns the {@link Notification.Builder}. * @return Returns the {@link Notification.Builder}.
*/ */
@Nullable @Nullable
public static Notification.Builder getPluginCommandErrorsNotificationBuilder( public static Notification.Builder getPluginCommandErrorsNotificationBuilder(final Context currentPackageContext,
final Context context, final CharSequence title, final CharSequence notificationText, final Context termuxPackageContext,
final CharSequence notificationBigText, final PendingIntent contentIntent, final PendingIntent deleteIntent, final int notificationMode) { final CharSequence title,
final CharSequence notificationText,
Notification.Builder builder = NotificationUtils.geNotificationBuilder(context, final CharSequence notificationBigText,
final PendingIntent contentIntent,
final PendingIntent deleteIntent,
final int notificationMode) {
Notification.Builder builder = NotificationUtils.geNotificationBuilder(termuxPackageContext,
TermuxConstants.TERMUX_PLUGIN_COMMAND_ERRORS_NOTIFICATION_CHANNEL_ID, Notification.PRIORITY_HIGH, TermuxConstants.TERMUX_PLUGIN_COMMAND_ERRORS_NOTIFICATION_CHANNEL_ID, Notification.PRIORITY_HIGH,
title, notificationText, notificationBigText, contentIntent, deleteIntent, notificationMode); title, notificationText, notificationBigText, contentIntent, deleteIntent, notificationMode);
@@ -333,7 +411,7 @@ public class PluginUtils {
builder.setShowWhen(true); builder.setShowWhen(true);
// Set notification icon // Set notification icon
builder.setSmallIcon(R.drawable.ic_error_notification); builder.setSmallIcon(Icon.createWithResource(currentPackageContext, R.drawable.ic_error_notification));
// Set background color for small notification icon // Set background color for small notification icon
builder.setColor(0xFF607D8B); builder.setColor(0xFF607D8B);

View File

@@ -39,6 +39,12 @@
<!-- TermuxPluginUtils -->
<string name="error_allow_external_apps_ungranted">%1$s requires `allow-external-apps`
property to be set to `true` in `%2$s` file.</string>
<!-- ReportActivity --> <!-- ReportActivity -->
<string name="title_report_text">Report Text</string> <string name="title_report_text">Report Text</string>
<string name="msg_report_truncated">**Report Truncated**\n\nReport is too large to view here. <string name="msg_report_truncated">**Report Truncated**\n\nReport is too large to view here.