调整NFC接口窗体根据动作类型指定对应的脚本运行。

This commit is contained in:
2026-03-16 16:42:02 +08:00
parent 7713d6c460
commit b8c70bef98
3 changed files with 75 additions and 25 deletions

View File

@@ -1,8 +1,8 @@
#Created by .winboll/winboll_app_build.gradle #Created by .winboll/winboll_app_build.gradle
#Sun Mar 15 12:22:44 GMT 2026 #Mon Mar 16 08:40:20 GMT 2026
stageCount=26 stageCount=26
libraryProject= libraryProject=
baseVersion=15.11 baseVersion=15.11
publishVersion=15.11.25 publishVersion=15.11.25
buildCount=21 buildCount=26
baseBetaVersion=15.11.26 baseBetaVersion=15.11.26

View File

@@ -293,10 +293,17 @@
<activity <activity
android:name=".termux.NfcTermuxBridgeActivity" android:name=".termux.NfcTermuxBridgeActivity"
android:exported="true" android:exported="true"> <!-- 必须设置为 true允许外部应用调用 -->
android:launchMode="singleTop">
<!-- 接收 ACTION_BUILD 意图 -->
<intent-filter> <intent-filter>
<action android:name="cc.winboll.nfc.ACTION_EXEC_TERMUX" /> <action android:name="cc.winboll.studio.winboll.termux.NfcTermuxBridgeActivity.ACTION_BUILD" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
<!-- 接收 ACTION_BUILD_VIEW 意图 -->
<intent-filter>
<action android:name="cc.winboll.studio.winboll.termux.NfcTermuxBridgeActivity.ACTION_BUILD_VIEW" />
<category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.DEFAULT" />
</intent-filter> </intent-filter>
</activity> </activity>

View File

