diff --git a/winboll/build.properties b/winboll/build.properties index d52fadf..8747ee0 100644 --- a/winboll/build.properties +++ b/winboll/build.properties @@ -1,8 +1,8 @@ #Created by .winboll/winboll_app_build.gradle -#Mon Jan 19 07:19:47 GMT 2026 +#Mon Jan 19 07:45:31 GMT 2026 stageCount=11 libraryProject= baseVersion=15.11 publishVersion=15.11.10 -buildCount=36 +buildCount=40 baseBetaVersion=15.11.11 diff --git a/winboll/src/main/java/cc/winboll/studio/winboll/unittest/TermuxEnvTestActivity.java b/winboll/src/main/java/cc/winboll/studio/winboll/unittest/TermuxEnvTestActivity.java index 07bddcc..94cb59b 100644 --- a/winboll/src/main/java/cc/winboll/studio/winboll/unittest/TermuxEnvTestActivity.java +++ b/winboll/src/main/java/cc/winboll/studio/winboll/unittest/TermuxEnvTestActivity.java @@ -23,10 +23,10 @@ import java.nio.charset.StandardCharsets; /** * @Author 豆包&ZhanGSKen * @Date 2026/01/19 11:11:00 - * @LastEditTime 2026/01/21 10:45:00 + * @LastEditTime 2026/01/21 17:45:00 * @Describe Termux环境测试工具(跨包+sharedUserId模式) * 适配不同应用包名(当前包:cc.winboll.studio.winboll.beta / Termux包:com.termux) - * 支持Termux目录读取、Gradle命令执行(唤起窗口显示输出),基于sharedUserId实现跨包权限适配 + * 支持Termux目录读取、Gradle命令实时输出执行(唤起窗口),基于sharedUserId实现跨包权限适配 */ public class TermuxEnvTestActivity extends BaseWinBoLLActivity { // 常量属性(置顶排列) @@ -67,10 +67,12 @@ public class TermuxEnvTestActivity extends BaseWinBoLLActivity { StringBuilder initMsg = new StringBuilder(); initMsg.append("Termux 测试工具(跨包+sharedUserId模式)\n"); initMsg.append("-------------------------\n"); - initMsg.append("当前应用包名:").append(getPackageName()).append("\n"); + initMsg.append("当前应用包名:"); + initMsg.append(getPackageName()); + initMsg.append("\n"); initMsg.append("Termux应用包名:com.termux\n"); initMsg.append("sharedUserId:com.termux(需一致)\n"); - initMsg.append("支持功能:目录读取、Gradle命令执行(唤起Termux窗口)\n"); + initMsg.append("支持功能:目录读取、Gradle命令实时输出(唤起Termux窗口)\n"); initMsg.append("-------------------------\n"); tvMessage.setText(initMsg.toString()); @@ -94,13 +96,13 @@ public class TermuxEnvTestActivity extends BaseWinBoLLActivity { ((AppCompatActivity) getActivity()).getSupportActionBar().setDisplayHomeAsUpEnabled(true); mToolbar.setNavigationOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - LogUtils.d(TAG, "initToolbar() 导航栏返回按钮点击"); - getActivity().finish(); - WinBoLLActivityManager.getInstance().startWinBoLLActivity(getActivity(), MainActivity.class); - } - }); + @Override + public void onClick(View v) { + LogUtils.d(TAG, "initToolbar() 导航栏返回按钮点击"); + getActivity().finish(); + WinBoLLActivityManager.getInstance().startWinBoLLActivity(getActivity(), MainActivity.class); + } + }); LogUtils.d(TAG, "initToolbar() 初始化完成"); } @@ -122,11 +124,14 @@ public class TermuxEnvTestActivity extends BaseWinBoLLActivity { if (createSuccess) { LogUtils.d(TAG, "initTermuxDirectory() Termux目录创建成功:" + TERMUX_HOME_PATH); tvMessage.append("Termux目录创建成功:"); - tvMessage.append(TERMUX_HOME_PATH); - tvMessage.append("\n"); + tvMessage.append(TERMUX_HOME_PATH); + tvMessage.append("\n"); } else { LogUtils.e(TAG, "initTermuxDirectory() 错误:Termux目录创建失败"); - tvMessage.append("警告:Termux目录创建失败!\n请检查:\n1.AndroidManifest.xml中sharedUserId是否为com.termux\n2.设备是否已root(部分机型需root才能跨包写私有目录)\n"); + tvMessage.append("警告:Termux目录创建失败!\n"); + tvMessage.append("请检查:\n"); + tvMessage.append("1.AndroidManifest.xml中sharedUserId是否为com.termux\n"); + tvMessage.append("2.设备是否已root(部分机型需root才能跨包写私有目录)\n"); } } @@ -139,17 +144,17 @@ public class TermuxEnvTestActivity extends BaseWinBoLLActivity { String fileListStr = readTermuxHomeFileList(); tvMessage.append(fileListStr); - tvMessage.append("\n-------------------------\n"); + tvMessage.append("\n-------------------------\n"); LogUtils.d(TAG, "onTestTermuxEnv() 执行完成,读取结果长度:" + fileListStr.length() + "字符"); } /** - * 测试执行Gradle命令(唤起Termux窗口,修复source加载+目录容错) + * 测试执行Gradle命令(实时输出版,唤起Termux窗口) */ public void onTestTermuxCMD(View view) { - LogUtils.d(TAG, "onTestTermuxCMD() 按钮点击,执行Gradle命令(修复环境变量加载)"); - tvMessage.append("\n【测试:执行Gradle命令(Termux窗口)】\n"); + LogUtils.d(TAG, "onTestTermuxCMD() 按钮点击,执行Gradle命令(实时输出)"); + tvMessage.append("\n【测试:执行Gradle命令(实时输出)】\n"); // 1. 校验Termux是否安装 if (!TermuxCommandExecutor.isTermuxInstalled(this)) { @@ -162,19 +167,20 @@ public class TermuxEnvTestActivity extends BaseWinBoLLActivity { String gradleFullPath = "/data/data/com.termux/files/home/gradle/gradle-7.5.1/bin/gradle"; String projectPath = TERMUX_HOME_PATH + "/Sources/WinBoLL"; // 项目目录 - // 3. 构造命令(关键修复:&&前后加空格,目录容错,双重环境变量保障) + // 3. 构造命令(核心:用stdbuf禁用缓冲,实现实时输出) String targetCmd = ""; - // 步骤1:进入项目目录(不存在则创建,避免cd失败) + // 步骤1:进入项目目录(不存在则创建) targetCmd += "cd " + projectPath + " || (mkdir -p " + projectPath + " && cd " + projectPath + ") && "; - // 步骤2:加载bash环境变量(&&前后加空格,确保解析) + // 步骤2:加载环境变量 targetCmd += "source ~/.bashrc && "; - // 步骤3:显式添加Gradle路径到PATH(双重保障,避免source失效) + // 步骤3:显式配置PATH targetCmd += "export PATH=/data/data/com.termux/files/usr/bin:/data/data/com.termux/files/home/gradle/gradle-7.5.1/bin:$PATH && "; - // 步骤4:执行Gradle版本查询(指定完整路径,三重保障) - //targetCmd += gradleFullPath + " -v && "; - targetCmd += gradleFullPath + " task --all | grep assemble && "; - // 步骤5:执行成功提示,保持窗口打开 - targetCmd += "echo '\n✅ 命令执行成功!' && echo '\n📌 项目目录:" + projectPath + "' && read -p '按回车键关闭终端...'"; + // 步骤4:用stdbuf禁用stdout/stderr缓冲(关键!),执行Gradle命令 + // -o0:stdout无缓冲;-e0:stderr无缓冲;-i0:stdin无缓冲 + //targetCmd += "stdbuf -o0 -e0 -i0 " + gradleFullPath + " task --all | grep assemble && "; + targetCmd += "stdbuf -o0 -e0 -i0 " + gradleFullPath + " -Pandroid.aapt2FromMavenOverride=/data/data/com.termux/files/home/android-sdk/build-tools/34.0.4/aapt2 assembleBetaDebug && "; + // 步骤5:执行成功提示 + targetCmd += "echo '\n✅ 命令执行完成!' && echo '\n📌 项目目录:" + projectPath + "' && read -p '按回车键关闭终端...'"; LogUtils.d(TAG, "onTestTermuxCMD() 执行命令:" + targetCmd); @@ -182,20 +188,25 @@ public class TermuxEnvTestActivity extends BaseWinBoLLActivity { boolean cmdSuccess = TermuxCommandExecutor.executeTerminalCommand(this, targetCmd); if (!cmdSuccess) { LogUtils.e(TAG, "onTestTermuxCMD() 错误:命令发送失败"); - tvMessage.append("命令发送失败!\n可能原因:\n1.Termux未开启外部应用调用权限(执行termux-setup-storage后配置)\n2.sharedUserId配置不一致\n3.设备未root导致目录创建失败\n"); + tvMessage.append("命令发送失败!\n"); + tvMessage.append("可能原因:\n"); + tvMessage.append("1.Termux未开启外部应用调用权限(执行termux-setup-storage后配置)\n"); + tvMessage.append("2.sharedUserId配置不一致\n"); + tvMessage.append("3.Termux未安装stdbuf(执行pkg install coreutils)\n"); return; } - // 5. 应用内详细提示 - tvMessage.append("已唤起Termux窗口,执行流程:\n"); - tvMessage.append("1. 检查并创建项目目录:"); - tvMessage.append(projectPath); - tvMessage.append("\n"); - tvMessage.append("2. 加载Termux环境变量(source ~/.bashrc)\n"); - tvMessage.append("3. 执行Gradle版本查询\n"); + // 5. 应用内提示(说明实时输出特性) + tvMessage.append("已唤起Termux窗口,执行说明:\n"); + tvMessage.append("1. 自动创建/进入项目目录:"); + tvMessage.append(projectPath); + tvMessage.append("\n"); + tvMessage.append("2. 禁用输出缓冲(stdbuf),实现Gradle实时输出\n"); + tvMessage.append("3. 筛选assemble相关任务(grep assemble)\n"); tvMessage.append("⚙️ Gradle路径:"); - tvMessage.append(gradleFullPath); - tvMessage.append("\n"); + tvMessage.append(gradleFullPath); + tvMessage.append("\n"); + tvMessage.append("💡 若未实时输出,请在Termux中执行:pkg install coreutils(安装stdbuf)\n"); tvMessage.append("-------------------------\n"); } @@ -225,7 +236,8 @@ public class TermuxEnvTestActivity extends BaseWinBoLLActivity { br = new BufferedReader(new InputStreamReader(new FileInputStream(resultFile), StandardCharsets.UTF_8)); String line; while ((line = br.readLine()) != null) { - result.append(line).append("\n"); + result.append(line); + result.append("\n"); } LogUtils.d(TAG, "readCmdResultDirectly() 文件读取完成,结果长度:" + result.length() + "字符"); } catch (IOException e) { @@ -301,9 +313,18 @@ public class TermuxEnvTestActivity extends BaseWinBoLLActivity { } // 拼接结果字符串 - result.append("Termux主目录:").append(TERMUX_HOME_PATH).append("\n"); - result.append("文件/子目录总数:").append(files.length).append("\n"); - result.append("目录权限:").append("读:").append(termuxHomeDir.canRead()).append(" | 写:").append(termuxHomeDir.canWrite()).append("\n"); + result.append("Termux主目录:"); + result.append(TERMUX_HOME_PATH); + result.append("\n"); + result.append("文件/子目录总数:"); + result.append(files.length); + result.append("\n"); + result.append("目录权限:"); + result.append("读:"); + result.append(termuxHomeDir.canRead()); + result.append(" | 写:"); + result.append(termuxHomeDir.canWrite()); + result.append("\n"); result.append("-------------------------\n"); for (File file : files) { @@ -312,13 +333,20 @@ public class TermuxEnvTestActivity extends BaseWinBoLLActivity { String filePath = file.getAbsolutePath(); String fileSize = file.isFile() ? " | 大小:" + formatFileSize(file.length()) : ""; String filePerm = " | 权限:r:" + file.canRead() + "/w:" + file.canWrite(); - result.append(fileType).append(" ").append(fileName).append(fileSize).append(filePerm).append(" → ").append(filePath).append("\n"); + + result.append(fileType); + result.append(" "); + result.append(fileName); + result.append(fileSize); + result.append(filePerm); + result.append(" → "); + result.append(filePath); + result.append("\n"); } LogUtils.d(TAG, "readTermuxHomeFileList() 读取完成,结果长度:" + result.length() + "字符"); return result.toString().trim(); } - /** * 格式化文件大小(B→KB→MB) */ @@ -348,4 +376,3 @@ public class TermuxEnvTestActivity extends BaseWinBoLLActivity { LogUtils.d(TAG, "onDestroy() 执行完成"); } } -