ARTICLE AD BOX
I have an Android app and need to run termux commands from it and get results. I have this code in <package>/Utils/TermuxUtils.java
package com.example.myapplication3.Utils; import android.app.PendingIntent; import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; import android.util.Log; import com.termux.shared.termux.TermuxConstants; public class TermuxUtils { public static final String PERMISSION = "com.termux.permission.RUN_COMMAND"; public static void exec(Context context, String command, String[] args, String path) { if (context.checkSelfPermission(PERMISSION) != PackageManager.PERMISSION_GRANTED) { Log.d("termux_permission", "permission not granted"); return; } Intent intent = new Intent(); intent.setClassName("com.termux", "com.termux.app.RunCommandService"); intent.setAction(TermuxConstants.TERMUX_APP.RUN_COMMAND_SERVICE.ACTION_RUN_COMMAND); intent.putExtra(TermuxConstants.TERMUX_APP.RUN_COMMAND_SERVICE.EXTRA_COMMAND_PATH, TermuxConstants.TERMUX_FILES_DIR_PATH + "/usr/bin/" + command); intent.putExtra(TermuxConstants.TERMUX_APP.RUN_COMMAND_SERVICE.EXTRA_ARGUMENTS, args); intent.putExtra(TermuxConstants.TERMUX_APP.RUN_COMMAND_SERVICE.EXTRA_WORKDIR, path); intent.putExtra(TermuxConstants.TERMUX_APP.RUN_COMMAND_SERVICE.EXTRA_BACKGROUND, true); int execId = TermuxPluginResultsService.getNextExecutionId(); Intent pluginResultsService = new Intent(context, TermuxPluginResultsService.class); pluginResultsService.putExtra(TermuxPluginResultsService.EXTRA_EXECUTION_ID, execId); PendingIntent pendingIntent = PendingIntent.getService(context, execId, pluginResultsService, PendingIntent.FLAG_ONE_SHOT | PendingIntent.FLAG_IMMUTABLE); intent.putExtra(TermuxConstants.TERMUX_APP.RUN_COMMAND_SERVICE.EXTRA_PENDING_INTENT, pendingIntent); context.startForegroundService(intent); } public static void exec(Context context, String command, String path) { exec(context, "bash", new String[]{"-c", command}, path); } public static void exec(Context context, String command) { exec(context, command, TermuxConstants.TERMUX_HOME_DIR_PATH); } }And this in <package>/Utils/TermuxPluginResultsService:
package com.example.myapplication3.Utils; import android.app.IntentService; import android.content.Intent; import android.os.Bundle; import android.util.Log; import androidx.annotation.Nullable; import com.termux.shared.termux.TermuxConstants; public class TermuxPluginResultsService extends IntentService { public static final String EXTRA_EXECUTION_ID = "execution_id"; public static final String SERVICE_LABEL = "PluginResultsService"; private static int EXECUTION_ID = 1000; public TermuxPluginResultsService() { super(SERVICE_LABEL); } @Override protected void onHandleIntent(@Nullable Intent intent) { Log.d("termux_handleIntent", String.valueOf(intent == null)); if (intent == null) return; if (intent.getExtras() != null) { intent.getExtras().setClassLoader(getClassLoader()); } Bundle bundle = intent.getBundleExtra(TermuxConstants.TERMUX_APP.TERMUX_SERVICE.EXTRA_PLUGIN_RESULT_BUNDLE); Log.d("termux_bundleNull", String.valueOf(bundle == null)); if (bundle == null) return; bundle.setClassLoader(getClassLoader()); int execId = intent.getIntExtra(EXTRA_EXECUTION_ID, 0); // Log.d("termux_execId", String.valueOf(execId)); String stdout = bundle.getString(TermuxConstants.TERMUX_APP.TERMUX_SERVICE.EXTRA_PLUGIN_RESULT_BUNDLE_STDOUT); String stderr = bundle.getString(TermuxConstants.TERMUX_APP.TERMUX_SERVICE.EXTRA_PLUGIN_RESULT_BUNDLE_STDERR); int exitCode = bundle.getInt(TermuxConstants.TERMUX_APP.TERMUX_SERVICE.EXTRA_PLUGIN_RESULT_BUNDLE_EXIT_CODE); Log.d("termux_exit_code", String.valueOf(exitCode)); Log.d("termux_stdout", stdout); Log.d("termux_stderr", stderr); } public static synchronized int getNextExecutionId() { return EXECUTION_ID++; } }I am receiving null instead of result bundle (so, have true in termux_bundleNull tag). Don't know how to fix it. Read https://github.com/termux/termux-app/wiki/RUN_COMMAND-Intent#RUN_COMMAND-Intent-Result-Extras to write this.
In example app I run just TermuxUtils.exec(this, "echo HelloWorld") (in real app need some git commands).
Tried reading all extras in onHandleIntent by this code
Bundle allExtras = intent.getExtras(); if (allExtras != null) { for (String key : allExtras.keySet()) { Object value = allExtras.get(key); Log.d("termux_extra_key", "Key: " + key + ", Value type: " + (value != null ? value.getClass().getSimpleName() : "null")); if (value instanceof Bundle) { Bundle innerBundle = (Bundle) value; for (String innerKey : innerBundle.keySet()) { Log.d("termux_bundle_content", " " + innerKey + " = " + innerBundle.get(innerKey)); } } } }but all I receive is Key: execution_id, Value type: Integer - only the extra that I've set myself and nothing else, that may contain command result.
Also tried adding additional extras
intent.putExtra("com.termux.RUN_COMMAND_RETURN_STDOUT", true); intent.putExtra("com.termux.RUN_COMMAND_RETURN_STDERR", true); intent.putExtra("com.termux.RUN_COMMAND_RETURN_EXIT_CODE", true); intent.putExtra("return_stdout", true); intent.putExtra("return_stderr", true); intent.putExtra("return_exit_code", true);to intent in TermuxUtils.exec, but this also didn't helped.
By the way, the code worked in my app that was written using old android.support libraries, and after migrating project to androidX it fails. What may be the problem?
