新版硅基轻享app修改教程:从疯狂闪退到成功喂给xDrip(万字实操)
从官方新版硅基轻享app 02.23.01.00 到本地修改版 v15,再到 xDrip 收到真实血糖
最近体检结果出来了。

具体指标就不在这里展开了,但它确实提醒我,不能只在一年一次的报告里看几个数字了。我想重新观察一段时间,看看日常吃饭、睡眠、运动和压力到底会怎样影响血糖曲线。顺便,医生建议监测1天的心电。

于是,我又戴上了硅基轻享。
传感器还是熟悉的传感器,手机里的 App 却已经不是前几个月的版本了。官方轻享更新到了 02.23.01.00,而我电脑上那套能把血糖转发给 xDrip 的修改版 v14,还停在 02.21.02.00。上次教程文章见《我是如何把硅基轻享的血糖数据“解放”出来喂给xDrip+和AAPS的》,这次是化用上次的方法,然后遇到了新的问题点。
戴上轻享以后,一个自然而然的问题冒了出来。
旧修改版还能不能继续用?如果不能继续用,能不能基于当前官方版重新做一份?
一开始我觉得这大概只是一次版本迁移。把旧补丁搬到新代码,重新打包,签名,安装,应该就差不多了。
后来的事实证明,我还是乐观了。。。
新版做出来以后,手机显示蓝牙连接中,接着进入设备初始化中,然后直接闪回桌面。系统弹出「硅基轻享屡次停止运行」。等把这个闪退修完,xDrip 又冒出 0 和 2.2 mmol/L 的占位数据问题。
一个看起来很简单的升级,最后横跨了 APK 身份识别、运行时 DEX 提取、Smali 修复、Android 多进程、Binder、Parcelable、BLE GATT、Fastjson、跨应用广播和数据质量过滤。
但也正因为坑够多,这次过程反而很值得完整记录下来。(本文可以喂给claude、gpt、deepseek等任何大模型,直接达成目标)
我想讲清楚,作为一名代码方面的小白,在面对一个既有硬件、又有 App、还有第三方接收端的系统,怎样把黑盒一层层拆开,直到实现自己的需求,同时让每个结论都能明白。
一、我面对的不是一个 App
很多朋友看到 xDrip 没有血糖,第一反应大概率会是 xDrip 配置错了。
这很正常。
因为用户最终看到的是 xDrip 里的一个空白数字。但在这个数字出现之前,数据至少要经过传感器广播、Android BLE 扫描、GATT 连接、设备认证、原生算法处理、血糖实体生成、跨应用广播、xDrip 接收和入库。
中间任何一环断掉,最终表现都一样。
没数据。
所以这次工作的目标只有1个:
基于当前官方 02.23.01.00 重做 v15,并证明它能在真机上把真实血糖送进 xDrip!!!

二、为什么不能给 v14 改个版本号就交差
从 02.21.02.00 到 02.23.01.00,变化的不只是版本字段。
官方代码经过混淆,类名和方法名会变。登录路径、BLE 库、数据库依赖和初始化时序也可能调整。旧版里有效的一个调用点,到了新版的已经搬家,甚至整条调用链都换了。
最典型的是 xDrip 桥接。
旧补丁最终要挂到真实血糖处理路径上。新版里不能只搜索旧混淆方法名,而要从 BloodGlucoseEntity 反向追踪,确认 glucoseValue、glucoseTrend 和 processedTimeMill 在哪里被消费,再把桥接放到真正稳定执行的入口。
登录恢复也是同样的逻辑。旧版用于恢复登录标志的方法,在新官方代码中已经换了混淆名。照抄能编译,可就是不能执行。
我一直觉得,版本迁移里最费时间的不是写补丁,是证明你找到了新版本里的同一条业务语义。
代码相似只是线索,运行证据才是确认。
三、v15 的第一步,从当前官方版重新取得业务代码
官方轻享做了加固。
静态解压 APK 看到的 DEX,并不能代表运行时完整业务代码。壳会在应用启动后解密并加载真正的业务 DEX,所以这次没有把旧 v14 的 DEX 硬塞进新包,而是让当前官方版在 MuMu 中运行,再从进程内存里确认和提取已经加载的代码。
最终确认了八个 DEX。
早期只拿到七个,第八个只有三万多字节,体积小得很容易被忽略。后来检查发现,提取脚本在 Android shell 中处理 64 位内存地址时发生截断,于是那个小 DEX 根本没有进入结果集。
这块特别容易制造假象。
少一个小 DEX,App 可能照样能启动,登录页也能打开。只有走到某个深层场景,才会出现缺类或方法残缺。你会怀疑刚写的补丁,实际上拼图在提取阶段就少了一块。
修正地址处理后,八个 DEX 全部反汇编为 Smali,才开始真正的补丁迁移。
这里的 Smali 可以理解为 Dalvik 字节码的人类可读形式。它不是 Java 源码,却能精确对应寄存器、方法调用、字段访问和控制流。对于没有原始工程、只能处理 APK 的场景,Smali 往往就是最终施工面。

