一个能塞进口袋的 AI 编程工作台。 在 Android 上接入主流大模型,让它直接读写你的项目文件、跑 Shell、用 SSH 连远程主机,或者接入一个可插拔的 IPC Provider —— 一切都在手机本地完成。
LineCode Pro 是一款面向 Android 8.0+ 的本地化 AI 编程助理。它围绕"一个 Activity + 一段流式聊天 + 一套真正可执行的工具循环"组织代码。你只要指定一个项目目录(本地、SSH 远程,或第三方 IPC Provider),接好一个大模型,模型就能读取、编辑、glob、新建、删除文件,能跑 Shell、能抓取和搜索网页、能理解和生成图片,还能分派子任务。
LineCode 不是一个轻量聊天客户端,它是一个完整的编程工作台:系统提示、工具注册表、上下文管理、Diff 存档、文件树、项目选择器、SSH / IPC 管道、导入导出归档、扩展框架、安全策略……全部跑在 App 内部。除非你自己接到远程模型,否则项目文件不会离开你的手机。
应用包名是 cn.lineai,仓库采用 12 模块 Gradle 结构::build-logic(composite build)、:core-model、:core-api、:core-security、:ui-theme、:markdown、:data、:feature-tool、:feature-model、:feature-ssh、:feature-share、:app,外加可复用库 :ipc 与示例 Provider :terminal-provider。
- 同一个聊天界面下支持多种模型协议:OpenAI 兼容 HTTP API、Anthropic Messages、OpenAI Codex Responses、本地 GGUF 推理。
- 推理块(
<think>…</think>)会被ThinkTagParser单独抽出来,和最终回答分块渲染。 - 流中的工具调用文本由
ToolCallTextParser解析并派发;模型请求做的每件事,在真正执行前都会先展示给你看。 - 系统提示由
feature-model/src/main/assets/prompts/*.txt中的模板拼装:语气(聊天 / 编程)变体、上下文压缩、记忆抽取、技能抽取、工作目录、学习上下文、模型身份。你可以在设置里覆盖语气、工作目录、身份块、提示模板。 - 长对话由
ContextCompactionService后台用当前模型本身做动态压缩(50% 软触发 + 80% 硬触发);MemoryExtractionService抽取长期知识,LearningContextRepository在下一次会话中喂回上下文。 - 图片附件 - 在输入框右侧点图片按钮打开系统选择器;选中的图片经压缩后 base64 编码,按协议格式输出(OpenAI
image_url、Anthropicimage.source.base64、Codexinput_image)。
模型可以调用 ToolRegistry 里的全部工具,并支持会话级自动确认:
| 分类 | 内置工具 |
|---|---|
| 文件系统 | file_read、file_write、file_edit、file_delete、glob、list_directory |
| Shell | shell_execute(经 Termux 或 IPC Provider) |
| 网络 | web_search、web_fetch |
| 媒体 | image_understanding、image_generation |
| 子任务 | agent、agent_pipeline(分派给另一个 LLM 循环) |
| 效率 | todo_update |
每个会触碰文件的工具都走 FileToolPathPolicy 路径校验,模型只能动你授权的目录里的内容。Shell 调用走 Termux 或 IPC Provider —— 永远不在 App 自身进程里跑命令。
- 动态压缩 -
ContextCompactionService在上下文窗口占用 50% 时触发软压缩(最早 70% 被总结、最近 30% 原文保留),80% 时硬压缩兜底;转录文本按 256KB 分段拼接防 OOM。 - 工具结果截断 -
ToolResult.truncateContent()强制 50KB 上限:超过 50KB 中间截断(前 25KB + 截断提示 + 后 25KB)。Shell 输出同样截断。 - 大文件防护 -
FileReadTool使用 KB 参数(start_kb/end_kb,50KB 上限);超过 1MB 的文件直接拒绝读取。 - 模型上下文大小 - 支持
k/m单位输入(如128K、1m),由ContextSizeParser解析;旧{id}[{size}]格式通过ModelContextParser兼容。
- 本地 —— 通过系统 Storage Access Framework 选择器选一个目录,App 会在重启后记住。授权
MANAGE_EXTERNAL_STORAGE后,模型可以对真实项目目录做 glob。 - SSH —— 通过
jsch远程浏览、读写、执行;凭据加密存在设置仓库里。 - IPC Provider(可插拔) —— 绑定到任何对外暴露
cn.lineai.action.IPC_TERMINAL_PROVIDER动作和ITerminalProviderServiceAIDL 接口的第三方 App。仓库自带的terminal-provider模块就是参考实现,把命令和文件操作跑在独立进程里。 - 自定义 Agent / MCP —— 在 扩展 页面注册
agentx_/mcpx_工具,模型可以像调用内置工具一样调用它们。
- 每次成功的
file_write/file_edit都会在DiffRepository里生成一条DiffRecord;聊天流里能看到内联变更,存储 → Diff 历史 页面可以回放。 - Shell 跑在自定义的
ToolCallShellView中流式输出;Agent 跑在ToolCallAgentView/ToolCallAgentPipelineView卡片中实时显示进度。
- 一个
.linecode归档里包含整库(对话、消息、记忆、设置、扩展)和工作区文件。敏感信息 —— 模型 API key、SSH 凭据、网页搜索 key、敏感 MCP 请求头 —— 在写入前由ArchiveSecretRedactor自动剥离。 - 导入流程需要显式确认,因为它会覆盖本地数据。
- 所有持久化都走 SQLite(
LineCodeDatabase单例,schema 在LineCodeSchema)和"一个关注点对应一个仓库"的设计。控制器不直接操作数据库。
- 一个聊天,多家后端。 OpenAI 兼容、Anthropic Messages、Codex Responses、本地 GGUF 在同一 UI 内任意切换。
- 真正能干活的工具循环。 模型能读、改、glob、新建、删除文件,能跑 Shell,能抓取和搜索网页,能看图,能生图,能递归调子任务 —— 全部由你逐条审批或会话级自动确认。
- 可在任意目录工作。 本地(SAF + 可选
MANAGE_EXTERNAL_STORAGE)、远程(jsch SSH)、或第三方 IPC Provider。 - 支持自定义扩展。 自定义 Agent(
agentx_*)和 MCP-HTTP 工具(mcpx_*)即配即用。 - 可插拔 IPC Provider。 把 Shell 和文件操作放到独立进程里以做安全隔离。可以把 Provider 当成普通 Android App 上架,详见
ipc/README.md。 - 记忆与上下文。 动态压缩(50% 软触发 + 80% 硬触发)+ 分段拼接转录。长期知识会在下一次会话注入。
- 上下文溢出防护。 工具结果 50KB 中间截断;文件读取使用 KB 参数;超过 1MB 的文件直接拒绝。
- 免费网页搜索。 内置 Bing RSS 搜索 Provider,无需任何 API key。
- 默认隐私优先。 URL 白名单、严格
network_security_config.xml、导出文件去敏、内置浏览器默认关闭 JavaScript。 - 纯 Java 写在骨子里。 无 Kotlin 运行时、无 XML 布局 —— App 全部由 Java 11 写成,便于审计。
LineCode/
├── build-logic/ # composite build,linecode.convention 约定插件
├── core-model/ # :core-model — 纯数据类 / DTO / 枚举
│ └── src/main/java/cn/lineai/model/ # ModelConfig、ThemePalette、OutputSettings、
│ # ContextSizeParser、ModelContextParser、ChatMessage、ToolResult…
├── core-api/ # :core-api — 接口抽象
│ └── src/main/java/cn/lineai/ # ToolInfo、ToolNames、ToolCategory、ToolDisplayCategory、
│ # ModelServiceProvider、WebSearchProvider
├── core-security/ # :core-security — UrlPolicy、SimpleHttpClient
├── ui-theme/ # :ui-theme — LineTheme 及共享 UI 基础设施
│ └── src/main/java/cn/lineai/ui/theme/ # LineTheme(被约 80 个文件引用)
├── markdown/ # :markdown — Markdown 渲染(commonmark + GFM tables)
│ └── src/main/java/cn/lineai/ui/markdown/
├── data/ # :data — 仓库 / 数据库 / 导入导出 / 错误日志
│ └── src/main/java/cn/lineai/
│ ├── data/db/ # LineCodeDatabase、LineCodeSchema、迁移
│ ├── data/repository/ # 所有仓库(对话、模型、Diff、扩展…)
│ ├── data/importer/ # ArchiveSecretRedactor、LineCodeDatabaseArchive
│ ├── log/ # ErrorLog、ErrorLogRedactor
│ └── workspace/ # WorkspacePaths
├── feature-tool/ # :feature-tool — BaseTool、ToolRegistry、全部内置工具
│ └── src/main/java/cn/lineai/tool/
│ ├── BaseTool.java、ToolRegistry.java、ToolContext.java、ToolArgsCleaner.java
│ └── builtin/ # FileReadTool、FileWriteTool、FileEditTool、ShellExecuteTool、
│ # WebSearchTool、WebFetchTool、AgentTool、AgentPipelineTool…
├── feature-model/ # :feature-model — 协议、ModelClient、ContextManager、提示词模板
│ └── src/main/
│ ├── assets/prompts/ # 全部 .txt 提示词模板(系统、压缩、Agent…)
│ └── java/cn/lineai/
│ ├── ai/protocol/ # ModelProtocol、OpenAiCompatibleProtocol、AnthropicMessagesProtocol…
│ ├── ai/prompt/ # SystemPromptProvider、StringTemplate
│ ├── context/ # ContextManager、ContextCompactionService
│ └── ai/message/ # SystemModelMessage、UserModelMessage 等
├── feature-ssh/ # :feature-ssh — SshService、SshConnectionPool、TermuxHelper
├── feature-share/ # :feature-share — 导出 / 分享 / PDF
├── app/ # :app — MainActivity、MainCoordinator、控制器、UI 组件
│ ├── build.gradle.kts
│ ├── lint.xml
│ ├── proguard-rules.pro
│ └── src/
│ ├── main/
│ │ ├── AndroidManifest.xml
│ │ ├── aidl/ # IPC AIDL 存根
│ │ ├── java/cn/lineai/
│ │ │ ├── MainActivity.java
│ │ │ ├── mvp/ # MainCoordinator + 各关注点控制器
│ │ │ ├── ui/ # Java 写的视图(不 inflate XML)
│ │ │ └── tool/ # ToolExecutor、ToolExecutionCoordinator(装配)
│ │ └── res/ # 矢量图、字符串、主题
│ ├── test/ # JUnit 4 单元测试
│ └── debugUserCert/ # 旁加载 build flavor
├── ipc/ # :ipc — 可复用 Android 库(cn.lineai.ipc)
│ ├── build.gradle.kts
│ └── src/main/
│ ├── AndroidManifest.xml # <permission> cn.lineai.permission.IPC_TERMINAL_PROVIDER
│ ├── aidl/ # IBaseIpcService + terminal 接口
│ └── java/cn/lineai/ipc/ # BaseIpcProvider、IpcProviderManager、注册表、扫描器
├── terminal-provider/ # :terminal-provider — 示例 Provider App(cn.lineai.terminalprovider)
│ ├── build.gradle.kts
│ ├── proguard-rules.pro
│ └── src/main/
│ ├── AndroidManifest.xml # <service> 上强制 android:permission
│ └── java/cn/lineai/terminalprovider/TerminalProviderService.java
├── docs/ # 合规审计、威胁模型
├── gradle/libs.versions.toml # 版本目录
├── settings.gradle.kts
├── build.gradle.kts
├── CLAUDE.md # 面向 AI / 评审者的架构圣经
├── README.md / README_CN.md # ← 你正在看这里
└── LICENSE
MainActivity是唯一的 Activity,它实例化MainCoordinator(Presenter)和MainChatView(View),View 完全由 Java 代码构建 —— 不 inflate XML;lint.xml故意屏蔽ViewConstructor。MainCoordinator实现MainUiController,把行为分派给cn.lineai.mvp.*下各关注点控制器(聊天、生成、工具执行、模型管理、设置、页面、权限模式、归档、项目面板、SSH 文件树、IPC 文件树、文件操作、Agent 执行、上下文压缩、手机控制、错误日志、存储维护)。UI 状态走ChatUiStateAssembler→ChatUiState→MainContract.View.render(...)通路。cn.lineai.ai.protocol.ModelProtocol是流式 / Completion 接口,ModelProtocolFactory按ModelProtocolType分派(OPENAI_COMPATIBLE、CODEX_RESPONSES、ANTHROPIC_MESSAGES、LOCAL_GGUF)。每个协议通过supportsNativeTools()/supportsContextCompaction()/supportsImageGeneration()/supportsImageUnderstanding()声明自身能力。BaseTool(name、description、category、JSON schema、execute(JSONObject, ToolContext))是工具契约;ToolRegistry注册内置并热加载用户扩展;ToolExecutionCoordinator+ToolExecutor执行;PermissionModeController+ToolReviewListener控制逐条审批。- 模块依赖规则:
:app→:feature-*→:data→:core-model/:core-api/:core-security。ai ↔ tool循环依赖已打破::feature-tool不得引用cn.lineai.ai,:feature-model只引用:core-api中的ToolInfo/ToolNames/ToolCategory。
完整架构圣经(控制器、工具系统、上下文管理、SQLite schema、安全模型)见 CLAUDE.md。
方式 A —— 下载预编译 APK。 在 Releases 页面下载最新的 LineCode Pro <version>.APK,旁加载安装。release 版本用私钥签名(见 signing.properties);debug 版本用 debug 证书签名,适合临时测试。
方式 B —— 从源码构建。 见 从源码构建。
关于存储权限的提示。 LineCode 默认申请
MANAGE_EXTERNAL_STORAGE,这样 AI 才能对真实项目目录做 glob 和编辑。如果你不愿授权,也可以只通过系统文档选择器选目录 —— 大部分功能仍然能用,但对超大目录的 glob 会变慢。
- 授予存储权限。 首次启动时 LineCode 会请求所需的存储权限,授权后文档选择器才可用。
- 添加模型。 抽屉 → 模型 → 新增模型。挑一个协议:
- OpenAI 兼容 —— Base URL、API key、模型名。适用于 OpenAI、DeepSeek、通义千问、Moonshot、智谱、Groq、Ollama、llama.cpp server …
- Anthropic Messages —— Base URL、API key、模型名(Claude 4.x 与 3.x)。
- Codex Responses —— Base URL、API key、模型名。
- 本地 GGUF —— 设备本地 llama.cpp 推理。
- 选一个工作区。 抽屉 → 项目 → 打开外部目录(本地)。路径会在重启后记住;也可以在 设置 → SSH 加一台远程主机,或在 设置 → MCP execution mode → Terminal Provider 绑定一个 IPC Provider。
- 开始聊天。 输入问题或任务。模型会发出工具调用 —— 你可以逐条审批,也可以点 本次会话自动确认 放手让它跑。
- 可选集成。
- Termux。 从 F-Droid 安装 Termux,授权
RUN_COMMAND,shell_execute工具就会走它。 - SSH。 在 设置 → SSH 添加主机;项目抽屉里能看到远程文件。
- IPC Provider。 安装
terminal-provider(或任何第三方 Provider),在 设置 → MCP execution mode → Terminal Provider 启用。LineCode 每次冷启动会自动重连。 - 扩展。 在 扩展 页面配置自定义 Agent / MCP 工具。
- Termux。 从 F-Droid 安装 Termux,授权
如果你手上有 Ollama 或 llama.cpp server,指向它即可:协议选 OpenAI 兼容,Base URL 填 http://10.0.2.2:11434/v1(模拟器)或 http://<笔记本 IP>:11434/v1(真机),API key 填 ollama,模型名 llama3.1:8b。完全本地,无需账号。
LineCode 在 设置 → MCP execution mode 里提供三种 Shell / 文件工具执行模式:
| 模式 | Shell 与文件操作实际跑在哪里 | 适用场景 |
|---|---|---|
| Local(本地) | 经 Android SAF 选择器,在 App 自己的上下文里跑 | 设备本地任意目录,无需 Termux |
| SSH | 通过 jsch 连到配置的 SSH 主机 |
远端开发机 |
| Terminal Provider(IPC) | 绑定到一个第三方 Android App,通过 AIDL 调度(仓库自带 terminal-provider 作为参考实现) |
独立进程沙箱化 Shell,可插拔 —— 你可以发布自己的 Provider |
三种模式都通过统一的 IpcFileTreeStore / SshFileTreeStore / FileTreeStore 接口暴露,所以文件树、附件选择器、模型看到的是同样的 UI,不管字节实际在哪里。
| 协议 | 实现类 | 已验证可用的模型 / 服务 |
|---|---|---|
| OpenAI 兼容 | OpenAiCompatibleProtocol(默认) |
OpenAI、DeepSeek、通义千问、Moonshot、智谱、Groq、Ollama、llama.cpp server、LM Studio … |
| Anthropic Messages | AnthropicMessagesProtocol |
Claude 4.x 与 3.x |
| Codex Responses | CodexResponsesProtocol |
OpenAI Responses API |
| 本地 GGUF | LocalGgufProtocol |
设备本地 llama.cpp |
加新模型通常只要填一个 Base URL 和 Key。能力探针 OpenAiCompatibleCapabilities 会探测工具支持,模型会被告知它能调用哪些工具。
BaseTool 是契约,每个工具都要暴露:
name、description、category- 入参的 JSON schema
execute(JSONObject args, ToolContext ctx)返回ToolResult
内置工具在 feature-tool/src/main/java/cn/lineai/tool/builtin/:
FileReadTool FileWriteTool FileEditTool FileDeleteTool
GlobTool ListDirectoryTool ShellExecuteTool
ImageUnderstandingTool ImageGenerationTool WebSearchTool WebFetchTool
AgentTool AgentPipelineTool TodoUpdateTool
执行由 ToolExecutionCoordinator + ToolExecutor 驱动;每次调用都要过 PermissionModeController + ToolReviewListener,用户可逐条确认或会话级自动确认。自动确认列表由 MainCoordinator.sessionAutoConfirmedTools 跟踪。
工具结果由 ToolResult.truncateContent() 在 50KB 处截断(首尾各 25KB)后进入上下文。文件读取使用 KB 参数,50KB 范围上限;超过 1MB 的文件直接拒绝。Shell 输出超过 50KB 同样中间截断。
聊天流的工具调用由 app/src/main/java/cn/lineai/ui/component/toolcall/ 下的自定义卡片渲染(ToolCallReadView、ToolCallWriteView、ToolCallShellView、ToolCallAgentView、ToolCallAgentPipelineView、ToolCallGenericView…)。新工具只要在 ToolCallUtils 注册,就能拿到自己的卡片。
三类一等公民的扩展点:
- 自定义 Agent(
agentx_*)—— 实现CustomAgentExtensionTool,模型可以像调用内置工具一样调用它。 - 自定义 MCP-HTTP 工具(
mcpx_*)—— 实现CustomMcpHttpTool,模型可以走 HTTP 调用,per-tool 请求头存在设置仓库。 - 自定义 IPC Provider —— 在任意 Android App 里实现
IBaseIpcService/ITerminalProviderServiceAIDL,发布为普通 APK,LineCode 就会自动发现、绑定、把 Shell + 文件操作路由过去。完整协议与可运行示例见ipc/README.md。
以上三类都通过 ExtensionRepository 持久化,由 ToolRegistry.reloadExtensions() 热加载。
环境要求:
- JDK 11 或更新
- 已安装 Android SDK 平台 36
- 本仓库一份 checkout
所有 Gradle 命令都走 wrapper。settings.gradle.kts 强制 FAIL_ON_PROJECT_REPOS,并接入了腾讯云 Maven 镜像 —— 新增仓库时请保持。
# Debug 构建(debug 证书签名)
./gradlew :app:assembleDebug
# → app/build/outputs/apk/debug/app-debug.apk
# Debug 构建(debug 证书 + 重命名,便于旁加载)
./gradlew :app:assembleDebugUserCert
# → app/build/outputs/apk/debugUserCert/export/LineCode-user-cert-debug.apk
# 单元测试
./gradlew :app:testDebugUnitTest
# 单个测试类
./gradlew :app:testDebugUnitTest --tests "cn.lineai.tool.ToolRegistryTest"
# 追加 .methodName 跑单个方法
# 静态分析(自定义规则在 app/lint.xml)
./gradlew :app:lintDebugRelease APK 需要在仓库根放一份 signing.properties:
storeFile=/绝对路径/your.keystore
storePassword=…
keyAlias=…
keyPassword=…validateReleaseSigning 任务会拒绝用 debug 证书签 release。配置好后:
./gradlew :app:assembleRelease
# → app/release/LineCode Pro <versionName>.APKRelease 流水线刻意加强:
- 8192 项 R8 混淆字典,由
generateReleaseObfuscationDictionary生成(app/build/generated/r8/obfuscation-dictionary.txt) exportReleaseApk把产物重命名为LineCode Pro <versionName>.APK,放到app/release/purgeReleaseSymbolFiles删除outputs/mapping/release与outputs/native-debug-symbols/release
改版本号要同步更新 app/build.gradle.kts 的 releaseVersionName 和 defaultConfig.versionCode;APK 文件名由 releaseVersionName 派生。
./gradlew :ipc:assembleDebug
./gradlew :terminal-provider:assembleDebugterminal-provider 模块产出普通 debug APK(terminal-provider/build/outputs/apk/debug/terminal-provider-debug.apk),可以与主 App 一起安装来演示 IPC 链路。
按 docs/android-compliance-audit.md 要求,以下命令必须全部通过:
./gradlew :app:testDebugUnitTest
./gradlew :app:lintDebug
./gradlew :app:assembleDebug
./gradlew :app:assembleRelease- 导出文件去敏。 模型 API key、SSH 密码 / 私钥 / passphrase、网页搜索 key、敏感 MCP 请求头都会在
.linecode导出时由ArchiveSecretRedactor剥离。新增敏感字段时记得同步扩展它。 - 出网请求全部走
UrlPolicy。 内置浏览器、外链打开、模型 HTTP、模型目录、网页抓取 / 搜索、自定义 MCP HTTP 都要过白名单。明文 HTTP 仅放行localhost、127.0.0.1、10.0.2.2,与res/xml/network_security_config.xml(cleartextTrafficPermitted="false"默认)一致。 - 内置 WebView 禁用
file:///content://、禁止混合内容、默认关闭 JavaScript,直到用户主动开启。 - IPC 权限模型。 Provider 必须在
<service>上声明android:permission="cn.lineai.permission.IPC_TERMINAL_PROVIDER";主 App 声明同名<permission>和<uses-permission>。没有权限的调用方会在 Android 框架层被直接拒掉,Provider 端不必再做校验。 - 绕过路径保护。 安全设置页提供
OutputSettings.bypassPathProtection开关(默认关闭);开启后FileToolPathPolicy跳过工作区边界校验。开启时会显示警告对话框。所有文件类工具自动遵守此标志。 - Release 加固。 R8 + 8192 项混淆字典,剥离 LineNumberTable、native debug symbols、mapping 文件。Debug 证书签 release 会被
validateReleaseSigning拒绝。
完整威胁模型与已接受风险见 docs/android-compliance-audit.md。
欢迎提 Issue、想法和 PR。写代码前请注意:
-
纯 Java。
app/src/main/java全部是 Java;Kotlin stdlib 被刻意排除在运行时 classpath 外,引入 Kotlin 传递依赖会在运行期静默失败。ipc/与terminal-provider/同样。 -
视图用 Java 写,不用 XML。
lint.xml故意屏蔽ViewConstructor与IconDuplicates。 -
选择最低层模块。 加新代码时挑能容纳它的最低层模块:DTO →
:core-model;接口 →:core-api;UI 基础设施 →:ui-theme;新工具 →:feature-tool;新协议 →:feature-model。库模块不要回头引用:app。 -
通过控制器扩展。 新增聊天或工具行为时,扩展
cn.lineai.mvp.*下对应的控制器,状态走ChatUiStateAssembler→ChatUiState→MainContract.View.render(...)。不要绕过控制器去直接动 View。 -
测试镜像包路径。
app/src/test/java/cn/lineai/...与生产代码同包名。仅用 JUnit 4 +org.json(无 Robolectric、无 Mockito)。仓库或控制器单测优先用 sibling test 里已有的内存 fake。Feature 模块有各自独立的feature-*/src/test/java。 -
发 PR 前跑门禁:
./gradlew :app:testDebugUnitTest :app:lintDebug :app:assembleDebug :app:assembleRelease
LineCode Pro 是自由软件,按 GNU 通用公共许可证 v3.0 或更高版本 发布。
Copyright (C) 2026 langlang03 <jiyu03@qq.com>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
许可证全文见 LICENSE,在线副本:https://www.gnu.org/licenses/gpl-3.0.txt。
随 APK 一起分发的第三方库各自遵循自己的许可证:commonmark(BSD-2)、JSch(BSD 风格)、org.json(JSON License)。