17、多用户与账户系统:多用户管理、用户切换与配置文件、账户同步策略
多用户系统,说白了就是让一辆车能服务好一家人。你想想看,爸爸喜欢导航播报用林志玲的声音,妈妈习惯把座椅调到最低,孩子只想看动画片——没有多用户,这些需求根本没法同时满足。
我在做第一代车载系统时,遇到过最头疼的问题就是:用户切换后,蓝牙连接断了,WiFi密码丢了,甚至导航收藏夹全没了。嗯,这背后其实就是多用户架构没设计好。今天我们就来彻底搞懂它。
17.1 多用户管理:Android Automotive 的用户模型
Android Automotive 的多用户,和手机上的多用户不太一样。手机上的多用户更像「访客模式」,而车载的多用户是「驾驶员专属空间」。每个用户都有自己的设置、应用数据、账户信息。
核心概念就三个:
- UserHandle:每个用户的唯一标识。系统通过它来隔离数据。
- UserManager:管理用户的创建、删除、切换。这是多用户的总闸。
- UserInfo:描述用户的信息,比如用户名、头像、是否是管理员。
我习惯把 UserManager 看作「酒店前台」,UserInfo 是「房卡」,UserHandle 是「房间号」。前台告诉你哪个房间有人,房卡决定你能进哪个房间,房间号决定了你的东西放在哪。
关键点:车载系统通常有 3 种用户类型:
- 系统用户(System User):User 0,系统服务跑在这里,普通用户看不到。
- 管理员用户(Admin User):可以管理其他用户,通常对应车主。
- 普通用户(Secondary User):家庭成员或临时驾驶员。
创建用户的代码其实不复杂,但权限要求很高:
// 获取 UserManager 实例
UserManager userManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
// 创建新用户(需要 MANAGE_USERS 权限)
UserHandle newUser = userManager.createUser("张三", 0); // 0 表示普通用户
// 设置用户头像
userManager.setUserIcon(newUser, bitmap);
// 删除用户
userManager.removeUser(newUser);
我在项目中遇到过一个问题:创建用户时如果传入了错误的 flag,会导致新用户无法使用某些系统功能。比如忘记加 FLAG_EPHEMERAL,临时用户的数据就不会被自动清理。嗯,这个坑踩过一次就记住了。
17.2 用户切换与配置文件:切换背后的机制
用户切换,听起来就是点一下头像换个账号。但底层发生的事情,比你想象的多得多。
切换流程大致是这样的:
- 系统收到切换请求,调用
UserManager.switchUser()。 - AMS(ActivityManagerService)开始冻结当前用户的所有进程。
- 系统切换到目标用户的 UserData 目录。
- 启动目标用户的 Launcher 和系统服务。
- 恢复目标用户的应用进程。
这里面最耗时的,其实是第 3 步——切换数据目录。每个用户的数据都存放在 /data/user/<userId>/ 下。切换用户,本质上就是切换这个目录的挂载点。
我的建议:用户切换时,不要做太多「清理工作」。我曾经在切换回调里做了大量数据库迁移,结果切换一次要 8 秒。后来改成懒加载,用户点开应用时才迁移,体验好多了。
配置文件这块,Android Automotive 用的是 Profile 机制。每个用户可以有多个 profile,比如「工作模式」和「个人模式」。但车载场景下,profile 更多用于区分「驾驶模式」和「停车模式」。
// 获取当前用户的配置文件
UserManager userManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
UserHandle myUser = Process.myUserHandle();
// 获取该用户的所有 profile
List<UserHandle> profiles = userManager.getUserProfiles();
// 检查当前是否是 managed profile
boolean isManagedProfile = userManager.isManagedProfile();
你想想看,为什么需要 profile?因为同一个驾驶员,开车时和停车时需要的应用完全不同。开车时只能看导航和音乐,停车时可以看视频、玩游戏。用 profile 来隔离,比用多用户更轻量。
注意:profile 切换不会触发用户切换的完整流程,所以速度更快。但 profile 之间的数据隔离不如多用户彻底。如果你的应用需要完全隔离的数据,请使用多用户,而不是 profile。
17.3 账户同步策略:让数据跟着用户走
多用户搞定了,账户系统也得跟上。否则换个用户,Spotify 账号还得重新登录,那体验就太差了。
Android 的账户系统核心是 AccountManager。每个用户可以绑定多个账户,比如 Google 账号、百度账号、车厂自己的账号。
账户同步,说白了就是:用户 A 登录了 Spotify,切换到用户 B 后,用户 B 的 Spotify 应该自动登录自己的账号,而不是沿用用户 A 的。
实现这个逻辑,需要做两件事:
- 账户隔离:每个用户的账户数据存放在自己的 UserData 目录下。
- 同步适配器:系统通过 SyncAdapter 来同步账户数据。
// 获取当前用户的 AccountManager
AccountManager accountManager = AccountManager.get(context);
// 获取当前用户的所有账户
Account[] accounts = accountManager.getAccounts();
// 添加账户
Account account = new Account("zhangsan@example.com", "com.example.account");
accountManager.addAccountExplicitly(account, "password", null);
// 设置同步
ContentResolver.setSyncAutomatically(account, "com.example.provider", true);
ContentResolver.addPeriodicSync(account, "com.example.provider", new Bundle(), 3600);
我在项目中遇到过最典型的坑是:账户同步时机。用户切换后,如果立即触发同步,网络可能还没准备好。我建议的做法是:监听用户切换完成广播,延迟 3-5 秒再启动同步。
同步策略总结:
| 策略 | 说明 | 适用场景 |
|---|---|---|
| 立即同步 | 用户切换后立即同步 | 关键数据,如导航收藏 |
| 延迟同步 | 等待 3-5 秒后同步 | 非关键数据,如音乐播放列表 |
| 按需同步 | 用户打开应用时才同步 | 第三方应用数据 |
| 定时同步 | 每隔一段时间同步一次 | 后台数据,如天气信息 |
还有一个容易被忽略的点:账户删除。当管理员删除一个用户时,该用户的所有账户也应该被清理。否则下次创建同名用户时,可能会残留旧的账户数据。
// 监听用户删除事件
UserManager userManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
userManager.addUserStatusListener(new UserManager.UserStatusListener() {
@Override
public void onUserRemoved(int userId) {
// 清理该用户的所有账户
AccountManager accountManager = AccountManager.get(context);
Account[] accounts = accountManager.getAccountsForUser(userId);
for (Account account : accounts) {
accountManager.removeAccountExplicitly(account);
}
}
});
嗯,这里要注意:getAccountsForUser() 这个 API 在 Android 10 之后才稳定可用。如果你的系统版本较低,可能需要通过反射或者 ContentProvider 来获取。
17.4 多用户架构的整体视图
说了这么多,我们来画一张图,把多用户、用户切换、账户同步串起来。
这张图把三个核心层的关系讲清楚了。用户管理层负责「谁在用」,数据隔离层负责「数据在哪」,账户同步层负责「账号怎么跟」。三层协作,才能实现流畅的多用户体验。
个人经验:我建议你在设计多用户系统时,先把「用户切换的边界条件」列清楚。比如:
- 用户切换时,正在播放的音乐要不要暂停?
- 导航中的路线要不要保存?
- 蓝牙通话中的电话要不要挂断?
这些细节,比技术实现更影响用户体验。我曾经因为没处理好蓝牙通话的切换,被用户投诉了好几次。
好了,多用户与账户系统就讲到这里。核心就三件事:管好用户、隔好数据、同步好账户。下一层我们聊聊更具体的系统服务,但那是后话了。
公众号:蓝海资料掘金营,微信deep3321