@@ -1,11 +1,11 @@
/* /*
* 源码说明与描述: * 源码说明与描述:
* NFC 与 Termux 桥接活动,用于接收 NFC 传递的 JSON 指令并执行 Termux 脚本命令 * NFC 与 Termux 桥接活动,用于接收外部应用(包调用)传递的 JSON 指令并执行 Termux 脚本命令
* 支持后台执行与终端窗口唤起两种模式,提供测试注入接口 * 支持 ACTION_BUILD后台执行与 ACTION_BUILD_VIEW终端窗口唤起两种动作
* *
* 作者:豆包&ZhanGSKen<zhangsken@qq.com> * 作者:豆包&ZhanGSKen<zhangsken@qq.com>
* 创建时间2025-03-15 14:00:00 * 创建时间2025-03-15 14:00:00
* 最后编辑时间2026-03-15 15:22:00 * 最后编辑时间2026-03-16 10:00:00
*/ */
package cc.winboll.studio.winboll.termux; package cc.winboll.studio.winboll.termux;
@@ -23,7 +23,11 @@ public class NfcTermuxBridgeActivity extends Activity {
// ========================= 常量与静态属性 ========================= // ========================= 常量与静态属性 =========================
public static final String TAG = "NfcTermuxBridgeActivity"; public static final String TAG = "NfcTermuxBridgeActivity";
public static final String ACTION_BUILD_VIEW = NfcTermuxBridgeActivity.class.getName() + ".ACTION_BUILD_VIEW";
// 外部应用调用时使用的 Action 常量
public static final String ACTION_BUILD = "cc.winboll.studio.winboll.termux.NfcTermuxBridgeActivity.ACTION_BUILD";
public static final String ACTION_BUILD_VIEW = "cc.winboll.studio.winboll.termux.NfcTermuxBridgeActivity.ACTION_BUILD_VIEW";
private static final Gson GSON = new Gson(); private static final Gson GSON = new Gson();
// ========================= 生命周期方法 ========================= // ========================= 生命周期方法 =========================
@@ -51,6 +55,10 @@ public class NfcTermuxBridgeActivity extends Activity {
} }
// ========================= 统一 Intent 分发(合并去重) ========================= // ========================= 统一 Intent 分发(合并去重) =========================
/**
* 统一分发 Intent根据 Action 路由到不同业务逻辑
* @param intent 外部传入的 Intent
*/
private void dispatchIntent(Intent intent) { private void dispatchIntent(Intent intent) {
LogUtils.d(TAG, "dispatchIntent() 分发 intent"); LogUtils.d(TAG, "dispatchIntent() 分发 intent");
if (intent == null) { if (intent == null) {
@@ -58,17 +66,22 @@ public class NfcTermuxBridgeActivity extends Activity {
return; return;
} }
if (ACTION_BUILD_VIEW.equals(intent.getAction())) { String action = intent.getAction();
if (ACTION_BUILD_VIEW.equals(action)) {
ToastUtils.show("ACTION_BUILD_VIEW 命中"); ToastUtils.show("ACTION_BUILD_VIEW 命中");
onOpenTermuxProjectBuildView(intent); onOpenTermuxProjectBuildView(intent);
} else { } else if (ACTION_BUILD.equals(action)) {
LogUtils.d(TAG, "ACTION_BUILD 命中");
handleNfcIntent(intent); handleNfcIntent(intent);
} else {
LogUtils.w(TAG, "dispatchIntent() 未知 Action: " + action);
finish();
} }
} }
// ========================= 核心业务方法 ========================= // ========================= 核心业务方法 =========================
/** /**
* 处理 NFC 传递的 JSON 指令 * 处理 ACTION_BUILD 动作:后台执行 NFC 指令
*/ */
private void handleNfcIntent(Intent intent) { private void handleNfcIntent(Intent intent) {
LogUtils.d(TAG, "handleNfcIntent() 调用"); LogUtils.d(TAG, "handleNfcIntent() 调用");
@@ -83,6 +96,7 @@ public class NfcTermuxBridgeActivity extends Activity {
if (json == null || json.isEmpty()) { if (json == null || json.isEmpty()) {
LogUtils.e(TAG, "handleNfcIntent() 指令为空"); LogUtils.e(TAG, "handleNfcIntent() 指令为空");
showToast("指令为空");
finish(); finish();
return; return;
} }
@@ -92,45 +106,53 @@ public class NfcTermuxBridgeActivity extends Activity {
if (cmd.script == null || cmd.script.isEmpty()) { if (cmd.script == null || cmd.script.isEmpty()) {
LogUtils.e(TAG, "handleNfcIntent() script 为空"); LogUtils.e(TAG, "handleNfcIntent() script 为空");
showToast("script 不能为空");
finish(); finish();
return; return;
} }
String scriptPath = "/data/data/com.termux/files/home/TermuxWorkSpaces/BashShells/AutoNFC/" + cmd.script; //String scriptPath = "/data/data/com.termux/files/home/TermuxWorkSpaces/BashShells/AutoNFC/" + cmd.script;
String scriptPath = "/data/data/com.termux/files/home/TermuxWorkSpaces/BashShells/AutoNFC/" + "BuildWinBoLLProject.sh";
LogUtils.d(TAG, "handleNfcIntent() 脚本路径: " + scriptPath); LogUtils.d(TAG, "handleNfcIntent() 脚本路径: " + scriptPath);
boolean success = TermuxCommandExecutor.executeCommand( boolean success = TermuxCommandExecutor.executeCommand(
this, scriptPath, cmd.args, cmd.workDir, cmd.background, cmd.resultDir this, scriptPath, cmd.args, cmd.workDir, cmd.background, cmd.resultDir
); );
LogUtils.d(TAG, "handleNfcIntent() 执行结果: " + success); LogUtils.d(TAG, "handleNfcIntent() 执行结果: " + success);
if (success) { if (success) {
Toast.makeText(this, "指令已发送: " + cmd.script, Toast.LENGTH_SHORT).show(); showToast("指令已发送: " + cmd.script);
LogUtils.i(TAG, "执行成功: " + scriptPath); LogUtils.i(TAG, "执行成功: " + scriptPath);
} else { } else {
Toast.makeText(this, "指令发送失败", Toast.LENGTH_SHORT).show(); showToast("指令发送失败");
LogUtils.e(TAG, "执行失败"); LogUtils.e(TAG, "执行失败");
} }
} catch (Exception e) { } catch (Exception e) {
LogUtils.e(TAG, "handleNfcIntent() 异常: " + e.getMessage(), e); LogUtils.e(TAG, "handleNfcIntent() 异常: " + e.getMessage(), e);
Toast.makeText(this, "解析失败", Toast.LENGTH_SHORT).show(); showToast("解析失败");
} finally { } finally {
finish(); finish();
} }
} }
/** /**
* 唤起 Termux 窗口执行命令(实时输出版) * 处理 ACTION_BUILD_VIEW 动作:唤起 Termux 窗口执行命令
*/ */
public void onOpenTermuxProjectBuildView(Intent intent) { public void onOpenTermuxProjectBuildView(Intent intent) {
LogUtils.d(TAG, "onOpenTermuxProjectBuildView() 调用"); LogUtils.d(TAG, "onOpenTermuxProjectBuildView() 调用");
if (intent == null) {
LogUtils.w(TAG, "onOpenTermuxProjectBuildView() intent 为空");
return;
}
try { try {
String json = intent.getStringExtra(Intent.EXTRA_TEXT); String json = intent.getStringExtra(Intent.EXTRA_TEXT);
LogUtils.d(TAG, "onOpenTermuxProjectBuildView() json: " + json); LogUtils.d(TAG, "onOpenTermuxProjectBuildView() json: " + json);
if (json == null || json.isEmpty()) { if (json == null || json.isEmpty()) {
LogUtils.e(TAG, "onOpenTermuxProjectBuildView() 指令为空"); LogUtils.e(TAG, "onOpenTermuxProjectBuildView() 指令为空");
showToast("指令为空");
finish(); finish();
return; return;
} }
@@ -140,45 +162,50 @@ public class NfcTermuxBridgeActivity extends Activity {
if (cmd.script == null || cmd.script.isEmpty()) { if (cmd.script == null || cmd.script.isEmpty()) {
LogUtils.e(TAG, "onOpenTermuxProjectBuildView() script 为空"); LogUtils.e(TAG, "onOpenTermuxProjectBuildView() script 为空");
showToast("script 不能为空");
finish(); finish();
return; return;
} }
StringBuilder targetCmd = new StringBuilder(); StringBuilder targetCmd = new StringBuilder();
String nfcScriptFolder = "/data/data/com.termux/files/home/TermuxWorkSpaces/BashShells/AutoNFC/"; String nfcScriptFolder = "/data/data/com.termux/files/home/TermuxWorkSpaces/BashShells/AutoNFC/";
targetCmd.append("cd " + nfcScriptFolder + " && "); targetCmd.append("cd " + nfcScriptFolder + " && ");
targetCmd.append("stdbuf -o0 -e0 -i0 bash ").append(cmd.script).append(" "); //targetCmd.append("stdbuf -o0 -e0 -i0 bash ").append(cmd.script).append(" ");
targetCmd.append("stdbuf -o0 -e0 -i0 bash ").append("BuildWinBoLLProjectView.sh").append(" ");
if (cmd.args != null) { if (cmd.args != null) {
for (String arg : cmd.args) { for (String arg : cmd.args) {
targetCmd.append(arg).append(" "); targetCmd.append(arg).append(" ");
} }
} }
//targetCmd.append(" && echo '\n✅ 执行完成!' && echo '\n📌 项目: ").append(cmd.args != null && cmd.args.length > 0 ? cmd.args[0] : "").append("' && read -p '按回车关闭...'");
LogUtils.d(TAG, "onOpenTermuxProjectBuildView() 命令: " + targetCmd); LogUtils.d(TAG, "onOpenTermuxProjectBuildView() 命令: " + targetCmd);
boolean cmdSuccess = TermuxCommandExecutor.executeTerminalCommand(this, targetCmd.toString()); boolean cmdSuccess = TermuxCommandExecutor.executeTerminalCommand(this, targetCmd.toString());
LogUtils.d(TAG, "onOpenTermuxProjectBuildView() 执行结果: " + cmdSuccess); LogUtils.d(TAG, "onOpenTermuxProjectBuildView() 执行结果: " + cmdSuccess);
if (cmdSuccess) { if (cmdSuccess) {
Toast.makeText(this, "指令已发送: " + cmd.script + " " + (cmd.args != null && cmd.args.length > 0 ? cmd.args[0] : ""), Toast.LENGTH_SHORT).show(); showToast("指令已发送: " + cmd.script);
} else { } else {
Toast.makeText(this, "指令发送失败", Toast.LENGTH_SHORT).show(); showToast("指令发送失败");
} }
} catch (Exception e) { } catch (Exception e) {
LogUtils.e(TAG, "onOpenTermuxProjectBuildView() 异常: " + e.getMessage(), e); LogUtils.e(TAG, "onOpenTermuxProjectBuildView() 异常: " + e.getMessage(), e);
Toast.makeText(this, "解析失败", Toast.LENGTH_SHORT).show(); showToast("解析失败");
} finally { } finally {
finish(); finish();
} }
} }
// ========================= 公共静态测试方法 ========================= // ========================= 公共静态测试方法 =========================
/**
* 内部测试方法:发送 ACTION_BUILD 指令
*/
public static void testCommand(Context context) { public static void testCommand(Context context) {
LogUtils.d(TAG, "testCommand()"); LogUtils.d(TAG, "testCommand()");
try { try {
String testJson = "{\"script\":\"BuildWinBoLLProject.sh\",\"args\":[\"DebugTemp\"],\"workDir\":null,\"background\":true,\"resultDir\":null}"; String testJson = "{\"script\":\"BuildWinBoLLProject.sh\",\"args\":[\"DebugTemp\"],\"workDir\":null,\"background\":true,\"resultDir\":null}";
Intent intent = new Intent(context, NfcTermuxBridgeActivity.class); Intent intent = new Intent(context, NfcTermuxBridgeActivity.class);
intent.setAction(ACTION_BUILD); // 指定 Action
intent.putExtra(Intent.EXTRA_TEXT, testJson); intent.putExtra(Intent.EXTRA_TEXT, testJson);
context.startActivity(intent); context.startActivity(intent);
} catch (Exception e) { } catch (Exception e) {
@@ -186,17 +213,33 @@ public class NfcTermuxBridgeActivity extends Activity {
} }
} }
/**
* 内部测试方法:发送 ACTION_BUILD_VIEW 指令
*/
public static void testViewCommand(Context context) { public static void testViewCommand(Context context) {
LogUtils.d(TAG, "testViewCommand()"); LogUtils.d(TAG, "testViewCommand()");
try { try {
String testJson = "{\"script\":\"BuildWinBoLLProjectView.sh\",\"args\":[\"DebugTemp\"],\"workDir\":null,\"background\":true,\"resultDir\":null}"; String testJson = "{\"script\":\"BuildWinBoLLProjectView.sh\",\"args\":[\"DebugTemp\"],\"workDir\":null,\"background\":true,\"resultDir\":null}";
Intent intent = new Intent(context, NfcTermuxBridgeActivity.class); Intent intent = new Intent(context, NfcTermuxBridgeActivity.class);
intent.setAction(ACTION_BUILD_VIEW); intent.setAction(ACTION_BUILD_VIEW); // 指定 Action
intent.putExtra(Intent.EXTRA_TEXT, testJson); intent.putExtra(Intent.EXTRA_TEXT, testJson);
context.startActivity(intent); context.startActivity(intent);
} catch (Exception e) { } catch (Exception e) {
LogUtils.e(TAG, "testViewCommand() 失败: " + e.getMessage()); LogUtils.e(TAG, "testViewCommand() 失败: " + e.getMessage());
} }
} }
// ========================= 工具方法 =========================
/**
* 统一显示 Toast确保在主线程调用
*/
private void showToast(final String message) {
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(NfcTermuxBridgeActivity.this, message, Toast.LENGTH_SHORT).show();
}
});
}
} }