四、v15 到底改了哪些东西
这一版不是只加了一条 xDrip 广播。
它保留官方 02.23.01.00 的业务代码,在这个基础上重新移植了启动、登录、数据库和数据转发相关补丁。
1、恢复真实 Application 启动链
Manifest 的 Application 入口从加固壳切换到真实的 com.sisensing.base.BaseApplication,并恢复应用上下文、MMKV、Blankj utilcode、ARouter 和业务数据库初始化。
这一步如果缺初始化,App 可能能开页面,却在后续路由、缓存、数据库或 BLE 调用时才崩。
2、重新定位 xDrip 桥接
在新版真实血糖处理入口中读取 glucoseValue、glucoseTrend 和 processedTimeMill。
血糖从 mmol/L 乘以 18.0182 转换为 mg/dL,趋势转换成 xDrip 能识别的方向字符串,再发送 com.eveningoutpost.dexdrip.NS_EMULATOR 广播。
广播使用显式组件指向 xDrip 的 NSEmulatorReceiver,并加入 FLAG_INCLUDE_STOPPED_PACKAGES,减少接收端不在前台时的漏收概率。
3、保留 AAPS 广播
继续发送 cn.diyaps.sharing.SISENSING_APP 到 info.nightscout.androidaps。
这只是保留数据接口!!!
4、恢复登录状态
根据新官方代码重新定位登录恢复路径。本地令牌存在时恢复登录标志并进入已登录路由,避免脱壳后错误停留在登录页。
5、调整 401 行为
沿用旧版策略,关闭 HTTP 401 后立即强制下线的处理,减少网络波动对本地数据链的打断。
代价也要说清楚。失效会话可能保留更久。如果接口持续认证失败,正确动作仍然是强制停止app→清除app缓存和数据→重新登录。
6、增加数据库容错
业务数据库打开失败时允许删除并重建一次 cgm_database,避免结构不兼容导致永久崩溃。
它不是无损修复。真触发回退时,尚未同步的数据可能丢失。
7、处理 v14 覆盖升级
v14 使用的 WorkManager 调度库与新依赖不兼容。v15 会在初始化阶段一次性重建 androidx.work.workdb,并写入版本化标记,后续启动不再重复删除。
这里重建的是后台任务调度元数据,不是硅基账号、传感器和血糖业务库。
8、重新组装、对齐和签名
修订后的八个 DEX 重新组装进 APK,执行 ZIP alignment,再使用本地证书签名。最终 v1、v2、v3 签名全部验证通过。
v14 和 v15 使用同一张本地证书,versionCode 又从 27 升到 31,所以修改版之间可以覆盖升级。官方轻享使用另一张证书,不能直接被本地修改版覆盖。
签名不是一个可有可无的尾部步骤。
在 Android 里,它就是应用身份的一部分。
五、MuMu 安卓模拟器
MuMu 在这次工作里非常好用。
它完成了官方版运行时提取、全新安装、冷启动、v14 覆盖升级到 v15、数据库迁移、进程存活和类校验测试。出错后可以快速重置,不会碰真实传感器会话。

