- 移动开发
【免费下载链接】trime
同文安卓輸入法平臺3.x/Android-rime/Rime Input Method Engine for Android
同文(TRIME)是一款基于 Rime 引擎的开源安卓输入法,其官方隐私政策承诺"不收集、不上传任何用户隐私数据,尤其是用户输入内容"。本文以仓库根目录的 PRIVACY.md 为主体,结合AndroidManifest.xml、数据管理、数据同步与语音输入等源码实现,逐一验证这两项权限的真实用途、数据在设备上的存储位置,以及"数据不出设备"承诺背后的工程依据,帮助开发者与用户快速核实这款输入法的隐私边界与可控性。
一、隐私政策核心承诺:应用本身不联网、不上传
PRIVACY.md 的开篇即阐明立场:同文是开源的安卓汉语输入法项目,读取相关信息的目的是协助用户更快速地输入文字;应用本身不会收集、上传任何个人隐私数据到任何外部服务或服务器,尤其是用户的输入数据。
该承诺是否成立,最直接的证据是权限声明。查看仓库主清单文件 app/src/main/AndroidManifest.xml,整个<manifest>仅声明了三个权限:
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" /> <uses-permission android:name="android.permission.VIBRATE" /> <uses-permission android:name="android.permission.POST_NOTIFICATIONS" />RECEIVE_BOOT_COMPLETED:开机自启,用于开机后恢复输入法服务状态;VIBRATE:按键震动反馈(InputFeedbackManager 所在模块实现);POST_NOTIFICATIONS:发布部署进度、同步结果等本地通知。
清单中没有声明android.permission.INTERNET,即应用自身不具备发起网络连接所需的权限。用户在键盘上通过command: run打开的网址(参见 trime.yaml 中的Homepage、Wiki、WebSearch等按键定义),走的是 Android 系统的Intent交给浏览器处理,属于"用户主动点击、系统组件代为打开",与应用自身联网是两个概念。从源码结构看,核心输入链路(core/Rime.kt、data/目录)中也不存在网络请求相关代码,数据读写全部面向本地文件系统。
二、权限清单逐项解读:存储与麦克风
PRIVACY.md 列出的读取信息与权限只有两项,逐一对照源码分析如下。
1. 存储空间:保存用户词典数据与配置信息
用户词库(*.userdb目录、user.yaml、default.custom.yaml等)与 Rime 部署产物都存放在应用的外部私有目录中。见 DataManager.kt:
val sharedDataDir = File(externalFilesDir, "shared").also { it.mkdirs() } val userDataDir = File(externalFilesDir, "rime").also { it.mkdirs() }其中externalFilesDir对应Context.getExternalFilesDir()(应用专属外部存储目录),该目录不需要也不应申请存储权限即可读写——这也解释了当前清单中为何不再出现READ/WRITE_EXTERNAL_STORAGE。另外,从 DataManager.kt 可以看到:
// If Android version supports direct boot, we put the hierarchy in device encrypted storage // instead of credential encrypted storage so that data can be accessed before user unlock private val dataDir: File = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { appContext.createDeviceProtectedStorageContext().dataDir } else { File(appContext.applicationInfo.dataDir) }Android 7.0 及以上使用设备加密存储(Device Protected Storage)放置校验文件等关键数据,使输入法在设备解锁前也能被系统调用,同时保证数据仍停留在设备本地。
如果用户选择"外部同步"模式(DataStorageMode.EXTERNAL_SYNC,见 DataStorageMode.kt),应用会通过 Android 系统的Storage Access Framework(SAF)让用户在系统文件选择器中主动挑选一个目录作为同步目标(对应 SetupActivity 中的存储设置流程),之后仅在 Rime 部署前后执行导入/导出(见 RimeDataSync.kt)。这一设计有两个关键点:
- 同步目录由用户主动授权并持久化(
StorageAccess.persistedPermissions()校验读写权限,见 RimeDataSync.kt); - 同步规则会主动跳过
build目录和所有.userdb子串路径(见 RimeDataSync.kt 的SKIP_DIR/SKIP_DIR_SUBSTRING常量),避免把临时产物或数据库中间状态卷入备份;同步索引rime_sync_index.json记录每个文件的尺寸与修改时间,用于增量判断(RimeDataSync.kt)。
可见,"存储空间"权限的真实用途就是读写本地用户词典与配置文件,全程本地化,不存在上传通道。
2. 麦克风:用于系统语音输入,可关闭
PRIVACY.md 明确标注麦克风为可选项:"用於系統語音輸入,如不需要可關閉"(Microphone(OPTIONAL): Used for voice input)。
结合源码,同文本身并不直接采集音频。当用户按下键盘上的语音辅助键(KeyEvent.KEYCODE_VOICE_ASSIST)时,会触发 CommonKeyboardActionListener.kt 中的switchToVoiceInputMethod(),其逻辑(CommonKeyboardActionListener.kt)是:
- 读取用户在设置中选择的"首选语音输入法"(
preferred_voice_input,见 AppPrefs.kt 与 AppPrefs.kt); - 通过 InputMethodUtils.voiceInputMethods() 枚举系统已启用输入法中
subtype.mode == "voice"的语音子类型; - 调用系统
InputMethodManager.switchInputMethod()(InputMethodUtils.kt)切换到该语音输入法;若系统未安装任何语音输入法,则提示no_voice_input_installed("未安装语音输入",见 strings.xml)。
也就是说,录音行为发生在用户切换过去的其他语音输入法进程中,同文只负责"切换"这一系统级操作,因此完全可以在系统设置中关闭麦克风授权或干脆不授予,语音输入功能不受影响。当前清单中也未声明RECORD_AUDIO权限,与该设计一致。
三、数据本地化设计:词典、配置与同步的完整链路
为了把"数据留在设备上"落到工程实处,同文在数据层做了三层设计,均可从源码验证:
部署数据本地化:Rime 引擎所需的方案、词典等资源从 APK 内置 assets(app/src/main/assets/shared 下的
trime.yaml、luna_pinyin.schema.yaml、essay.txt等)按需拷贝到应用私有目录,并通过checksums.json做差异增量更新(DataManager.kt),整个过程不依赖网络。用户数据与应用沙箱隔离:
userDataDir位于getExternalFilesDir()/rime,随应用卸载自动清除(系统管理),同时支持"应用专属存储"(APP_STORAGE)与"外部目录同步"(EXTERNAL_SYNC)两种模式自由切换(DataStorageMode.kt),切换回应用存储时会标记.userdb需要重新导入,确保本地数据库始终是权威数据(RimeDataSync.kt)。同步只在用户选定的目录内进行:导出前按
installation_id生成带实例标识的同步前缀,导入时对未出现在外部目录中的本地文件执行孤儿清理,并跳过build/*.userdb内部目录(RimeDataSync.kt)。所有读写均通过 SAF 的文档 URI 完成,应用既拿不到系统级存储权限,也不会越过用户授权范围。
四、用户如何自行核对与掌控
鉴于仓库只读,读者可以从以下途径验证本文结论,并管理自己设备上的数据:
- 核对权限声明:打开 app/src/main/AndroidManifest.xml,确认
INTERNET、RECORD_AUDIO、READ/WRITE_EXTERNAL_STORAGE均未出现;如需排查三方库注入的权限,可查看构建产物中的合并清单(build/intermediates/merged_manifests)。 - 核对数据文件:在设备上进入"应用信息 → 存储"查看同文占用的空间;选择外部同步后,可在自行指定的目录中直接查看备份出的
user.yaml、default.custom.yaml等配置(导出清单见 DataManager.kt 的POST_SCHEMA_DEPLOY_EXPORT_FILES)。 - 管理语音输入:在系统"语言与输入法"设置中查看麦克风授权,或在同文设置中清除"首选语音输入法"(
preferred_voice_input),即可完全关闭语音输入入口,不影响键盘打字。 - 审计同步行为:同步过程的日志会记录每个文件的 copied/skipped/deleted/failed 统计(RimeDataSync.kt),可通过应用内日志界面核对同步是否只发生在授权目录内。
五、说明与版本沿革
需要指出的是,PRIVACY.md 最后更新于 2017 年 7 月 25 日(Updated on 2017.7.25),其描述的权限模型(如独立的"存储空间"权限)对应早期的 Android 版本;而当前仓库的清单采用 Android 6.0+ 运行时权限模型与应用专属存储,存储访问不再需要全局权限,麦克风权限也未被声明。两份材料口径一致的核心事实没有变化:应用不收集、不上传用户输入数据,存储仅用于本地词典与配置,麦克风仅服务于用户主动发起的系统语音输入。对隐私敏感的用户,仍建议安装后到系统设置中实际核对授权项,并以安装版本对应的应用商店声明为准。
- 移动开发
【免费下载链接】trime
同文安卓輸入法平臺3.x/Android-rime/Rime Input Method Engine for Android
相关推荐
Netcatty 数据隐私与安全架构解析:本地优先存储、零知识云同步与第三方数据流向
Netcatty 数据隐私与安全架构解析:本地优先存储、零知识云同步与第三方数据流向 Netcatty(SSH workspace、SFTP 与终端的桌面一体化
Octotree数据存储机制:本地缓存与同步策略
Octotree数据存储机制:本地缓存与同步策略 Octotree作为GitHub增强工具,其数据存储机制直接影响用户体验与功能稳定性。本文将深入解析Octot
开发工具Canta 隐私架构全解:Shizuku 无 Root 卸载应用背后的权限、数据流与本地存储机制
Canta 隐私架构全解:Shizuku 无 Root 卸载应用背后的权限、数据流与本地存储机制 导读 本文以仓库根目录的 privacy_policy.md
移动开发
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考