Cloud-Kernel 开发文档
面向 Android 平台的内核驱动管理套件 —— 驱动选择与注入、PTY 终端交互、系统信息检测、在线更新与主题自定义。
01 项目概述
1.1 项目简介
Cloud-Kernel(云内核)是一款面向 Android 平台的内核驱动管理套件,提供内核驱动选择与注入、PTY 终端命令行交互、系统信息检测、在线更新和主题自定义等功能。该应用运行在已获取 Root 权限的 Android 设备上,通过 JNI 调用原生 C/C++ 代码,利用 PTY(伪终端)技术与系统 Shell 进行交互。
1.2 基本信息
| 属性 | 值 |
|---|---|
| 应用名称 | Cloud-Kernel |
| 包名 | com.js.fc |
| 版本号 | versionCode=1, versionName=1.5 |
| 最低 SDK | API 21 (Android 5.0) |
| 目标 SDK | API 29 (Android 10) |
| 开发语言 | Java (Android) + C++ (JNI) |
| 构建系统 | Android SDK + NDK (ndk-build) |
| 支持架构 | armeabi-v7a, arm64-v8a |
| 启动入口 | SplashActivity → MainActivity |
1.3 权限声明
| 权限 | 用途 |
|---|---|
INTERNET | 在线版本检查与文件下载 |
ACCESS_NETWORK_STATE | 检测网络状态 |
READ_EXTERNAL_STORAGE | 读取外部存储图片(背景图) |
WRITE_EXTERNAL_STORAGE (maxSdkVersion=28) | 写入外部存储 |
SYSTEM_ALERT_WINDOW | 悬浮窗口(预留) |
usesCleartextTraffic="true" 以允许 HTTP 明文流量,以及 requestLegacyExternalStorage="true" 以兼容 Android 10 的分区存储。02 项目结构
03 核心架构
3.1 整体架构图
3.2 页面导航
应用采用单 Activity + 四页面切换架构,通过底部 Dock 导航栏在四个页面间切换:
| 页面 | 索引 | 功能 |
|---|---|---|
| 首页 (page_home) | 0 | 系统状态、Root 检测、设备信息展示 |
| 驱动 (page_driver) | 1 | dits 工具下载与执行 |
| 终端 (page_terminal) | 2 | PTY Shell 交互终端 |
| 设置 (page_settings) | 3 | 主题、背景、更新、公告、资助 |
页面切换采用淡入淡出动画(alpha 属性动画,200ms),标签栏随选中状态改变颜色、字号和粗体。
04 启动页 (SplashActivity)
4.1 功能描述
SplashActivity 作为应用入口(LAUNCHER),展示品牌启动动画,2.5 秒后自动跳转到 MainActivity。
4.2 动画流程
| 阶段 | 时间线 | 动画描述 |
|---|---|---|
| 内容渐显 | 100ms | splash_content alpha 0→1,持续 200ms |
| 圆点呼吸 | 200ms | splash_dot 放大 1x→2.8x,alpha 1→0,持续 500ms,加速插值器 |
| 图标弹入 | 500ms | splash_icon 缩放 0→1,持续 800ms,OvershootInterpolator(1.5f) |
| 文字渐显 | 900ms | splash_text_group alpha 0→1,持续 400ms |
| 副标题渐显 | 1300ms | splash_subtitle alpha 0→1,持续 300ms |
| 下划线绘制 | 1600ms | splash_underline scaleX 0→1,持续 450ms |
| 跳转 | 2500ms | 启动 MainActivity,淡入淡出过渡 |
4.3 界面元素
| 元素 | 说明 |
|---|---|
| splash_dot | 16dp 圆形装饰点,背景 splash_dot_bg |
| splash_icon | 140dp 应用图标,ic_splash_icon |
| splash_title | "Cloud-Kernel",42sp,颜色 #D97757 |
| splash_subtitle | "绝世",24sp,颜色 #888888 |
| splash_underline | 4dp 高下划线,splash_underline_bg |
4.4 状态栏处理
- 白色状态栏背景 (
0xFFFFFFFF) - API 26+ 设置浅色状态栏图标 (
SYSTEM_UI_FLAG_LIGHT_STATUS_BAR) - API 28+ 适配刘海屏 (
LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES)
05 主界面 (MainActivity)
5.1 初始化流程
MainActivity.onCreate() 按以下顺序执行初始化:
setContentView(R.layout.activity_main)applyFullScreenImmersive()— 全屏沉浸式- 页面引用绑定 (pages[0-3], tabLabels, tabIcons, tabContainers)
- 终端视图引用 (tvTerminal, scrollTerminal, inputTerminal)
- Root 检测按钮绑定
initKernelDriver()— 驱动选择初始化initBackgroundImage()— 背景图片初始化initThemeColor()— 主题颜色初始化initTerminal()— 终端初始化initDriverPage()— 驱动页面初始化initSoftwareUpdate()— 软件更新初始化initKernelUpdate()— 内核更新初始化- 标签页点击事件绑定
fillDeviceInfo()— 填充设备信息refreshRootStatus()— 刷新 Root 状态loadCachedContent()— 加载缓存内容checkAnnouncementPopup()— 检查公告弹窗- 延迟 1000ms →
checkSoftwareUpdate() - 延迟 1500ms →
checkCloudUpdate() - 延迟 2000ms →
syncContent(公告) - 延迟 2500ms →
syncContent(资助)
5.2 生命周期
| 回调 | 行为 |
|---|---|
onResume() | 重新应用全屏沉浸式,刷新 Root 状态 |
onPause() | 保存所有偏好设置 (saveAllPrefs()) |
onDestroy() | 移除所有 Handler 回调,停止 PTY 会话 |
5.3 全屏沉浸式
applyFullScreenImmersive() 方法设置的标志位:
View.SYSTEM_UI_FLAG_LAYOUT_STABLE
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
| View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_FULLSCREEN
| View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY状态栏和导航栏颜色设为 #F9F9F7,API 30+ 额外调用 WindowInsetsController.hide() 隐藏状态栏。500ms 后重新应用标志位以确保生效。
06 首页 —— 设备信息与 Root 检测
6.1 设备信息展示
fillDeviceInfo() 方法通过 Build 类获取以下设备信息:
| 字段 | 数据来源 | 显示 ID |
|---|---|---|
| 设备指纹 | Build.FINGERPRINT | info_fingerprint |
| 内核版本 | System.getProperty("os.version") | info_kernel |
| Android 版本 | Build.VERSION.RELEASE + API Level | info_android |
| 设备型号 | Build.MANUFACTURER + Build.MODEL | info_device |
6.2 Root 权限检测
checkRootPermission() 方法采用双重检测策略:
第一层——文件存在检测:遍历以下 su 路径,检查文件是否存在:
/system/bin/su,/system/xbin/su,/system/app/Superuser.apk/sbin/su,/system/sbin/su,/vendor/bin/su/data/local/su,/data/local/xbin/su,/su/bin/su
第二层——功能验证:创建临时脚本 check_su.sh(内容为 id),通过 su -c 执行,读取输出并检查退出码是否为 0。
检测结果通过 indicator_root(绿色 / 灰色圆点)和 info_root_status("已获取"/"未获取",颜色绿/红)显示。
07 驱动内核管理
7.1 驱动选择器
应用提供 8 个驱动选项按钮:
| 索引 | 按钮 ID | 显示文本 | 特殊功能 |
|---|---|---|---|
| 0 | btn_drv_1 | 多驱动 | 展开子项选择 (sub_row) |
| 1 | btn_drv_2 | 绝世KPM旧 | — |
| 2 | btn_drv_3 | TwT驱动[推荐] | — |
| 3 | btn_drv_4 | 橘子驱动[停服] | — |
| 4 | btn_drv_5 | LQ驱动[推荐] | 展开触摸模式 (touch_row) |
| 5 | btn_drv_6 | Gin驱动 | — |
| 6 | btn_drv_7 | 绝世KPM[新版] | — |
| 7 | btn_drv_8 | TearGame | — |
7.2 子项选择(驱动 0 专属)
当选择"多驱动"时,展开子项选择行:
| 索引 | 按钮 ID | 显示文本 |
|---|---|---|
| 0 | btn_sub_0 | ditpro_kpm[很推荐] |
| 1 | btn_sub_1 | ditpro_ko |
| 2 | btn_sub_2 | qx(10.6)-ko |
| 3 | btn_sub_3 | rtdev-ko |
7.3 触摸模式(驱动 4 专属)
| 按钮 | 值 | 含义 |
|---|---|---|
btn_touch_off | "0" | 不启动 |
btn_touch_on | "1" | 启动 |
7.4 防录屏开关
| 按钮 | 值 | 含义 |
|---|---|---|
btn_scr_1 | "1" | 关闭 |
btn_scr_2 | "2" | 开启 |
7.5 运行内核命令
点击"运行"按钮时,根据当前驱动类型拼接命令:
# 驱动 0(多驱动)
printf "1\n0\n1\n" | {updateFilePath}
# 驱动 4(LQ驱动)
printf "5\n{touchInput}\n1\n" | {updateFilePath}
# 其他驱动
printf "N\n1\n" | {updateFilePath}执行前检查 updateFilePath 文件是否存在,执行后设置 5 秒冷却时间。
08 驱动管理页面 (Dits)
8.1 概述
驱动管理页面提供 dits 工具的下载和 6 种操作选项的执行。dits 是一个外部二进制工具,通过 execViaScript 方法以 root 权限执行。
8.2 下载流程
- 检查
ditsFilePath文件是否存在,若存在则标记ditsDownloaded = true - 点击下载按钮或执行操作时自动触发下载
- 下载 URL:
DITS_DOWNLOAD_URL(123 云盘链接) - 下载完成后自动执行
chmod 755设置可执行权限 - 状态更新为绿色"下载完成",操作按钮文字变为主题色
8.3 操作选项
6 个操作按钮对应 btn_drv_opt0_exec 到 btn_drv_opt5_exec,执行时:
- 若未下载,弹出下载提示对话框
- 若正在运行,忽略点击
- 将
drvOptSelected设为对应值 - 切换到终端页面显示输出
- 通过
startExecuteDits(option)执行
8.4 卡片折叠
驱动管理卡片头部 drv_card_header 点击可展开/折叠 drv_card_body,折叠时 drv_chevron 图标旋转 180°。
09 PTY 终端系统
9.1 JNI 接口 (PtyTerminal.java)
PtyTerminal 是 final 类,私有构造函数,通过静态块加载 libptyterm.so:
| 方法 | 参数 | 返回值 | 说明 |
|---|---|---|---|
nativeStart | String command, int rows, int cols | int[2] | 启动 PTY 执行命令,返回 [fd, pid] |
nativeStartShell | String shell, int rows, int cols | int[2] | 启动指定 Shell 的 PTY,返回 [fd, pid] |
nativeRead | int fd, int maxBytes | byte[] | 从 PTY 主设备读取数据 |
nativeWrite | int fd, byte[] data | int | 向 PTY 主设备写入数据 |
nativeResize | int fd, int rows, int cols | void | 调整 PTY 窗口大小 |
nativeWaitExit | int pid | int | 阻塞等待进程退出,返回退出码 |
nativeClose | int fd, int pid | void | 关闭 PTY 并终止进程 |
9.2 C++ 原生实现 (ptyterm.cpp)
9.2.1 构建配置
LOCAL_MODULE := ptyterm
LOCAL_SRC_FILES := ptyterm.cpp
LOCAL_LDLIBS := -llog
include $(BUILD_SHARED_LIBRARY)APP_ABI := armeabi-v7a arm64-v8a
APP_PLATFORM := android-21
APP_STL := c++_static9.2.2 my_openpty() —— PTY 创建
static int my_openpty(int *amaster, int *aslave, char *name,
const struct termios *termp,
const struct winsize *winp)流程:
posix_openpt(O_RDWR | O_NOCTTY)打开主 PTY 设备grantpt(master)授予从设备权限unlockpt(master)解锁从设备ptsname(master)获取从设备名称open(slave_name, O_RDWR | O_NOCTTY)打开从设备- 若提供 winsize,通过
ioctl(TIOCSWINSZ)设置窗口大小
9.2.3 startPty() —— 创建 PTY 并 Fork 进程
static jintArray startPty(JNIEnv *env, const char *cmd, jint rows, jint cols)流程:
- 设置 winsize(默认 24 行 x 80 列)
- 调用
my_openpty()创建 PTY fork()创建子进程
子进程:
setsid()创建新会话ioctl(slave_fd, TIOCSCTTY, 0)设置控制终端dup2()将 stdin/stdout/stderr 重定向到从设备- 关闭主设备 fd
- 设置环境变量:
TERM=dumb,PATH为 Android 系统路径,清空 PS1/PS2/PS4/PROMPT_COMMAND/BASH_ENV,HISTFILE=/dev/null - 若提供 cmd,执行
sh -c cmd;否则执行sh _exit(127)兜底
父进程:
- 关闭从设备 fd
- 设置 master fd 为
FD_CLOEXEC - 返回
int[2]:{master_fd, pid}
9.2.4 nativeStartShell() —— 启动指定 Shell 的 PTY
与 nativeStart 类似,区别在于子进程端执行:
const char *initCmd = "stty -echo 2>/dev/null; export PS1=''; export PS2=''; "
"export PS4=''; export PROMPT_COMMAND=''; exec /system/bin/sh";
execlp(shellPath, shellPath, "-c", initCmd, nullptr);
execl("/system/bin/sh", "sh", "-c", initCmd, nullptr); // 兜底9.2.5 nativeRead() —— 读取终端输出
JNIEXPORT jbyteArray JNICALL
Java_com_js_fc_PtyTerminal_nativeRead(JNIEnv *env, jobject, jint fd, jint maxBytes)maxBytes范围限制:≤ 0 时设为 4096,> 65536 时截断为 65536- 通过
read()系统调用读取数据 - 返回
byte[],若读取失败返回空数组
9.2.6 nativeWrite() —— 写入终端输入
JNIEXPORT jint JNICALL
Java_com_js_fc_PtyTerminal_nativeWrite(JNIEnv *env, jobject, jint fd, jbyteArray data)- 获取 Java 字节数组长度和内容
- 通过
write()系统调用写入 - 返回实际写入字节数
9.2.7 nativeResize() —— 调整终端窗口
JNIEXPORT void JNICALL
Java_com_js_fc_PtyTerminal_nativeResize(JNIEnv *, jobject, jint fd, jint rows, jint cols)通过 ioctl(fd, TIOCSWINSZ, &win) 发送窗口大小变更信号。
9.2.8 nativeWaitExit() —— 等待进程退出
JNIEXPORT jint JNICALL
Java_com_js_fc_PtyTerminal_nativeWaitExit(JNIEnv *, jobject, jint pid)- 阻塞调用
waitpid(pid, &status, 0) - 若被 EINTR 中断,继续等待
- 正常退出返回退出码,信号终止返回
128 + 信号编号
9.2.9 nativeClose() —— 关闭 PTY 和终止进程
JNIEXPORT void JNICALL
Java_com_js_fc_PtyTerminal_nativeClose(JNIEnv *, jobject, jint fd, jint pid)- 关闭 fd
- 向进程发送
SIGTERM - 轮询等待最多 20 次(每次 50ms),检查进程是否退出
- 若仍未退出,发送
SIGKILL强制终止
9.3 Java 层终端管理
9.3.1 终端会话启动
startTerminalSession() 在后台线程中执行:
- 通过
computeTermSize()计算终端行列数 - 优先尝试
PtyTerminal.nativeStartShell("su", rows, cols)启动 root shell - 若失败,回退到
PtyTerminal.nativeStartShell("/system/bin/sh", rows, cols) - 保存
ptyFd和ptyPid,标记ptySessionAlive = true - 清空终端显示,调整窗口大小
- 启动读取线程
9.3.2 终端输出读取
startPtyReader() 在守护线程中循环读取:
while (ptyReading && ptyFd >= 0) {
byte[] data = PtyTerminal.nativeRead(ptyFd, 4096);
if (data == null || data.length == 0) break;
String clean = sanitizeTerminalOutput(chunk);
if (clean.length() > 0) appendTerminal(clean);
}9.3.3 终端输出过滤
sanitizeTerminalOutput() 和 isUiTerminalNoise() 负责过滤不需要的输出:
- ANSI 转义序列过滤:
stripAnsi()移除 ESC 序列(CSI 序列和 OSC 序列) - UI 噪音过滤:移除应用的 UI 提示消息(如 [错误]、[提示]、[完成]、[会话已结束] 等)
- 提示符过滤:移除单独的
$、#、>、%提示符 - 命令回显过滤:移除以
#、$、>、%开头的行,以及以这些符号结尾的路径行
9.3.4 终端大小计算
computeTermSize() 通过测量 TextView 的字符宽度和行高计算最优行列数:
float charW = paint.measureText("M");
float lineH = paint.getFontSpacing() + dp(3);
cols = Math.max(20, (int)(w / charW));
rows = Math.max(5, (int)(h / lineH));9.3.5 命令发送
sendTerminalCmd() 从输入框获取命令,通过 nativeWrite 写入 PTY master fd,命令末尾追加 \n。
9.3.6 会话终止
stopPtySession() 停止读取线程,调用 nativeClose(fd, pid) 关闭 PTY 并终止进程。
10 内核命令执行
10.1 execViaScript()
内核命令通过写入临时 Shell 脚本文件执行,避免命令注入和参数转义问题:
private void execViaScript(File parentDir, String scriptName,
String cmdContent, ShellLineCallback cb)流程:
- 在 parentDir 下创建脚本文件
- 写入
#!/system/bin/sh\n{cmdContent} - 通过
runPtyCommand("su -c 'sh {scriptPath}'", cb)以 root 权限执行 - 执行完成后删除脚本文件
10.2 runPtyCommand()
创建临时 PTY 会话执行命令,逐行回调输出:
private void runPtyCommand(String cmd, ShellLineCallback cb)- 使用
nativeStart而非nativeStartShell(一次性命令执行) - 循环读取输出,按
\n分割逐行回调 - 忽略
\r字符 - 命令结束后调用
nativeWaitExit获取退出码,然后nativeClose
10.3 stdbuf 检测
hasStdbuf() 检测系统中是否存在 stdbuf 命令,用于 wrapUnbuffered() 方法。若存在,在命令前添加 stdbuf -oL -eL 以禁用输出缓冲,确保实时获取输出。
11 在线更新系统
11.1 更新架构
应用包含两套独立的更新系统:
| 更新类型 | 版本检查 URL | 下载 URL | 本地文件名 |
|---|---|---|---|
| 内核更新 | http://xn--evv35d.top:6861/version | http://xn--evv35d.top:6861/Download | update_kernel |
| 软件更新 | http://xn--evv35d.top:6864/version | http://xn--evv35d.top:6864/Download | update_software.apk |
11.2 内核更新流程
手动检查(checkKernelUpdate())不受 24 小时休眠限制,始终弹出更新对话框。
11.3 软件更新流程
11.4 下载引擎
downloadToFile() 方法特性:
- 支持 HTTP 重定向(301/302/303/307/308),最多 10 次
- 相对 URL 自动解析为绝对 URL
- 8KB 缓冲区流式写入
- 每 80ms 回调一次进度(下载量、总量、百分比、速度)
- 下载完成后自动
chmod 755和su -c chmod 755
11.5 更新休眠机制
取消更新后 24 小时内不再弹出相同类型的更新提示,通过 SharedPreferences 存储休眠截止时间戳。
12 内容同步系统
12.1 公告与资助
应用从服务器拉取公告和资助信息:
| 内容 | 缓存 Key | 哈希 Key | URL |
|---|---|---|---|
| 公告 | cache_announce | cache_announce_hash | https://xn--evv35d.top/软件公告.txt |
| 资助 | cache_funding | cache_funding_hash | https://xn--evv35d.top/资助.txt |
12.2 同步机制
syncContent() 方法:
- 通过
fetchTextFile()获取文本内容(5 秒超时) - 计算 SHA-256 哈希
- 与缓存哈希比较,相同则跳过
- 不同则更新 UI 和缓存
12.3 公告弹窗
应用启动时检查公告更新:
- 获取最新公告内容
- 计算 SHA-256 哈希
- 与
PREF_ANNOUNCE_LAST_SHOWN_HASH比较 - 不同则弹出公告对话框
- 用户点击"知道了"后记录已读哈希
12.4 可点击链接
buildClickableAnnouncementText() 解析公告文本中的 URL(https://、http://、www. 开头),将其渲染为可点击的 ClickableSpan,颜色为主题色,点击后通过 ACTION_VIEW 在浏览器中打开。
13 主题系统
13.1 预设主题
| 索引 | 名称 | 主色 | 渐变尾色 |
|---|---|---|---|
| 0 | 柠檬绿 | #A9E657 | #CDEE9A |
| 1 | 翡翠绿 | #10B981 | #6EE7B7 |
| 2 | 红色 | #EF4444 | #FCA5A5 |
| 3 | 紫色 | #8B5CF6 | #C4B5FD |
| 4 | 橙色 | #F97316 | #FDBA74 |
13.2 自定义颜色
通过 Rainbow SeekBar(0-359 色相)选择自定义颜色。SPECIAL_COLORS 数组定义了 9 个渐变色节点,通过 HSV 插值实现平滑过渡:
private static final int[] SPECIAL_COLORS = {
0xFFFF6B6B, 0xFFFFA94D, 0xFFFFD93D, 0xFF6BCB77,
0xFF4DD0E1, 0xFF4D96FF, 0xFFA55EEA, 0xFFFF6BB3, 0xFFFF6B6B
};自定义颜色时 themeSchemeIndex = -1,渐变尾色通过降低饱和度(0.45)生成。
13.3 渐变开关
switch_theme_gradient 控制是否启用渐变效果。启用后按钮、进度条等使用 themeColor → themeGradientEnd 的线性渐变(TL_BR 方向)。
13.4 主题应用范围
applyThemeColor() 影响以下 UI 元素:
- 标签栏文字和图标颜色
- 设置页标题文字颜色
- 进度条颜色(
PorterDuffColorFilter) - 按钮背景渐变(
applyGradientToButton) - Switch 组件的 thumb 和 track 颜色
- Chevron 图标颜色
- RGB 十六进制标签背景和文字颜色
13.5 主题预览
updateThemePreviewBar() 在设置页显示当前主题的实时预览条,支持纯色和渐变两种模式。
14 背景图片系统
14.1 功能
用户可为首页、驱动页、终端页设置自定义背景图片,并调整透明度。
14.2 图片选择
pickBackgroundImage() 根据 Android 版本采用不同策略:
- API 33+:先通过
su -c pm grant授予READ_MEDIA_IMAGES权限,再调用ACTION_OPEN_DOCUMENT选择图片 - API 23-32:检查
READ_EXTERNAL_STORAGE权限,必要时请求运行时权限 - API 22 及以下:直接启动图片选择器
14.3 图片加载
loadBgImageFromUri() 使用 BitmapFactory.Options 采样加载,限制最大宽度为 2048px,避免 OOM。通过 BitmapDrawable 设置背景,初始 alpha 值由 imgAlpha 决定。
14.4 透明度调节
SeekBar(0-255)控制背景透明度,updateBgImageAlpha() 实时更新三个页面的背景 alpha。
14.5 持久化
图片 URI 通过 takePersistableUriPermission() 获取持久读取权限,URI 字符串和 alpha 值保存到 SharedPreferences。
15 动画系统
15.1 弹性动画
springAnim(View v) 实现按钮点击弹性效果:
15.2 按压效果
applyPressEffect(View v) 为按钮添加触摸反馈:
| 事件 | 动画 |
|---|---|
ACTION_DOWN | scale 1.0→0.92 (80ms),叠加半透明黑色前景 |
ACTION_UP | scale 0.92→1.0 (350ms, OvershootInterpolator 2.0f),移除前景 |
ACTION_CANCEL | scale 恢复 1.0 (200ms),移除前景 |
applyPressEffectNoShadow() 是简化版,无前景叠加效果。
15.3 对话框动画
animateUnifiedDialog() 为对话框添加弹出动画:
15.4 页面切换动画
switchPage() 在页面间切换时:
- 旧页面:alpha 1→0 (200ms),完成后隐藏
- 新页面:alpha 0→1 (200ms,延迟 100ms)
- 标签栏:选中态颜色、字号、粗体变化
- 轻量弹性动画:scale 1.0→0.94→1.0 (320ms, OvershootInterpolator 1.8f)
16 数据持久化
16.1 SharedPreferences
应用使用两个 SharedPreferences 实例:
| 实例名 | 用途 |
|---|---|
kernel_prefs | 用户偏好设置 |
cache_prefs | 缓存内容(公告、资助) |
16.2 持久化字段
| 键 | 类型 | 默认值 | 说明 |
|---|---|---|---|
curDrv | int | 0 | 当前选中驱动索引 |
drvInput | String | "1" | 驱动编号 |
subInput | String | "0" | 子项选择 |
touchInput | String | "0" | 触摸模式 |
scrInput | String | "1" | 防录屏开关 |
bgImageUri | String | null | 背景图片 URI |
imgAlpha | int | 255 | 背景透明度 |
cloudVersion | String | "0" | 云内核版本 |
drvOptSelected | int | -1 | 驱动操作选项 |
themeSchemeIndex | int | 0 | 主题方案索引 |
themeGradientEnabled | boolean | false | 渐变开关 |
themeCustomR/G/B | int | 255/122/255 | 自定义主题 RGB |
subMem_0~7 | int | 0 | 各驱动的子项记忆 |
touchMem_0~7 | int | 0 | 各驱动的触摸记忆 |
software_update_snooze_until | long | 0 | 软件更新休眠截止 |
kernel_update_snooze_until | long | 0 | 内核更新休眠截止 |
17 颜色系统
17.1 颜色定义 (colors.xml)
| 颜色名称 | 色值 | 用途 |
|---|---|---|
bgPrimary | #F9F9F7 | 主背景色 |
bgSecondary | #FFFFFF | 次背景色 |
bgCard | #FFFFFF | 卡片背景 |
bgCardHover | #F0F1F5 | 卡片悬停 |
bgSurface | #EEF0F4 | 表面色 |
accentPrimary | #007AFF | 默认强调色 |
accentPrimaryDark | #0066E0 | 深色强调 |
accentSecondary | #66B0FF | 浅色强调 |
textPrimary | #1A1A2E | 主文字色 |
textSecondary | #6B7280 | 次文字色 |
textTertiary | #9CA3AF | 三级文字色 |
textOnAccent | #FFFFFF | 强调色上文字 |
successGreen | #10B981 | 成功绿 |
errorRed | #EF4444 | 错误红 |
warningOrange | #F59E0B | 警告橙 |
borderSubtle | #E5E7EB | 淡边框 |
borderMedium | #D1D5DB | 中边框 |
borderAccent | #007AFF | 强调边框 |
iconActive | #007AFF | 激活图标 |
iconInactive | #9CA3AF | 未激活图标 |
terminalBg | #F9FAFB | 终端背景 |
terminalText | #1F2937 | 终端文字 |
terminalPrompt | #007AFF | 终端提示符 |
dockBg | #E6FFFFFF | Dock 背景 |
dockBorder | #E5E7EB | Dock 边框 |
18 Drawable 资源说明
| 文件 | 类型 | 说明 |
|---|---|---|
btn_outline.xml | shape | 轮廓按钮 |
btn_primary.xml | shape | 主按钮 |
btn_primary_small.xml | shape | 小号主按钮 |
card_bg.xml | shape | 卡片背景 |
color_circle_*.xml | shape | 彩色圆点(蓝/绿/青柠/橙/紫/红) |
dialog_bg.xml | shape | 对话框背景 |
dialog_btn_cancel.xml | shape | 对话框取消按钮 |
dialog_btn_confirm.xml | shape | 对话框确认按钮 |
dock_glass_bg.xml | shape | Dock 毛玻璃背景 |
driver_btn_off.xml | shape | 驱动按钮(未选中) |
driver_btn_on.xml | shape | 驱动按钮(选中) |
ic_chevron_down.xml | vector | 向下箭头图标 |
ic_drive.xml | vector | 驱动图标 |
ic_home.xml | vector | 首页图标 |
ic_launcher_background.xml | vector | 启动器背景 |
ic_launcher_foreground.xml | vector | 启动器前景 |
ic_settings.xml | vector | 设置图标 |
ic_splash_icon.xml | vector | 启动页图标 |
ic_terminal.xml | vector | 终端图标 |
indicator_active.xml | shape | 激活指示器(绿色圆点) |
indicator_inactive.xml | shape | 未激活指示器(灰色圆点) |
seekbar_thumb.xml | shape | SeekBar 滑块 |
splash_dot_bg.xml | shape | 启动页圆点背景 |
splash_icon_bg.xml | shape | 启动页图标背景 |
splash_underline_bg.xml | shape | 启动页下划线 |
terminal_bg.xml | shape | 终端背景 |
19 构建与部署
19.1 构建前提
- Android SDK(API 29)
- Android NDK(支持 ndk-build)
- JDK 8+
19.2 NDK 构建
在 jni/ 目录执行:
ndk-build生成产物:
libs/armeabi-v7a/libptyterm.solibs/arm64-v8a/libptyterm.so
19.3 APK 构建
使用 Android SDK 构建工具:
android update project --path . --target android-29
ant debug或使用 Android Studio / Gradle 导入项目后构建。
19.4 签名与发布
应用使用 HTTP 明文通信,部署时需注意:
- 确保服务器支持 HTTP 访问
- 目标设备需已获取 Root 权限
- 应用通过在线更新分发,初始安装通过 APK 侧载
20 关键类与方法索引
20.1 MainActivity 成员变量
| 变量 | 类型 | 说明 |
|---|---|---|
pages[4] | View[] | 四个页面视图 |
tabLabels[4] | TextView[] | 标签文字 |
tabIcons[4] | ImageView[] | 标签图标 |
tabContainers[4] | View[] | 标签容器 |
drvBtns[8] | Button[] | 驱动按钮 |
subBtns[4] | Button[] | 子项按钮 |
touchBtns[2] | Button[] | 触摸模式按钮 |
scrBtns[2] | Button[] | 防录屏按钮 |
curDrv | int | 当前驱动索引 |
subMem[8] | int[] | 各驱动子项记忆 |
touchMem[8] | int[] | 各驱动触摸记忆 |
ptyFd | volatile int | PTY master fd |
ptyPid | volatile int | PTY 子进程 PID |
ptySessionAlive | volatile boolean | PTY 会话状态 |
themeColor | int | 当前主题色 |
themeGradientEnabled | boolean | 渐变开关 |
bgImageUri | String | 背景图片 URI |
imgAlpha | int | 背景透明度 |
20.2 MainActivity 方法索引
| 方法 | 说明 |
|---|---|
onCreate() | 初始化入口 |
applyFullScreenImmersive() | 全屏沉浸式 |
switchPage(int) | 页面切换 |
springAnim(View) | 弹性动画 |
applyPressEffect(View) | 按压效果 |
showUnifiedNotice(String, String) | 统一通知弹窗 |
fillDeviceInfo() | 填充设备信息 |
checkRootPermission() | 检测 Root 权限 |
checkSu() | su 文件检测 |
refreshRootStatus() | 刷新 Root 状态 |
initKernelDriver() | 初始化驱动选择器 |
updateDrvUI(int) | 更新驱动 UI |
runKernelInternal(String) | 执行内核命令 |
initTerminal() | 初始化终端 |
startTerminalSession() | 启动 PTY 会话 |
startPtyReader() | 启动 PTY 读取线程 |
sendTerminalCmd() | 发送终端命令 |
sanitizeTerminalOutput(String) | 过滤终端输出 |
stopPtySession() | 停止 PTY 会话 |
initBackgroundImage() | 初始化背景图 |
pickBackgroundImage() | 选择背景图 |
loadBgImageFromUri(Uri) | 加载背景图 |
initThemeColor() | 初始化主题 |
applyTheme(int) | 应用预设主题 |
applyCustomColor(int) | 应用自定义颜色 |
applyThemeColor() | 刷新主题色 |
initSoftwareUpdate() | 初始化软件更新 |
checkSoftwareUpdate() | 检查软件更新 |
startDownloadApk() | 下载 APK |
installSoftwareApk() | 安装 APK |
initKernelUpdate() | 初始化内核更新 |
checkKernelUpdate() | 检查内核更新 |
checkCloudUpdate() | 自动检查云更新 |
downloadToFile(String, File, DownloadCallback) | 通用下载 |
initDriverPage() | 初始化驱动页面 |
startDownloadDits() | 下载 dits 工具 |
startExecuteDits(int) | 执行 dits 操作 |
execViaScript(...) | 通过脚本执行命令 |
runPtyCommand(String, ShellLineCallback) | PTY 命令执行 |
syncContent(...) | 同步服务器内容 |
buildClickableAnnouncementText(String) | 构建可点击公告 |
saveAllPrefs() / loadAllPrefs() | 偏好设置读写 |
21 注意事项
21.1 安全性
- 应用通过
su -c以 root 权限执行命令,存在安全风险,仅应在受信任设备上使用 - 内核文件通过 HTTP 明文传输,未使用 HTTPS 加密,存在中间人攻击风险
- 下载的内核文件直接赋予可执行权限并执行,未进行签名验证
21.2 兼容性
- 最低支持 Android 5.0 (API 21),但实际功能依赖 Root 权限和 su 命令
- 不同厂商的 Android 系统对 PTY 的支持可能不同
- 存储权限处理区分了 API 33(
READ_MEDIA_IMAGES)和 API 23(READ_EXTERNAL_STORAGE) - 背景图片选择在 API 33+ 设备上通过
pm grant授权,依赖 su 可用
21.3 性能
- PTY 终端输出在 4KB 缓冲区中循环读取,高频输出时可能存在延迟
- 背景图片加载限制最大宽度 2048px,通过采样减少内存占用
- 下载使用 8KB 缓冲区,进度回调间隔 80ms
- 更新休眠机制 24 小时,避免频繁网络请求
21.4 代码规范
MainActivity.java将所有逻辑集中在单个类中,约 3400 行,建议按功能模块拆分- 硬编码的 URL 和字符串分散在代码中,建议集中管理
- 部分异常处理使用空的
catch (Throwable t) {}静默吞掉异常,不利于调试 - 大量使用匿名内部类和
runOnUiThread,增加了代码复杂度