但模拟器不能连接我身上的传感器。
所以它没法证明真实的BLE 扫描、GATT 连接、设备认证、初始化补传和原生算法处理。
这是真实情况与MuMu 的测试边界不同。
模拟器负责把低风险、可重复的问题尽量消灭。真机负责验证外设和真实业务路径。两者谁也替代不了谁。
当 v15 在 MuMu 中稳定启动时,我一度觉得主体工作已经结束。
真机很快教我做人。
六、真实故障现场,设备初始化中,然后闪退
手机上的官方 App 已经卸载,v15 安装成功。
蓝牙、附近设备、通知和后台运行权限全部允许。首页先显示蓝牙连接中,接着显示设备初始化中,然后 App 突然退出到手机桌面。
系统提示「硅基轻享屡次停止运行」。
复现这种问题时,我采用的是固定节奏。清空旧日志,启动 App,等待同一故障重新出现,再立即读取完整日志和 crash buffer。这样能把上一次启动的噪声排除掉。
adb logcat -cadb logcat -v timeadb logcat -b crash -v time真正要找的是最早的致命异常、所属进程、调用栈顶部方法,以及崩溃前几十行的 BLE 状态。
Android 日志里有大量红色警告。颜色不是严重程度,调用关系才是。
七、一串崩溃
第一次修 APK 的人很容易产生一种挫败感。
明明刚修完一个崩溃,怎么启动以后又出现另一个?是不是越修越坏?
其实很多时候,第一处错误只是挡在最前面的墙。它倒下以后,后面的残缺路径才第一次获得执行机会。
这次就是一轮一轮暴露出来的。
1、扫描回调触发 VerifyError
第一处是 vda.a(String)。
这个方法位于蓝牙批量扫描回调路径,运行时 DEX 里的方法体残缺。Android 运行到这里时触发 VerifyError,虚拟机认为字节码结构不合法,拒绝继续执行。
按原语义恢复后,App 能走得更远了。
2、自动登录绕过了 BLE 初始化
自动登录跳过 WelcomeActivity,而原来的 LocalBleManager.context 初始化恰好依赖这个页面。
页面没走,BLE 上下文就是空的。
修法是把初始化前移到 Application。
然后又崩了。
3、Application 在推送进程也会执行
这个 App 不只有主进程,还有独立的 pushcore 推送进程。两个进程都会创建自己的 Application。
如果它们都初始化 BLE,跨进程 Binder 会被错误地当成本地 Binder 使用。一个初始化太晚的问题,瞬间变成了初始化进程不对的问题。
最终方案是保留 Application 初始化,但严格限制只在 com.sisensing.eco 主进程执行。
4、Parcelable 在设备交换阶段损坏
BLE 服务真正开始交换对象后,Parcelable 基类 c.a 和 CREATOR c.a$a 又暴露出残缺方法。
Parcelable 是 Android 组件和 Binder 传输对象时常用的序列化协议。构造、写入和反序列化任何一环不完整,接收端都无法还原对象。
旧 v14 恰好使用同版稳定 BLE 库,所以这里没有搬运整个旧 DEX,而是只恢复已经确认同源、同语义的 Parcelable 实现。
5、算法上下文和 Fastjson 继续暴露残缺
连接和对象传输稳定后,代码进入设备认证与算法初始化。新的缺口出现在 AlgorithmContext.toString()、Fastjson 的 Feature、SerializerFeature 和底层 IOUtils。
能确认原语义的部分继续恢复。
然后,整次排障里最离谱的一幕出现了。
6、把 App 干崩的竟然是一条诊断日志
LocalBleService 有三处代码,为了记录调试信息,先调用 JSON.toJSON() 把对象转成 JSON。它会继续进入 Fastjson 的 SerializeConfig,而那条运行时提取路径并不完整。
蓝牙数据已经到了。
设备认证已经通过。
原生算法也开始加载了。
结果 App 被一条不参与业务的日志转换干崩了。。。
最终没有继续大规模移植整套 Fastjson,而是在确认三处调用只用于日志后,改为直接记录对象。
扫描、连接、认证、算法和血糖实体都没改,只绕开没有业务必要的 JSON 诊断路径。
八、xDrip 没有数据,究竟是谁的问题
闪退修完以后,真正的目标才重新出现。
xDrip 到底能不能收到血糖?
排查这类问题,我会把链路拆成三个观察面。
发送端看轻享有没有生成有效 BloodGlucoseEntity,有没有出现 SiSensingPatch 和 Broadcast sent。
Android 传输层看显式广播的 action、目标组件和包名是否正确,接收端有没有被系统调起。
接收端看 xDrip 是否出现 NSEmulator onReceiver、Receiving NSEmulator broadcast、bgReadingInsertFromData 和 Processing incoming json。
这次原始故障发生在发送端之前。
修改版在设备初始化阶段连续崩溃,还没稳定走到血糖广播,所以 xDrip 当时没有数据。
修复后,传感器 被扫描到,GATT 连接和服务发现完成,日志出现 authentication sucess。原生算法随后处理 CGMRecordV120,业务路径进入 dealCompositedData。
接着,真正让人松一口气的日志出现了。
轻享广播了一条 95.49646343669892 mg/dL 的真实记录,约等于 5.3 mmol/L。
同一时间,xDrip 依次打印接收、解析和入库日志。
两边的时间戳和数值对上了。
整个链路跑通了。
九、数据发通了,却差点发出假低血糖
看到 xDrip 出数字时,我以为终于能收工。
仔细翻初始化补传日志,又发现两类奇怪记录。
一种是 0。
另一种是 2.2 mmol/L,换算后约为 39.64 mg/dL。
它们不是每次都代表真实血糖。根据这次传感器的实际记录,官方算法每分钟产生对象,成熟值按观察规律出现在 5 分钟索引上,中间对象会出现 0 或下限 2.2 占位。
如果桥接看到对象就发,xDrip 可能先收到占位值,把当前血糖显示成 0 或严重低血糖。
但过滤也不能粗暴写成 ≤2.2 全丢。
真实严重低血糖同样可能位于这个区间。把真低血糖删掉,比多一条脏数据更危险。
最终过滤逻辑做了三件事。
0 不广播。
≤2.2 mmol/L 只有在成熟的 5 分钟索引上允许通过,保留真实低值的可能。
时间戳必须严格晚于本进程上一条已发送记录,抑制初始化补传中的重复值和旧值回灌。
真机随后收到 index=352、glouse=0 的记录。官方业务层正常处理,但桥接没有发出新的 Broadcast sent。
占位过滤生效。
我自己的感受是,程序能运行只是工程上的第一道门槛。医疗数据场景真正麻烦的,是一条格式完全正确、数值却不该出现的数据。
没有数据很容易被发现。
错误数据反而更像真的。

