用户登录与账户:AccountManager、OAuth2.0、多用户切换
车载系统里的用户登录,跟手机上的完全不是一回事。你想想看,手机基本是「一个人用到底」,但车是全家共享的。爸爸开车、妈妈开车、孩子可能也要用——每个人的座椅位置、音乐偏好、导航历史都不一样。所以车载的账户体系,核心就三个事:怎么存账户信息、怎么安全登录、怎么快速切换。
我最早做车载项目时,团队直接照搬了手机端的登录方案。结果呢?用户一换人,整个系统就乱套了。后来才明白,车载场景下,多用户切换不是附加功能,而是核心体验。
AccountManager:车载端的账户管家
Android 系统自带的 AccountManager,说白了就是一个集中管理账户的「保险柜」。它不存密码明文,而是存 token。我习惯用它来管理车载端的账户凭证,因为系统层已经帮我们处理了跨进程访问和加密存储。
举个例子,添加一个账户:
AccountManager am = AccountManager.get(context);
Account account = new Account("user_001", "com.car.auth");
am.addAccountExplicitly(account, null, null);
这里有个坑——addAccountExplicitly 需要 MANAGE_ACCOUNTS 权限。我在项目中遇到过,有些车机厂商把权限收得很紧,导致第三方应用无法直接添加账户。解决办法是用 AccountManager.addAccount() 配合 Intent 回调,让系统弹窗授权。
OAuth2.0:车载端的授权流程
OAuth2.0 在车载端最大的挑战是什么?是「无浏览器环境」。很多车机没有预装 Chrome,或者系统 WebView 版本太老。我建议直接用 Authorization Code + PKCE 流程,这样即使没有浏览器,也能安全完成授权。
为什么用 PKCE?因为车载端的 client secret 很容易被反编译拿到。PKCE 用动态生成的 code verifier 替代了 secret,安全性高了一个档次。
流程大致是这样:
- 车载应用生成一个 code verifier(随机字符串)
- 对 verifier 做 SHA256 哈希,得到 code challenge
- 打开系统浏览器或 WebView,跳转到授权页,带上 challenge
- 用户登录后,服务端返回 authorization code
- 车载应用用 code + verifier 去换 access token
// 生成 code verifier
String verifier = generateRandomString(64);
String challenge = Base64.encodeToString(
sha256(verifier.getBytes()), Base64.URL_SAFE | Base64.NO_PADDING
);
// 构建授权 URL
Uri authUri = new Uri.Builder()
.scheme("https")
.authority("auth.car.com")
.path("/oauth2/authorize")
.appendQueryParameter("response_type", "code")
.appendQueryParameter("client_id", "car_app")
.appendQueryParameter("code_challenge", challenge)
.appendQueryParameter("code_challenge_method", "S256")
.appendQueryParameter("redirect_uri", "carapp://oauth2callback")
.build();
shouldOverrideUrlLoading,而不是等页面加载完。否则用户已经登录成功了,你的应用还在那傻等。
多用户切换:从「登录」到「切换」
车载的多用户切换,跟手机上的「多用户」完全是两码事。手机多用户是隔离的,每个用户有自己的应用和数据。但车载上,用户切换必须无缝——你不能让驾驶员停车等切换完成。
我设计的方案分三层:
| 层级 | 职责 | 实现方式 |
|---|---|---|
| 账户层 | 管理 token、用户信息 | AccountManager + 本地加密存储 |
| 会话层 | 管理当前活跃用户 | UserManager + 自定义 SessionManager |
| 应用层 | 响应切换事件 | BroadcastReceiver + LiveData |
切换时,应用层需要做三件事:
- 保存当前用户的状态(播放列表、导航路线等)
- 清除敏感数据(比如支付信息、通话记录)
- 加载新用户的偏好设置
嗯,这里要注意——不要每次切换都重新登录。我见过有些方案,用户一切换就弹登录页,体验极差。正确的做法是:后台维护多个用户的 token,切换时直接换 token,只有 token 过期才要求重新登录。
SVG 流程图:用户登录与账户体系
这张图展示了我习惯的分层架构。最上层是三个核心模块,中间是具体实现,最下面是应用层需要响应的内容。说白了,就是上层定策略,中层做实现,下层做适配。
最后说一句,车载的账户体系,稳定比功能重要。我见过太多项目,为了加一个「扫码登录」的功能,把整个账户模块搞崩了。记住,用户开车时最不想看到的就是「登录失败,请重试」。