Skip to content

Commit a35ead0

Browse files
Add Termux result callback handling and output status streaming
1 parent 935e323 commit a35ead0

1 file changed

Lines changed: 72 additions & 0 deletions

File tree

app/src/main/kotlin/com/google/ai/sample/ScreenOperatorAccessibilityService.kt

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import android.accessibilityservice.GestureDescription
77
import android.content.ComponentName
88
import android.content.Context
99
import android.content.Intent
10+
import android.app.PendingIntent
1011
import android.content.pm.PackageManager
1112
import android.content.pm.ResolveInfo
1213
import android.graphics.Bitmap
@@ -562,6 +563,21 @@ class ScreenOperatorAccessibilityService : AccessibilityService() {
562563
"Resolved Termux RunCommandService=${resolvedService.serviceInfo?.name}, app=${resolvedService.serviceInfo?.packageName}"
563564
)
564565

566+
val callbackAction = "com.google.ai.sample.TERMUX_COMMAND_RESULT"
567+
val callbackIntent = Intent(callbackAction).apply {
568+
`package` = packageName
569+
}
570+
val callbackFlags = PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_MUTABLE
571+
val pendingResultIntent = PendingIntent.getBroadcast(applicationContext, 7001, callbackIntent, callbackFlags)
572+
573+
val callbackReceiver = TermuxResultReceiver(applicationContext)
574+
try {
575+
registerReceiver(callbackReceiver, android.content.IntentFilter(callbackAction), Context.RECEIVER_NOT_EXPORTED)
576+
Log.i(TAG, "Registered Termux result receiver for action=$callbackAction")
577+
} catch (t: Throwable) {
578+
Log.e(TAG, "Failed to register Termux result receiver", t)
579+
}
580+
565581
val intent = Intent("com.termux.RUN_COMMAND").apply {
566582
`package` = termuxPackage
567583
setClassName(termuxPackage, runCommandServiceClass)
@@ -571,6 +587,10 @@ class ScreenOperatorAccessibilityService : AccessibilityService() {
571587
putExtra("com.termux.RUN_COMMAND_BACKGROUND", true)
572588
putExtra("com.termux.RUN_COMMAND_SESSION_ACTION", 0)
573589
putExtra("com.termux.RUN_COMMAND_RUNNER", "app-shell")
590+
putExtra("com.termux.RUN_COMMAND_PENDING_INTENT", pendingResultIntent)
591+
putExtra("com.termux.RUN_COMMAND_BACKGROUND_CUSTOM_LOG_LEVEL", 0)
592+
putExtra("com.termux.RUN_COMMAND_RETURN_STDOUT", true)
593+
putExtra("com.termux.RUN_COMMAND_RETURN_STDERR", true)
574594
}
575595

576596
Log.i(
@@ -594,6 +614,58 @@ class ScreenOperatorAccessibilityService : AccessibilityService() {
594614
}
595615
}
596616

617+
private class TermuxResultReceiver(private val appContext: Context) : android.content.BroadcastReceiver() {
618+
override fun onReceive(context: Context?, intent: Intent?) {
619+
if (intent == null) {
620+
Log.w(TAG, "Termux result receiver invoked with null intent")
621+
return
622+
}
623+
val resultBundle = intent.getBundleExtra("com.termux.app.extra.TERMUX_SERVICE.EXTRA_PLUGIN_RESULT_BUNDLE")
624+
if (resultBundle == null) {
625+
Log.w(TAG, "Termux result bundle missing; available extras=${intent.extras?.keySet()?.joinToString()}")
626+
return
627+
}
628+
629+
val stdout = resultBundle.getString("com.termux.app.extra.TERMUX_SERVICE.EXTRA_PLUGIN_RESULT_BUNDLE_STDOUT", "") ?: ""
630+
val stderr = resultBundle.getString("com.termux.app.extra.TERMUX_SERVICE.EXTRA_PLUGIN_RESULT_BUNDLE_STDERR", "") ?: ""
631+
val exitCode = resultBundle.getInt("com.termux.app.extra.TERMUX_SERVICE.EXTRA_PLUGIN_RESULT_BUNDLE_EXIT_CODE", Int.MIN_VALUE)
632+
633+
Log.i(TAG, "Termux result received: exitCode=$exitCode stdoutLen=${stdout.length} stderrLen=${stderr.length}")
634+
635+
val combined = buildString {
636+
append("Termux finished (exit=")
637+
append(exitCode)
638+
append(")")
639+
if (stdout.isNotBlank()) {
640+
append("\nstdout:\n")
641+
append(stdout)
642+
}
643+
if (stderr.isNotBlank()) {
644+
append("\nstderr:\n")
645+
append(stderr)
646+
}
647+
}
648+
649+
mainHandler.post {
650+
MainActivity.getInstance()?.updateStatusMessage("Termux stream start", false)
651+
}
652+
combined.lineSequence().forEachIndexed { idx, line ->
653+
val framed = "Termux[$idx]: $line"
654+
Log.d(TAG, framed)
655+
mainHandler.post {
656+
MainActivity.getInstance()?.updateStatusMessage(framed, false)
657+
}
658+
}
659+
660+
try {
661+
appContext.unregisterReceiver(this)
662+
Log.i(TAG, "Termux result receiver unregistered")
663+
} catch (t: Throwable) {
664+
Log.w(TAG, "Failed to unregister Termux result receiver", t)
665+
}
666+
}
667+
}
668+
597669

598670
private fun processCommandQueue() {
599671
if (!commandQueue.tryAcquireProcessing()) {

0 commit comments

Comments
 (0)