十、最容易忽略的是签名
官方轻享和修改版使用相同包名,却不是同一张证书。
所以 Android 不允许 v15 直接覆盖官方版,通常会返回 INSTALL_FAILED_UPDATE_INCOMPATIBLE。
这不是重新签一次就能绕过去的小问题。签名决定 Android 是否把两个 APK 视为同一发布者。
从官方版切换到修改版,一般需要先卸载官方 App。卸载会清除本地应用数据,也可能影响当前传感器会话,所以必须先确认账号、绑定恢复方式和数据同步情况。
本次是在用户已经主动卸载官方版后安装 v15。后续热修都保持包名、versionCode 和本地证书不变,通过 adb install -r 覆盖,保留当前登录与绑定数据。
最终交付包的版本字段是 02.23.01.00,versionCode 31,文件大小 57,894,031 字节,SHA-256 为 B9F209CF1AA289C5CC518F073AA6AF3AACD713CB17F4C72824995AC7BB4B6F1A。
安装到手机后,又对设备内的 base.apk 做了一次 SHA-256 校验,结果和电脑交付文件完全一致。
我觉得这个动作还是挺重要的。
不是因为每次安装都会神秘损坏,而是它把「我大概装了最新版」变成了「手机里运行的就是这个确定文件」。
再也不用研究我手机里现在装的到底是哪个版本了!!!
十一、最终跑到了哪里
最终 v15 在三星S23U和S25U、Android 16 上完成了真机闭环。
主进程和推送进程持续存活,Android crash buffer 为空,没有新的 FATAL EXCEPTION、VerifyError 或「屡次停止运行」。
BLE 服务识别设备 Pxxxxxx,完成扫描、连接、服务发现和认证。原生算法处理真实 CGMRecordV120。轻享发出真实血糖广播,xDrip 接收并进入数据处理链。紧随其后的零值占位记录被过滤。
后续还出现过一次 scan not find 6TTW,BLE 进入断开状态,但 App 没有崩溃。

接下来就是数小时、数天、手机重启、传感器完整生命周期和各种极端边界的稳定性验证。
至于 AAPS,当前只验证了广播接口保留,没有进行闭环治疗验证。
十二、这次排障沉淀出的八步法
如果以后再遇到这类的问题,我会直接复用这条路线。
1,确认应用身份
核对包名、versionName、versionCode、签名和产品线。不要相信文件名,也不要因为两个 App 版本号相同就默认它们同源。
2,画出完整数据链
从硬件开始,一直画到最终数据库。每个进程、服务、算法入口、广播和接收器都放进去。链路没画清楚,排障只能靠运气。
3,给每一层设置观测点
进程看 ps,崩溃看 crash buffer,类加载看 VerifyError,BLE 看扫描和认证状态,发送看 Broadcast sent,接收看 receiver 和入库日志。
4,只处理最早的致命点
一次日志里可能有几十条异常。先修最早阻断主链的那一条,再重新复现。不要同时改五个地方,否则下一轮结果无法归因。
5,区分业务代码和诊断代码
认证、算法、数据转换必须按原语义恢复。纯日志路径如果会触发大面积残缺依赖,可以在证明无业务副作用后做最小旁路。
6,模拟器和真机分工
模拟器负责安装、升级、数据库和字节码完整性。真机负责 BLE、设备认证、原生算法和真实数据。不要拿一个环境的成功替另一个环境背书。
7,用双端日志证明链路
发送成功和接收成功必须在数值、时间戳上对应。只有一端的成功日志,不能证明端到端完成。
8,验证数据质量和未测范围
检查单位、时间戳、趋势、占位值、重复和旧数据。然后明确写出还没测什么。
十三、最后
回头想想,这次折腾的起点不过是硅基轻享app不能将数据发给我用。但技术的有趣之处就在于此——它把抽象的健康焦虑,变成了一个个具体可解的工程问题:BLE连接、数据格式、跨应用广播。
每一个报错都像一面镜子,照见我对这套系统理解不够深的地方,而修掉它的过程,就是理解加深的过程。
我相信,把数据的解释权和控制权握在自己手里,这份安心,值得花时间。
如果觉得不错,随手来个三连吧,如果想第一时间看到我的文章,可以给个星标⭐~谢谢你看我的文章,我们下次见~
夜雨聆风