Compare commits
7 Commits
debugtemp-
...
5f3168e17f
| Author | SHA1 | Date | |
|---|---|---|---|
| 5f3168e17f | |||
| e3c4bab6c9 | |||
| 2af6427ca8 | |||
| b8c70bef98 | |||
| 7713d6c460 | |||
| 73c69bd665 | |||
| a076fe50cd |
93
README.md
93
README.md
@@ -4,26 +4,27 @@ WinBoLL 源生态计划项目说明书
|
|||||||
|
|
||||||
1. 核心定位
|
1. 核心定位
|
||||||
|
|
||||||
【OriginMaster】WinBoLL 源生态计划,旨在通过核心项目 WinBoLL 联动系列开发库,构建手机端 Android 项目开发与多端编译同步的完整生态,实现手机与电脑的源码同步开发。
|
WinBoLL 手机源码计划,旨在通过核心项目 WinBoLL 构建手机端与服务器端的 Android 项目的开发源码生态。实现手机与服务器的源码的联合开发。
|
||||||
|
|
||||||
2. 仓库架构
|
2. 仓库架构
|
||||||
|
|
||||||
仓库类型 包含仓库 功能说明
|
仓库类型:功能说明
|
||||||
开发库 WinBoLL、APPBase、AES、PowerBell、Positions 核心开发依赖库,其中 WinBoLL 可作为应用开发的基础继承模板
|
基础项目分支 WinBoLL:手机端安卓应用开发基础模板。
|
||||||
分支汇总存档库 OriginMaster 仅用于汇总各开发库分支,不适宜作为开发库克隆使用,非应用开发基础库
|
应用项目分支 APPBase、AES、PowerBell、Positions:安卓应用单一管理系列项目。
|
||||||
|
各类分支源码合并存档 OriginMaster: 源码汇总管理,不适宜作为开发库使用。
|
||||||
|
|
||||||
3. 源码推送路径
|
3. 源码合并管理推送路线图。(仅仅展示不同应用模块源码的综合管理路线。分支合并操作时,必须具备Git管理经验。)
|
||||||
|
|
||||||
- WinBoLL → APPBase → OriginMaster
|
- WinBoLL → APPBase → OriginMaster
|
||||||
- WinBoLL → AES → OriginMaster
|
- WinBoLL → AES → OriginMaster
|
||||||
- WinBoLL → PowerBell → OriginMaster
|
- WinBoLL → PowerBell → OriginMaster
|
||||||
- WinBoLL → Positions → OriginMaster
|
- WinBoLL → Positions → OriginMaster
|
||||||
|
|
||||||
二、WinBoLL APP 核心信息
|
二、WinBoLL 项目核心信息
|
||||||
|
|
||||||
1. 项目简介
|
1. 项目简介
|
||||||
|
|
||||||
WinBoLL Studio Android 应用开源项目,专注于手机端 Android 开发与多端编译同步。
|
WinBoLL 项目是为手机端开发 Android 项目的需求而设计的项目。
|
||||||
|
|
||||||
2. 官方资源
|
2. 官方资源
|
||||||
|
|
||||||
@@ -32,73 +33,71 @@ WinBoLL Studio Android 应用开源项目,专注于手机端 Android 开发与
|
|||||||
- Gitea:https://gitea.winboll.cc/Studio/WinBoLL.git
|
- Gitea:https://gitea.winboll.cc/Studio/WinBoLL.git
|
||||||
- GitHub:https://github.com/ZhanGSKen/WinBoLL.git
|
- GitHub:https://github.com/ZhanGSKen/WinBoLL.git
|
||||||
- 码云:https://gitee.com/zhangsken/winboll.git
|
- 码云:https://gitee.com/zhangsken/winboll.git
|
||||||
- 托管类库源码:
|
|
||||||
- APPBase(jitpack.io):https://github.com/ZhanGSKen/APPBase.git
|
|
||||||
- AES(jitpack.io):https://github.com/ZhanGSKen/AES.git
|
|
||||||
|
|
||||||
三、通用特征文件夹前置(/sdcard)
|
三、WinBoLL 编译环境检查前提:使用通用特征文件夹"/sdcard/WinBoLLStudio/APKs"是否存在为判断条件。
|
||||||
|
- "/sdcard/WinBoLLStudio/APKs"目录条件设置方法
|
||||||
- Linux 系统文件夹直接使用 /sdcard 。
|
Linux 服务器端方面:建立 /sdcard/WinBoLLStudio/APKs 目录即可。
|
||||||
- 手机 SD 卡存储( /storage/emulated/0 )挂载的别名也可为 /sdcard 。
|
手机开发端方面:建立 "/sdcard/WinBoLLStudio/APKs"目录(即 "/storage/emulated/0/WinBoLLStudio/APKs"目录) 即可。
|
||||||
|
|
||||||
四、前置条件
|
四、前置条件
|
||||||
|
|
||||||
1. WinBoLL-APP 配置
|
1. WinBoLL APP 开发环境配置介绍
|
||||||
|
|
||||||
- APK 编译输出目录: /sdcard/WinBoLLStudio/APKs/ ,以及 /sdcard/AppProjects/ (命名为 app.apk )
|
- WinBoLL APK 编译输出内容包括:
|
||||||
- 签名与命名空间:支持应用签名验证定制化,与衍生 APP 共享 cc.winboll.studio 命名空间
|
"/sdcard/WinBoLLStudio/APKs" 目录内的所有应用分支的 APK 文件,
|
||||||
|
与 "/sdcard/AppProjects/app.apk"文件。
|
||||||
|
- WinBoLL APK 使用 "cc.winboll.studio" 命名空间。
|
||||||
|
|
||||||
五、核心需求规划
|
五、核心需求规划
|
||||||
|
|
||||||
1. 主机端需求
|
1. WinBoLL 应用安全验证需求
|
||||||
|
|
||||||
- 支持 winboll.cc 域名的用户注册登录服务
|
- 支持 https://console.winboll.cc/ 访问服务器以校验应用包签名与版本。
|
||||||
- 支持 https://console.winboll.cc/api 访问
|
|
||||||
|
|
||||||
2. APP 端需求
|
2. 手机端源码开发管理需求
|
||||||
|
|
||||||
- 实现手机端 Android 应用开发与管理功能
|
- 支持切换不同 WinBoLL 分支,以开发不同安卓应用。
|
||||||
|
|
||||||
六、编译与使用指南
|
六、编译与使用指南
|
||||||
|
|
||||||
1. 项目初始化(必须)
|
1. 项目初始化(必须)
|
||||||
|
|
||||||
1. 复制 settings.gradle-demo 为 settings.gradle ,取消对应项目模块注释
|
1. 复制 settings.gradle-demo 为 settings.gradle 。编辑 settings.gradle 文件内容,取消对应项目模块注释。
|
||||||
2. 复制 gradle.properties-androidx-demo 或 gradle.properties-android-demo 为 gradle.properties
|
2. 复制 gradle.properties-androidx-demo(Android X 项目) 或 gradle.properties-android-demo(基本 Android 项目) 为 gradle.properties。
|
||||||
3. (可选)复制 local.properties-demo 为 local.properties ,配置 Android SDK 目录
|
3. 复制(可选)local.properties-demo 为 local.properties ,编辑 local.properties 文件内容,配置 Android SDK 目录。
|
||||||
4. 签名设置:
|
4. 签名设置:
|
||||||
- 调试编译:进入 GenKeyStore 目录执行 bash gen_debug_keystore.sh
|
- 调试编译秘钥制作:使用 Termux 应用终端 cd 进入 GenKeyStore 目录,运行 bash gen_debug_keystore.sh 脚本即可生成应用调试秘钥。
|
||||||
- 非必须:clone keystore 模块,拷贝 appkey.jks 与 appkey.keystore 到项目根目录
|
- 应用秘钥配置方法:拷贝调试编译秘钥制作生成的 appkey.jks 与 appkey.keystore 文件到项目根目录即可。
|
||||||
|
|
||||||
2. 编译命令
|
七、应用编译命令介绍
|
||||||
|
|
||||||
(1)类库型项目
|
(1)类库型模块配置要点
|
||||||
|
|
||||||
1. 修改测试项目 build.properties ,设置 libraryProject=<类库项目模块名>
|
1. 优先修改应用测试项目(目录为"<WinBoLl根目录>/<类库测试应用>/")内 build.properties 文件,设置对应的类库项目名称:libraryProject=<类库项目模块名> 。
|
||||||
2. 编译测试项目: bash .winboll/bashPublishAPKAddTag.sh <应用项目模块名>
|
2. 编译优先启动步骤:使用 Termux 应用,进入"<WinBoLl根目录>",运行 $bash .winboll/bashPublishAPKAddTag.sh <类库测试项目模块名> 命令,运行后可生成测试项目与类库项目的编译参数文件 build.properties 。生成的 build.properties 文件有两份,一份在测试项目模块的文件夹内,一份在类库项目本身的模块文件夹内。
|
||||||
3. 编译类库项目: bash .winboll/bashPublishLIBAddTag.sh <类库项目模块名> (发布至 WinBoLL Nexus Maven 库)
|
3. 类库编译发布步骤:使用 Termux 应用,进入"<WinBoLl根目录>",运行 $bash .winboll/bashPublishLIBAddTag.sh <类库项目模块名> 命令,运行后可发布至 WinBoLL Nexus Maven 库、本地maven目录或者是通用默认的 Gradle Maven 库。
|
||||||
|
|
||||||
(2)应用型项目
|
(2)单一应用型模块与类库测试型模块配置要点
|
||||||
|
|
||||||
- 编译命令: bash .winboll/bashPublishAPKAddTag.sh <应用项目模块名>
|
- 编译方法:使用 Termux 应用,进入"<WinBoLl根目录>",运行 $bash .winboll/bashPublishAPKAddTag.sh <应用项目模块名> ,运行后
|
||||||
|
- 编译输出路径:
|
||||||
|
默认路径(assembleBetaDebug任务): /sdcard/WinBoLLStudio/APKs/<项目根目录名称>/debug/
|
||||||
|
默认路径(assembleStageRelease任务): /sdcard/WinBoLLStudio/APKs/<项目根目录名称>/tag/
|
||||||
|
额外路径:若 winboll.properties 配置 ExtraAPKOutputPath ,APK 同步拷贝至该ExtraAPKOutputPath路径
|
||||||
|
|
||||||
(3)调试编译
|
(3)手机端应用调试命令介绍
|
||||||
|
|
||||||
- Beta 调试: bash gradlew assembleBetaDebug
|
- Beta 渠道调试命令:$bash gradlew assembleBetaDebug
|
||||||
- Stage 调试: bash gradlew assembleStageDebug
|
- Stage 渠道调试命令:$bash gradlew assembleStageDebug
|
||||||
|
|
||||||
(4)发布编译
|
(4)服务器端应用发布命令介绍
|
||||||
|
|
||||||
- Stage 发布:bash .winboll/bashPublishAPKAddTag.sh <应用项目模块名>
|
- Stage 渠道应用发布命令为("<WinBoLl根目录>/settings.gradle"文件需要配置编译模块开启参数,拷贝 settings.gradle-demo 为 settings.gradle 文件取消对应的分支配置部分即可。):
|
||||||
或者执行 bash gradlew assembleStageRelease
|
$bash .winboll/bashPublishAPKAddTag.sh <应用项目模块名>
|
||||||
|
或者
|
||||||
|
$bash gradlew assembleStageRelease
|
||||||
|
|
||||||
3. 编译输出路径
|
|
||||||
|
|
||||||
- 默认路径(assembleBetaDebug任务): /sdcard/WinBoLLStudio/APKs/<项目根目录名称>/debug/
|
|
||||||
- 默认路径(assembleStageRelease任务): /sdcard/WinBoLLStudio/APKs/<项目根目录名称>/tag/
|
|
||||||
- 额外路径:若 winboll.properties 配置 ExtraAPKOutputPath ,APK 同步拷贝至该ExtraAPKOutputPath路径
|
|
||||||
|
|
||||||
4. 版本号命名规则
|
|
||||||
|
|
||||||
|
八、WinBoLL 应用 APK 版本号命名规则
|
||||||
- Stage 渠道: V<应用开发环境编号><应用功能变更号><应用调试阶段号> (示例: APPBase_15.7.0 )
|
- Stage 渠道: V<应用开发环境编号><应用功能变更号><应用调试阶段号> (示例: APPBase_15.7.0 )
|
||||||
- Beta 渠道: V<应用开发环境编号><应用功能变更号><应用调试阶段号>-beta<调试编译计数>_<调试编译时间(分钟+秒钟)> (示例: APPBase_15.9.6-beta8_5413 )
|
- Beta 渠道: V<应用开发环境编号><应用功能变更号><应用调试阶段号>-beta<调试编译计数>_<调试编译时间(分钟+秒钟)> (示例: APPBase_15.9.6-beta8_5413 )
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
#Created by .winboll/winboll_app_build.gradle
|
#Created by .winboll/winboll_app_build.gradle
|
||||||
#Sun Mar 15 11:48:40 HKT 2026
|
#Mon Mar 16 19:52:21 GMT 2026
|
||||||
stageCount=26
|
stageCount=26
|
||||||
libraryProject=
|
libraryProject=
|
||||||
baseVersion=15.11
|
baseVersion=15.11
|
||||||
publishVersion=15.11.25
|
publishVersion=15.11.25
|
||||||
buildCount=0
|
buildCount=29
|
||||||
baseBetaVersion=15.11.26
|
baseBetaVersion=15.11.26
|
||||||
|
|||||||
@@ -293,11 +293,14 @@
|
|||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".termux.NfcTermuxBridgeActivity"
|
android:name=".termux.NfcTermuxBridgeActivity"
|
||||||
android:exported="true">
|
android:exported="true"> <!-- 必须设置为 true,允许外部应用调用 -->
|
||||||
|
|
||||||
|
<!-- 接收 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" />
|
<category android:name="android.intent.category.DEFAULT" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
|
|
||||||
</activity>
|
</activity>
|
||||||
|
|
||||||
</application>
|
</application>
|
||||||
|
|||||||
@@ -1,3 +1,12 @@
|
|||||||
|
/*
|
||||||
|
* 源码说明与描述:
|
||||||
|
* NFC 与 Termux 桥接活动,用于接收外部应用(包调用)传递的 JSON 指令并执行 Termux 脚本命令。
|
||||||
|
* 支持 ACTION_BUILD(后台执行)与 ACTION_BUILD_VIEW(终端窗口唤起)两种动作。
|
||||||
|
*
|
||||||
|
* 作者:豆包&ZhanGSKen<zhangsken@qq.com>
|
||||||
|
* 创建时间:2025-03-15 14:00:00
|
||||||
|
* 最后编辑时间:2026-03-16 10:00:00
|
||||||
|
*/
|
||||||
package cc.winboll.studio.winboll.termux;
|
package cc.winboll.studio.winboll.termux;
|
||||||
|
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
@@ -6,99 +15,227 @@ import android.content.Intent;
|
|||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
import cc.winboll.studio.libappbase.LogUtils;
|
import cc.winboll.studio.libappbase.LogUtils;
|
||||||
|
import cc.winboll.studio.libappbase.ToastUtils;
|
||||||
import cc.winboll.studio.winboll.models.NfcTermuxCmd;
|
import cc.winboll.studio.winboll.models.NfcTermuxCmd;
|
||||||
import com.google.gson.Gson;
|
import com.google.gson.Gson;
|
||||||
|
|
||||||
public class NfcTermuxBridgeActivity extends Activity {
|
public class NfcTermuxBridgeActivity extends Activity {
|
||||||
|
|
||||||
private static final String TAG = "NfcTermuxBridge";
|
// ========================= 常量与静态属性 =========================
|
||||||
|
public static final String TAG = "NfcTermuxBridgeActivity";
|
||||||
|
|
||||||
|
// 外部应用调用时使用的 Action 常量
|
||||||
|
public static final String ACTION_BUILD = "cc.winboll.studio.winboll.termux.NfcTermuxBridgeActivity.ACTION_BUILD";
|
||||||
|
|
||||||
private static final Gson GSON = new Gson();
|
private static final Gson GSON = new Gson();
|
||||||
|
|
||||||
|
// ========================= 生命周期方法 =========================
|
||||||
@Override
|
@Override
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
handleNfcIntent(getIntent());
|
LogUtils.d(TAG, "onCreate() 调用,savedInstanceState: " + (savedInstanceState != null ? "非空" : "空"));
|
||||||
|
dispatchIntent(getIntent());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onNewIntent(Intent intent) {
|
protected void onNewIntent(Intent intent) {
|
||||||
super.onNewIntent(intent);
|
super.onNewIntent(intent);
|
||||||
handleNfcIntent(intent);
|
LogUtils.d(TAG, "onNewIntent() 调用,intent: " + (intent != null ? intent.toString() : "null"));
|
||||||
|
if (intent != null) {
|
||||||
|
LogUtils.d(TAG, "onNewIntent() action: " + intent.getAction());
|
||||||
|
LogUtils.d(TAG, "onNewIntent() data: " + intent.getDataString());
|
||||||
|
LogUtils.d(TAG, "onNewIntent() extras: " + intent.getExtras());
|
||||||
|
LogUtils.d(TAG, "onNewIntent() flags: " + intent.getFlags());
|
||||||
|
LogUtils.d(TAG, "onNewIntent() component: " + intent.getComponent());
|
||||||
|
} else {
|
||||||
|
LogUtils.w(TAG, "onNewIntent() intent is null");
|
||||||
|
}
|
||||||
|
dispatchIntent(intent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ========================= 统一 Intent 分发(合并去重) =========================
|
||||||
/**
|
/**
|
||||||
* 处理 NFC 传递的 JSON 指令
|
* 统一分发 Intent,根据 Action 路由到不同业务逻辑
|
||||||
|
* @param intent 外部传入的 Intent
|
||||||
*/
|
*/
|
||||||
private void handleNfcIntent(Intent intent) {
|
private void dispatchIntent(Intent intent) {
|
||||||
if (intent == null) return;
|
LogUtils.d(TAG, "dispatchIntent() 分发 intent");
|
||||||
|
if (intent == null) {
|
||||||
|
LogUtils.w(TAG, "dispatchIntent() intent is null");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
String action = intent.getAction();
|
||||||
|
if (ACTION_BUILD.equals(action)) {
|
||||||
|
ToastUtils.show("ACTION_BUILD 命中");
|
||||||
|
onOpenTermuxProjectBuild(intent);
|
||||||
|
} else {
|
||||||
|
LogUtils.w(TAG, "dispatchIntent() 未知 Action: " + action);
|
||||||
|
finish();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ========================= 核心业务方法 =========================
|
||||||
|
/**
|
||||||
|
* 处理 ACTION_BUILD 动作:后台执行 NFC 指令
|
||||||
|
*/
|
||||||
|
// private void handleNfcIntent(Intent intent) {
|
||||||
|
// LogUtils.d(TAG, "handleNfcIntent() 调用");
|
||||||
|
// if (intent == null) {
|
||||||
|
// LogUtils.w(TAG, "handleNfcIntent() intent 为空");
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// try {
|
||||||
|
// String json = intent.getStringExtra(Intent.EXTRA_TEXT);
|
||||||
|
// LogUtils.d(TAG, "handleNfcIntent() json: " + json);
|
||||||
|
//
|
||||||
|
// if (json == null || json.isEmpty()) {
|
||||||
|
// LogUtils.e(TAG, "handleNfcIntent() 指令为空");
|
||||||
|
// showToast("指令为空");
|
||||||
|
// finish();
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// NfcTermuxCmd cmd = GSON.fromJson(json, NfcTermuxCmd.class);
|
||||||
|
// LogUtils.d(TAG, "handleNfcIntent() cmd: " + cmd);
|
||||||
|
//
|
||||||
|
// if (cmd.script == null || cmd.script.isEmpty()) {
|
||||||
|
// LogUtils.e(TAG, "handleNfcIntent() script 为空");
|
||||||
|
// showToast("script 不能为空");
|
||||||
|
// finish();
|
||||||
|
// 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/" + "BuildWinBoLLProject.sh";
|
||||||
|
// LogUtils.d(TAG, "handleNfcIntent() 脚本路径: " + scriptPath);
|
||||||
|
//
|
||||||
|
// boolean success = TermuxCommandExecutor.executeCommand(
|
||||||
|
// this, scriptPath, cmd.args, cmd.workDir, cmd.background, cmd.resultDir
|
||||||
|
// );
|
||||||
|
// LogUtils.d(TAG, "handleNfcIntent() 执行结果: " + success);
|
||||||
|
//
|
||||||
|
// if (success) {
|
||||||
|
// showToast("指令已发送: " + cmd.script);
|
||||||
|
// LogUtils.i(TAG, "执行成功: " + scriptPath);
|
||||||
|
// } else {
|
||||||
|
// showToast("指令发送失败");
|
||||||
|
// LogUtils.e(TAG, "执行失败");
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// } catch (Exception e) {
|
||||||
|
// LogUtils.e(TAG, "handleNfcIntent() 异常: " + e.getMessage(), e);
|
||||||
|
// showToast("解析失败");
|
||||||
|
// } finally {
|
||||||
|
// finish();
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理 ACTION_BUILD_VIEW 动作:唤起 Termux 窗口执行命令
|
||||||
|
*/
|
||||||
|
public void onOpenTermuxProjectBuild(Intent intent) {
|
||||||
|
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);
|
||||||
|
|
||||||
// 1. 发布版逻辑:正常接收 NFC 传入的 JSON
|
|
||||||
if (json == null || json.isEmpty()) {
|
if (json == null || json.isEmpty()) {
|
||||||
LogUtils.e(TAG, "NFC 指令为空");
|
LogUtils.e(TAG, "onOpenTermuxProjectBuildView() 指令为空");
|
||||||
|
showToast("指令为空");
|
||||||
finish();
|
finish();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
LogUtils.d(TAG, "接收 JSON:" + json);
|
|
||||||
|
|
||||||
// 2. 解析指令
|
|
||||||
NfcTermuxCmd cmd = GSON.fromJson(json, NfcTermuxCmd.class);
|
NfcTermuxCmd cmd = GSON.fromJson(json, NfcTermuxCmd.class);
|
||||||
|
LogUtils.d(TAG, "onOpenTermuxProjectBuildView() cmd: " + cmd);
|
||||||
|
|
||||||
if (cmd.script == null || cmd.script.isEmpty()) {
|
if (cmd.script == null || cmd.script.isEmpty()) {
|
||||||
LogUtils.e(TAG, "script 不能为空");
|
LogUtils.e(TAG, "onOpenTermuxProjectBuildView() script 为空");
|
||||||
|
showToast("script 不能为空");
|
||||||
finish();
|
finish();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 3. 拼接脚本路径
|
StringBuilder targetCmd = new StringBuilder();
|
||||||
String scriptPath = "/data/data/com.termux/files/home/TermuxWorkSpaces/BashShells/AutoNFC/" + cmd.script;
|
String nfcScriptFolder = "/data/data/com.termux/files/home/TermuxWorkSpaces/BashShells/AutoNFC/";
|
||||||
|
targetCmd.append("cd " + nfcScriptFolder + " && ");
|
||||||
|
//targetCmd.append("stdbuf -o0 -e0 -i0 bash ").append(cmd.script).append(" ");
|
||||||
|
targetCmd.append("stdbuf -o0 -e0 -i0 bash ").append("BuildWinBoLLProject.sh").append(" ");
|
||||||
|
if (cmd.args != null) {
|
||||||
|
for (String arg : cmd.args) {
|
||||||
|
targetCmd.append(arg).append(" ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 4. 执行 Termux 命令
|
LogUtils.d(TAG, "onOpenTermuxProjectBuildView() 命令: " + targetCmd);
|
||||||
boolean success = TermuxCommandExecutor.executeCommand(
|
boolean cmdSuccess = TermuxCommandExecutor.executeTerminalCommand(this, targetCmd.toString());
|
||||||
this,
|
LogUtils.d(TAG, "onOpenTermuxProjectBuildView() 执行结果: " + cmdSuccess);
|
||||||
scriptPath,
|
|
||||||
cmd.args,
|
|
||||||
cmd.workDir,
|
|
||||||
cmd.background,
|
|
||||||
cmd.resultDir
|
|
||||||
);
|
|
||||||
|
|
||||||
// 5. 结果反馈
|
if (cmdSuccess) {
|
||||||
if (success) {
|
showToast("指令已发送: " + cmd.script);
|
||||||
Toast.makeText(this, "指令已发送:" + cmd.script, Toast.LENGTH_SHORT).show();
|
|
||||||
LogUtils.i(TAG, "执行成功:" + scriptPath);
|
|
||||||
} else {
|
} else {
|
||||||
Toast.makeText(this, "指令发送失败", Toast.LENGTH_SHORT).show();
|
showToast("指令发送失败");
|
||||||
LogUtils.e(TAG, "执行失败");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
LogUtils.e(TAG, "处理异常:" + e.getMessage(), e);
|
LogUtils.e(TAG, "onOpenTermuxProjectBuildView() 异常: " + e.getMessage(), e);
|
||||||
Toast.makeText(this, "解析失败", Toast.LENGTH_SHORT).show();
|
showToast("解析失败");
|
||||||
} finally {
|
} finally {
|
||||||
finish();
|
finish();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ===========================================================
|
// ========================= 公共静态测试方法 =========================
|
||||||
// 公共静态测试函数:外部可直接调用注入测试 JSON
|
/**
|
||||||
// ===========================================================
|
* 内部测试方法:发送 ACTION_BUILD 指令
|
||||||
|
*/
|
||||||
public static void testCommand(Context context) {
|
public static void testCommand(Context context) {
|
||||||
|
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\":[\"WinBoLL_Demo\"],\"workDir\":null,\"background\":true,\"resultDir\":null}";
|
Intent intent = new Intent(context, NfcTermuxBridgeActivity.class);
|
||||||
|
intent.setAction(ACTION_BUILD); // 指定 Action
|
||||||
Intent testIntent = new Intent(context, NfcTermuxBridgeActivity.class);
|
intent.putExtra(Intent.EXTRA_TEXT, testJson);
|
||||||
testIntent.putExtra(Intent.EXTRA_TEXT, testJson);
|
context.startActivity(intent);
|
||||||
|
|
||||||
// 模拟跳转至自身 Activity
|
|
||||||
context.startActivity(testIntent);
|
|
||||||
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
LogUtils.e(TAG, "测试指令注入失败:" + e.getMessage());
|
LogUtils.e(TAG, "testCommand() 失败: " + e.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 内部测试方法:发送 ACTION_BUILD_VIEW 指令
|
||||||
|
*/
|
||||||
|
// public static void testViewCommand(Context context) {
|
||||||
|
// LogUtils.d(TAG, "testViewCommand()");
|
||||||
|
// try {
|
||||||
|
// String testJson = "{\"script\":\"BuildWinBoLLProjectView.sh\",\"args\":[\"DebugTemp\"],\"workDir\":null,\"background\":true,\"resultDir\":null}";
|
||||||
|
// Intent intent = new Intent(context, NfcTermuxBridgeActivity.class);
|
||||||
|
// intent.setAction(ACTION_BUILD_VIEW); // 指定 Action
|
||||||
|
// intent.putExtra(Intent.EXTRA_TEXT, testJson);
|
||||||
|
// context.startActivity(intent);
|
||||||
|
// } catch (Exception e) {
|
||||||
|
// 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();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -38,8 +38,8 @@ public class TermuxEnvTestActivity extends BaseWinBoLLActivity {
|
|||||||
|
|
||||||
// 常量属性(置顶排列)
|
// 常量属性(置顶排列)
|
||||||
public static final String TAG = "TermuxEnvTestActivity";
|
public static final String TAG = "TermuxEnvTestActivity";
|
||||||
private static final String TERMUX_HOME_PATH = "/sdcard/WinBoLLStudio";
|
private static final String TERMUX_HOME_PATH = "/data/data/com.termux/files/home/TermuxWorkSpaces";
|
||||||
private static final String CMD_RESULT_FILE = TERMUX_HOME_PATH + "/.authcenter_cmd_result.tmp";
|
private static final String CMD_RESULT_FILE = TERMUX_HOME_PATH + "/CMD_RESULT_FILE.log";
|
||||||
|
|
||||||
// 成员属性(常量后排列)
|
// 成员属性(常量后排列)
|
||||||
private Toolbar mToolbar;
|
private Toolbar mToolbar;
|
||||||
@@ -158,7 +158,7 @@ public class TermuxEnvTestActivity extends BaseWinBoLLActivity {
|
|||||||
/**
|
/**
|
||||||
* 测试执行Gradle命令(实时输出版,唤起Termux窗口)
|
* 测试执行Gradle命令(实时输出版,唤起Termux窗口)
|
||||||
*/
|
*/
|
||||||
public void onTestTermuxCMD(View view) {
|
public void onTestTermuxGradleBuildCMD(View view) {
|
||||||
LogUtils.d(TAG, "onTestTermuxCMD() 按钮点击,执行Gradle命令(实时输出)");
|
LogUtils.d(TAG, "onTestTermuxCMD() 按钮点击,执行Gradle命令(实时输出)");
|
||||||
tvMessage.append("\n【测试:执行Gradle命令(实时输出)】\n");
|
tvMessage.append("\n【测试:执行Gradle命令(实时输出)】\n");
|
||||||
|
|
||||||
@@ -171,7 +171,7 @@ public class TermuxEnvTestActivity extends BaseWinBoLLActivity {
|
|||||||
|
|
||||||
// 2. 定义核心路径(确保路径与Termux中一致)
|
// 2. 定义核心路径(确保路径与Termux中一致)
|
||||||
String gradleFullPath = "/data/data/com.termux/files/home/gradle/gradle-7.5.1/bin/gradle";
|
String gradleFullPath = "/data/data/com.termux/files/home/gradle/gradle-7.5.1/bin/gradle";
|
||||||
String projectPath = TERMUX_HOME_PATH + "/Sources/WinBoLL"; // 项目目录
|
String projectPath = TERMUX_HOME_PATH + "/Sources/DebugTemp"; // 项目目录
|
||||||
|
|
||||||
// 3. 构造命令(核心:用stdbuf禁用缓冲,实现实时输出)
|
// 3. 构造命令(核心:用stdbuf禁用缓冲,实现实时输出)
|
||||||
String targetCmd = "";
|
String targetCmd = "";
|
||||||
@@ -218,10 +218,15 @@ public class TermuxEnvTestActivity extends BaseWinBoLLActivity {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void onTestWinBoLLProjectBuild(View view) {
|
public void onTestWinBoLLProjectBuild(View view) {
|
||||||
ToastUtils.show("onOpenTermuxBash");
|
ToastUtils.show("onTestWinBoLLProjectBuild");
|
||||||
NfcTermuxBridgeActivity.testCommand(this);
|
NfcTermuxBridgeActivity.testCommand(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// public void onTestWinBoLLProjectBuildView(View view) {
|
||||||
|
// ToastUtils.show("onTestWinBoLLProjectBuildView");
|
||||||
|
// NfcTermuxBridgeActivity.testViewCommand(this);
|
||||||
|
// }
|
||||||
|
|
||||||
public void onOpenTermuxBash(View view) {
|
public void onOpenTermuxBash(View view) {
|
||||||
LogUtils.d(TAG, "onTestTermuxCMD() 按钮点击,执行Gradle命令(实时输出)");
|
LogUtils.d(TAG, "onTestTermuxCMD() 按钮点击,执行Gradle命令(实时输出)");
|
||||||
tvMessage.append("\n【测试:执行Gradle命令(实时输出)】\n");
|
tvMessage.append("\n【测试:执行Gradle命令(实时输出)】\n");
|
||||||
@@ -235,7 +240,7 @@ public class TermuxEnvTestActivity extends BaseWinBoLLActivity {
|
|||||||
|
|
||||||
// 2. 定义核心路径(确保路径与Termux中一致)
|
// 2. 定义核心路径(确保路径与Termux中一致)
|
||||||
String gradleFullPath = "/data/data/com.termux/files/home/gradle/gradle-7.5.1/bin/gradle";
|
String gradleFullPath = "/data/data/com.termux/files/home/gradle/gradle-7.5.1/bin/gradle";
|
||||||
String projectPath = TERMUX_HOME_PATH + "/Sources/WinBoLL"; // 项目目录
|
String projectPath = TERMUX_HOME_PATH + "/"; // 项目目录
|
||||||
|
|
||||||
// 3. 构造命令(核心:用stdbuf禁用缓冲,实现实时输出)
|
// 3. 构造命令(核心:用stdbuf禁用缓冲,实现实时输出)
|
||||||
String targetCmd = "";
|
String targetCmd = "";
|
||||||
|
|||||||
@@ -18,24 +18,28 @@
|
|||||||
android:gravity="right">
|
android:gravity="right">
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
|
android:textAllCaps="false"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="OpenTermuxBash"
|
android:text="Open Termux Bash"
|
||||||
android:onClick="onOpenTermuxBash"/>
|
android:onClick="onOpenTermuxBash"/>
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
|
android:textAllCaps="false"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="TestTermuxCMD"
|
android:text="Test Termux Gradle Build CMD"
|
||||||
android:onClick="onTestTermuxCMD"/>
|
android:onClick="onTestTermuxGradleBuildCMD"/>
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
|
android:textAllCaps="false"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="TestTermuxEnv"
|
android:text="Test Termux Env"
|
||||||
android:onClick="onTestTermuxEnv"/>
|
android:onClick="onTestTermuxEnv"/>
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
|
android:textAllCaps="false"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="Test WinBoLL Project Build"
|
android:text="Test WinBoLL Project Build"
|
||||||
|
|||||||
Reference in New Issue
Block a user