IM 登录最佳实践
更新时间: 2025/11/03 15:41:36
登录对于 IM 产品来说至关重要,是后续业务顺利进行的前提条件。开发者集成 NIM SDK 的各项能力时,如果未能正确使用登录接口或处理登录状态,将引发不必要的问题,影响开发进度。本文详细介绍如何以最佳方式实现 IM 登录功能。
注意事项
- 本文主要介绍 移动端 的登录流程,涉及的接口请参考 登录相关 API 文档。
- 本文以静态 Token 鉴权为例,更多登录方式请参考 登录及登出 IM。
准备工作
根据本文操作前,请确保您已经完成了以下设置:
-
已 集成 SDK。
-
已通过服务端 注册 IM 账号,获取 IM 账号和对应的静态
token。如果仅需要测试和调试,您可通过控制台注册 IM 测试账号。测试账号及对应的静态
token仅适用于调试环境,线上生产环境必须将测试账号及其token替换为云信服务端生成的正式account_id和token。
Demo 体验
您可以参考 登录 Demo 体验完整登录流程。
登录流程
常见的登录流程一般分为三个部分,首次登录、自动登录以及登录状态处理。
首次登录
用户首次打开应用进行登录时,一般需要用户输入账号密码,进行用户自身业务系统的登录,成功后再使用云信返回的 IM 账号和 token 进行 IM 登录。
首次登录流程:
graph LR
A[应用登录界面] --> B[应用业务系统登录]
B -->|成功| C[IM 账号登录]
B -->|失败| D[提示登录错误]
C -->|成功| E[保存 IM 账号信息]
C -->|失败| D
D --> A
%% 样式定义
classDef default fill:#f9f9f9,stroke:#333,stroke-width:1px;
classDef success fill:#dfd,stroke:#333;
classDef error fill:#fdd,stroke:#333;
class E success;
class D error;
接口调用:
- 调用
login方法手动登录 IM。
在登录时 关闭离线模式。
-
调用后处理逻辑:
- 如果登录成功,保存 IM 账号和
token到本地,便于下次应用启动时使用。 - 如果登录失败,提示用户登录失败。
- 如果登录成功,保存 IM 账号和
示例代码:
JavaV2NIMLoginOption option = new V2NIMLoginOption();
//关闭离线模式
option.setOfflineMode(false);
NIMClient.getService(V2NIMLoginService.class).login(accid, token, option, new V2NIMSuccessCallback<Void>() {
@Override
public void onSuccess(Void unused) {
//保存accid、token,用于下次自动登录。
Preferences.saveUserAccount(accid);
Preferences.saveUserToken(token);
// TODO: 登录成功跳转到主页面
}
},
new V2NIMFailureCallback() {
@Override
public void onFailure(V2NIMError error) {
//登录失败
int code = error.getCode();
String desc = error.getDesc();
Toast.makeText(LoginActivity.this, R.string.tip_login_fail, Toast.LENGTH_SHORT).show();
}
});
}
Objective-CV2NIMLoginOption *loginOption = [[V2NIMLoginOption alloc] init];
loginOption.offlineMode = NO;
loginOption.forceMode = YES;
[[NIMSDK sharedSDK].v2LoginService login:accountId token:token option:loginOption success:^{
NSLog(@"=== 登录成功");
//缓存账号密码到本地
//跳转到主页面
} failure:^(V2NIMError * _Nonnull error) {
}];
自动登录
用户登录成功后,再次打开应用,一般无需用户输入账号密码,而是程序内部获取上次登录的 IM 的账号和 token,通过离线方式登录 IM,此次登录会优先打开本地数据库,即使无网络的情况下也可以正常访问本地数据。
自动登录流程:
graph LR
A[应用启动] --> B[自动登录]
B -->|成功| C[读取上次登录信息] --> D[离线模式登录 IM] --> E[登录成功进入主界面]
B -->|失败| F[打开登录页面使用手动登录] --> G[用户输入账号和 token] --> H[验证登录] --> E[登录成功进入主界面]
H -->|失败| F[打开登录页面使用手动登录]
%% 样式定义
classDef default fill:#f9f9f9,stroke:#333,stroke-width:1px;
classDef success fill:#dfd,stroke:#333;
classDef error fill:#fdd,stroke:#333;
class D,E success;
class F error;
接口调用:
-
获取上次登录的 IM 账号和
token。 -
调用
login方法登录 IM。
在登录时 开启离线模式。
- 开启离线模式后,登录会统一走失败回调,当状态码为 191008 时表示进入离线模式,可以进入主页面。
示例代码:
JavaV2NIMLoginOption option = new V2NIMLoginOption();
//本次登录采用离线登录,无网络下也可以登录成功,后面 SDK 内部会自动重连
option.setOfflineMode(true);
NIMClient.getService(V2NIMLoginService.class).login(account, token, option, new V2NIMSuccessCallback<Void>() {
@Override
public void onSuccess(Void unused) {
Log.e(TAG,"login onSuccess");
// 登录成功跳转到主页面
}
},
new V2NIMFailureCallback() {
@Override
public void onFailure(V2NIMError error) {
Log.e(TAG,"login onFailure:"+error.getCode()+","+error.getDesc());
if (191008 == error.getCode()) {
//进入离线模式,数据已经打开,跳转到主页面
}else {
//自动登录失败,清理登录缓存信息,返回登录页面
Preferences.saveUserAccount("");
Preferences.saveUserToken("");
}
}
});
}
Objective-CV2NIMLoginOption *loginOption = [[V2NIMLoginOption alloc] init];
loginOption.offlineMode = YES;
[[NIMSDK sharedSDK].v2LoginService login:accountId token:token option:loginOption success:^{
NSLog(@"=== 登录成功");
//缓存账号密码到本地
//跳转到主页面
} failure:^(V2NIMError * _Nonnull error) {
if (error.code == 191008) {
//进入离线模式,数据已经打开,跳转到主页面
} else {
//自动登录失败,清理登录缓存信息,返回登录页面
}
}];
登录状态处理
在 IM 初始接口调用之后,可以在应用的主页面注册 IM 的登录回调,处理一些业务逻辑,如 UI 层提示用户当前连接状态、被踢、多端登录等。
登录状态处理流程:
graph LR
A[应用主页面启动] --> B[注册登录状态回调]
B --> C[收到登录状态事件] --> D[UI 提示用户]
B --> E[收到被踢事件] --> F[打开登录页面使用手动登录]
B --> G[收到登录失败事件] --> F[打开登录页面使用手动登录]
%% 样式定义
classDef default fill:#f9f9f9,stroke:#333,stroke-width:1px;
classDef success fill:#dfd,stroke:#333;
classDef error fill:#fdd,stroke:#333;
class D success;
class F error;
接口调用:
-
进入应用主页面。
-
调用
addLoginListener添加登录状态监听。 -
收到被踢、登录失败等事件后,清理当前登录信息,并返回登录页面。
示例代码:
Javaprivate V2NIMLoginListener loginListener = new V2NIMLoginListener() {
@Override
public void onLoginStatus(V2NIMLoginStatus status) {
switch (status){
case V2NIM_LOGIN_STATUS_LOGOUT:
tvLoginStatus.setText("登出");
break;
case V2NIM_LOGIN_STATUS_UNLOGIN:
tvLoginStatus.setText("未登录");
break;
case V2NIM_LOGIN_STATUS_LOGINING:
tvLoginStatus.setText("登录中");
break;
case V2NIM_LOGIN_STATUS_LOGINED:
tvLoginStatus.setText("登录成功");
break;
}
Log.e(TAG,"loginListener onLoginStatus:"+status.toString());
}
@Override
public void onLoginFailed(V2NIMError error) {
//登录失败,清理登录缓存信息,返回登录页面
Preferences.saveUserAccount("");
Preferences.saveUserToken("");
}
@Override
public void onKickedOffline(V2NIMKickedOfflineDetail detail) {
//用户被踢,清理登录缓存信息返回登录页面
Preferences.saveUserAccount("");
Preferences.saveUserToken("");
}
@Override
public void onLoginClientChanged(V2NIMLoginClientChange change, List<V2NIMLoginClient> clients) {
}
};
//
NIMClient.getService(V2NIMLoginService.class).addLoginListener(loginListener);
Objective-C[[NIMSDK sharedSDK].v2LoginService addLoginListener:self];
- (void)onLoginFailed:(V2NIMError *)error {
//登录失败,清理登录缓存信息,返回登录页面
}
- (void)onKickedOffline:(V2NIMKickedOfflineDetail *)detail {
//用户被踢,清理登录缓存信息返回登录页面
}
获取登录状态
通过调用 getLoginStatus 获取登录状态,如果用户已经处于已登录和登录中状态,请勿再频繁调用登录接口登录。
| 登录状态 | 说明 |
|---|---|
| V2NIM_LOGIN_STATUS_LOGOUT(0) | 已登出 |
| V2NIM_LOGIN_STATUS_LOGINED(1) | 已登录 |
| V2NIM_LOGIN_STATUS_LOGINING(2) | 正在登录 |
| V2NIM_LOGIN_STATUS_UNLOGIN(3) | 未登录 |
JavaV2NIMLoginStatus status = NIMClient.getService(V2NIMLoginService.class).getLoginStatus();
Objective-C- (void)printLoginStatus:(V2NIMLoginStatus)status
{
switch (status) {
case V2NIM_LOGIN_STATUS_LOGOUT:
NSLog(@"login status = logout");
break;
case V2NIM_LOGIN_STATUS_LOGINING:
NSLog(@"login status = logining");
break;
case V2NIM_LOGIN_STATUS_LOGINED:
NSLog(@"login status = logined");
break;
default:
NSLog(@"login status = %ld", status);
}
}
V2NIMLoginStatus status = [[[NIMSDK sharedSDK] v2LoginService] getLoginStatus];





