Android应用转动态模块后,更新导致SharedPreferences数据丢失
问题分析与修复方案
可能原因1:SharedPreferences创建方式不统一
如果之前所有模块都通过主应用全局上下文创建SharedPreferences,但迁移动态模块过程中,部分代码改为使用模块自身上下文创建SP,会导致不同上下文生成的SP文件路径不同,旧版本的数据无法被读取,看起来像是被清空。
修复:
- 统一使用应用全局上下文创建SharedPreferences,确保所有模块访问同一SP文件:
// 正确写法:依赖全局上下文 SharedPreferences sp = getApplicationContext().getSharedPreferences("APP_GLOBAL_SP", Context.MODE_PRIVATE); - 检查所有模块中创建SP的代码,替换为全局上下文调用。
可能原因2:主模块applicationId或签名配置变更
引入动态模块时若误改主模块的applicationId,或调整了签名配置(比如调试/发布签名不一致),系统会将升级后的应用识别为全新应用,直接清空原有数据。
修复:
- 核对主模块
build.gradle中的applicationId,确保与旧版本完全一致:android { defaultConfig { applicationId "com.your.package.name" // 必须和旧版本保持一致 // 其他配置... } } - 确认发布用的签名证书、密钥库、别名及密码与旧版本完全匹配,签名不一致会触发全新安装逻辑。
可能原因3:动态模块配置异常导致安装流程错误
动态模块的AndroidManifest.xml配置错误(比如splitName冲突、交付规则设置不当),可能导致Google Play在升级时错误清理主应用数据目录。
修复:
- 检查动态模块的Manifest配置,确保
dist:module设置无冲突:<dist:module dist:instant="false" dist:title="@string/module_title"> <dist:delivery> <dist:install-time /> </dist:delivery> <dist:fusing dist:include="true" /> </dist:module> - 用
bundletool本地模拟升级流程,排查安装环节问题:# 生成旧版本APK包 bundletool build-apks --bundle=old_version.aab --output=old_version.apks # 生成新版本APK包 bundletool build-apks --bundle=new_version.aab --output=new_version.apks # 先安装旧版本,再升级到新版本,验证数据是否保留 bundletool install-apks --apks=old_version.apks bundletool install-apks --apks=new_version.apks
可能原因4:旧模块SP数据未迁移
如果旧版本的SP存储在被转为动态模块的专属路径中,升级后该模块变为按需加载,主应用无法直接访问旧路径下的SP数据,导致数据“消失”。
修复:
- 在主模块的
Application.onCreate()中添加数据迁移逻辑,将旧模块的SP数据复制到全局SP:private void migrateOldModuleSP() { Context oldModuleContext = null; try { // 获取旧动态模块的上下文 oldModuleContext = createPackageContext("com.your.dynamic.module", Context.CONTEXT_IGNORE_SECURITY); SharedPreferences oldSp = oldModuleContext.getSharedPreferences("OLD_MODULE_SP", Context.MODE_PRIVATE); // 复制数据到全局SP SharedPreferences.Editor editor = getApplicationContext().getSharedPreferences("APP_GLOBAL_SP", Context.MODE_PRIVATE).edit(); editor.putString("user_token", oldSp.getString("user_token", "")); // 其他需要迁移的字段... editor.apply(); } catch (PackageManager.NameNotFoundException e) { // 模块未安装,无需迁移 } }
内容的提问来源于stack exchange,提问作者Joseph Rex
相关产品推荐
相关产品推荐

