From 4e88f0e5c408bde919b0f21fa007efa23c035c6b Mon Sep 17 00:00:00 2001 From: jiangchen <1703935164@qq.com> Date: Tue, 1 Sep 2026 19:04:19 +0800 Subject: [PATCH] feat: add phone CommandActivity (send session.prompt + stream events) --- app/src/main/AndroidManifest.xml | 3 + .../com/dshwatch/app/CommandActivity.java | 115 ++++++++++++++++++ .../java/com/dshwatch/app/MainActivity.java | 8 ++ app/src/main/res/layout/activity_command.xml | 54 ++++++++ app/src/main/res/layout/activity_main.xml | 7 ++ app/src/main/res/values/strings.xml | 1 + 6 files changed, 188 insertions(+) create mode 100644 app/src/main/java/com/dshwatch/app/CommandActivity.java create mode 100644 app/src/main/res/layout/activity_command.xml diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index aaa2688..a7bfdc0 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -22,5 +22,8 @@ + diff --git a/app/src/main/java/com/dshwatch/app/CommandActivity.java b/app/src/main/java/com/dshwatch/app/CommandActivity.java new file mode 100644 index 0000000..3cbdfa2 --- /dev/null +++ b/app/src/main/java/com/dshwatch/app/CommandActivity.java @@ -0,0 +1,115 @@ +package com.dshwatch.app; + +import android.os.Bundle; +import android.view.View; +import android.widget.ArrayAdapter; +import android.widget.Button; +import android.widget.EditText; +import android.widget.ListView; + +import androidx.appcompat.app.AppCompatActivity; + +import org.json.JSONObject; + +import java.util.ArrayList; +import java.util.List; + +/** + * 命令/聊天页:发送 session.prompt 并流式展示 status/event 回显。 + * 这是远程控制 Harness 的核心入口。 + */ +public class CommandActivity extends AppCompatActivity { + + private EditText input; + private ArrayAdapter adapter; + private ServerClient client; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_command); + + input = findViewById(R.id.command_input); + ListView list = findViewById(R.id.command_log); + List data = new ArrayList<>(); + adapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, data); + list.setAdapter(adapter); + + client = new ServerClient(new ServerClient.Listener() { + @Override + public void onConnectionChanged(boolean connected) { + runOnUiThread(() -> adapter.add(connected ? "[已连接]" : "[连接断开]")); + } + + @Override + public void onHello(JSONObject hello) { + // connected + } + + @Override + public void onStatus(JSONObject status) { + runOnUiThread(() -> adapter.add("[status] " + status.optString("model") + " running=" + status.optBoolean("running"))); + } + + @Override + public void onEvent(JSONObject event) { + runOnUiThread(() -> { + adapter.add("[event] " + event.toString()); + adapter.notifyDataSetChanged(); + }); + } + + @Override + public void onResponse(String requestId, boolean ok, JSONObject result, JSONObject error) { + runOnUiThread(() -> { + adapter.add(ok ? ("[响应] " + (result != null ? result.toString() : "ok")) : ("[错误] " + (error != null ? error.optString("message") : "unknown"))); + adapter.notifyDataSetChanged(); + }); + } + + @Override + public void onError(String message) { + runOnUiThread(() -> { + adapter.add("[错误] " + message); + adapter.notifyDataSetChanged(); + }); + } + }); + + client.connect( + SettingsStore.serverUrl(CommandActivity.this), + SettingsStore.userId(CommandActivity.this), + SettingsStore.token(CommandActivity.this)); + + Button send = findViewById(R.id.command_send); + send.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + String text = input.getText().toString().trim(); + if (text.isEmpty()) return; + JSONObject params = new JSONObject(); + try { + params.put("content", text); + } catch (Exception e) { } + client.sendRequest("session.prompt", params); + input.setText(""); + } + }); + + Button cancel = findViewById(R.id.command_cancel); + cancel.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + JSONObject params = new JSONObject(); + try { params.put("sessionId", JSONObject.NULL); } catch (Exception e) { } + client.sendRequest("session.cancel", params); + } + }); + } + + @Override + protected void onDestroy() { + super.onDestroy(); + if (client != null) client.close(); + } +} diff --git a/app/src/main/java/com/dshwatch/app/MainActivity.java b/app/src/main/java/com/dshwatch/app/MainActivity.java index 9b2cab9..305a399 100644 --- a/app/src/main/java/com/dshwatch/app/MainActivity.java +++ b/app/src/main/java/com/dshwatch/app/MainActivity.java @@ -117,6 +117,14 @@ public class MainActivity extends AppCompatActivity { } }); + Button command = findViewById(R.id.btn_command); + command.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + startActivity(new Intent(MainActivity.this, CommandActivity.class)); + } + }); + Button refresh = findViewById(R.id.btn_refresh); refresh.setOnClickListener(new View.OnClickListener() { @Override diff --git a/app/src/main/res/layout/activity_command.xml b/app/src/main/res/layout/activity_command.xml new file mode 100644 index 0000000..1e6c299 --- /dev/null +++ b/app/src/main/res/layout/activity_command.xml @@ -0,0 +1,54 @@ + + + + + + + + +