快速开始

网易作为国内最大最早的即时通信开发商之一,从最早的网易泡泡到后来的易信,已经有了超过十五年的通讯技术积累。现在我们整合了这些产品高稳定、高可靠即时通信能力,开发者能以很小的成本将即时通信功能集成到自己的 APP 中。

网易云信即时通讯Android-SDK为Android移动应用提供完善的即时通信功能开发框架,屏蔽其内部复杂细节,对外提供较为简洁的 API 接口,方便第三方应用快速集成即时通信功能。SDK 兼容 Android 4.2+。

SDK集成

云信即时通讯 Android-SDK 支持两种集成方式:

此外,为了让开发者可以轻松快速的在 App 中集成 IM 功能,我们还提供了开源的 UI组件,通过简单的配置就可以实现聊天功能。

Gradle集成

首先,在整个工程的 build.gradle 文件中,配置 repositories,使用 jcenter 或者 maven ,二选一即可,如下:

allprojects {
    repositories {
        jcenter() // 或者 mavenCentral()
    }
}

然后,在主工程的 build.gradle 文件中,添加 dependencies。

android {
   defaultConfig {
       ndk {
           //设置支持的SO库架构
           abiFilters "armeabi-v7a", "x86","arm64-v8a","x86_64"
        }
   }
}

再是根据自己项目的需求,添加不同的依赖。注意:云信的组件版本号必须一致。可在SDK下载页面查看当前最新版本。这里以 x.x.x 版本为例:

dependencies {
    compile fileTree(dir: 'libs', include: '*.jar')
    // 添加依赖。注意,版本号必须一致。

    // 基础功能 (必需)
    implementation 'com.netease.nimlib:basesdk:x.x.x'

    // 聊天室需要
    implementation 'com.netease.nimlib:chatroom:x.x.x'

    // 通过云信来集成小米等厂商推送需要
    implementation 'com.netease.nimlib:push:x.x.x'

    // 超大群需要
    implementation 'com.netease.nimlib:superteam:x.x.x'

    // 全文检索插件
    implementation 'com.netease.nimlib:lucene:x.x.x'
}

手动集成

首先进入SDK下载页面完成下载,然后按需将对应的 SDK 文件拷贝到您的工程的 libs 目录下,即可完成配置。

SDK文件说明如下:

libs
├── arm64-v8a
│   ├── libne_audio.so          //语音消息录制功能
├── armeabi-v7a
│   ├── libne_audio.so
├── x86
│   ├── libne_audio.so
├── x86_64
│   ├── libne_audio.so
│
├── nim-basesdk-x.x.x.jar       //IM基础功能,必需
├── nim-chatroom-x.x.x.jar      //聊天室功能
├── nim-lucene-x.x.x.jar        //全文检索插件
├── nim-push-x.x.x.jar          //通过云信来集成小米等厂商推送时需要

权限与组件

AndroidManifest.xml 中加入以下配置(请将 com.netease.nim.demo 替换为自己的包名):

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
          package="com.netease.nim.demo">

    <!-- 权限声明 -->
    <!-- 访问网络状态-->
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
    <uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/>

    <!-- 外置存储存取权限 -->
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

    <!-- 多媒体相关 -->
    <uses-permission android:name="android.permission.CAMERA"/>
    <uses-permission android:name="android.permission.RECORD_AUDIO"/>
    <uses-permission android:name="android.permission.READ_PHONE_STATE"/>

    <!-- 控制呼吸灯,振动器等,用于新消息提醒 -->
    <uses-permission android:name="android.permission.FLASHLIGHT" />
    <uses-permission android:name="android.permission.VIBRATE" />

    <!-- 8.0+系统需要-->
    <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />


    <!-- 下面的 uses-permission 一起加入到你的 AndroidManifest 文件中。 -->
    <permission
        android:name="com.netease.nim.demo.permission.RECEIVE_MSG"
        android:protectionLevel="signature"/>

     <uses-permission android:name="com.netease.nim.demo.permission.RECEIVE_MSG"/>

    <application
        ...>
        <!-- APP key, 可以在这里设置,也可以在 SDKOptions 中提供。
            如果 SDKOptions 中提供了,则取 SDKOptions 中的值。 -->
        <meta-data
            android:name="com.netease.nim.appKey"
            android:value="key_of_your_app" />

        <!-- 云信后台服务,请使用独立进程。 -->
        <service
            android:name="com.netease.nimlib.service.NimService"
            android:process=":core"/>

       <!-- 云信后台辅助服务 -->
        <service
            android:name="com.netease.nimlib.service.NimService$Aux"
            android:process=":core"/>

        <!-- 云信后台辅助服务 -->
        <service
            android:name="com.netease.nimlib.job.NIMJobService"
            android:exported="true"
            android:permission="android.permission.BIND_JOB_SERVICE"
            android:process=":core"/>

        <!-- 云信监视系统启动和网络变化的广播接收器,保持和 NimService 同一进程 -->
        <receiver android:name="com.netease.nimlib.service.NimReceiver"
            android:process=":core"
            android:exported="false">
            <intent-filter>
                <action android:name="android.intent.action.BOOT_COMPLETED"/>
                <action android:name="android.net.conn.CONNECTIVITY_CHANGE"/>
            </intent-filter>
        </receiver>

        <!-- 云信进程间通信 Receiver -->
        <receiver android:name="com.netease.nimlib.service.ResponseReceiver"/>

        <!-- 云信进程间通信service -->
        <service android:name="com.netease.nimlib.service.ResponseService"/>

        <!-- 云信进程间通信provider -->
        <provider
            android:name="com.netease.nimlib.ipc.NIMContentProvider"
            android:authorities="com.netease.nim.demo.ipc.provider"
            android:exported="false"
            android:process=":core" />
    </application>
</manifest>

混淆配置

如果你的 apk 最终会经过代码混淆,请在 proguard 配置文件中加入以下代码:

-dontwarn com.netease.**
-keep class com.netease.** {*;}

#如果你使用全文检索插件,需要加入
-dontwarn org.apache.lucene.**
-keep class org.apache.lucene.** {*;}

使用说明

接口介绍

SDK 提供了两类接口供开发者使用:第一类是主动发起请求,第二类是作为观察者监听事件和变化。第一类接口名均以 Service 结尾,例如 AuthService ,第二类接口名均以 ServiceObserver 结尾,例如 AuthServiceObserver,个别太长的类名则可能直接以 Observer 结尾,比如 SystemMessageObserver

SDK 接口调用必须在主进程中,请在主进程中调用 SDK XXXService 提供的方法,在主进程中注册 XXXServiceObserver 的观察者(有事件变更,会回调给主进程的主线程)。如果你的模块运行在非主进程,请自行实现主进程与非主进程的通信(AIDL/Messenger/ContentProvider/BroadcastReceiver等IPC渠道)将主进程回调或监听返回的数据传递给非主进程。

SDK 提供三种接口返回值:基本数据类型(同步接口),InvocationFuture(异步接口) 和 AbortableFuture(异步接口)。异步接口基本上都是从主进程发起调用,然后在后台进程执行,最后再将结果返回给主进程。

SDK 接口返回值 说明
基本数据类型 同步接口
InvocationFuture 异步接口
AbortableFuture 异步接口,耗时很长或者传输大量数据时使用,可用 abort() 方法,中断请求。例如上传下载、登录等

异步接口可设置回调函数,提供两种方式:RequestCallback 和 RequestCallbackWrapper。

异步接口回调函数 说明
RequestCallback 需要实现3个接口:
成功 onSuccess, 失败 onFailed, 异常 onException
RequestCallbackWrapper 需要实现 onResult。封装了成功,失败和异常的3个接口,在参数上进行区分

数据缓存目录

当收到多媒体消息后,SDK 默认会下载一些相关的文件,同时 SDK 还要记录一些关键的日志文件,因此 SDK 需要一个数据缓存目录。

该目录可以在 SDK 初始化时通过 SDKOptions#sdkStorageRootPath 进行设置。在 SDK 4.4.0版本起,如果开发者配置在 Context#getExternalCacheDirContext#getExternalFilesDir 等应用扩展存储缓存目录下(即/sdcard/Android/data/{package}),SDK 内部将不再检查写权限。值得注意的是,该缓存目录下的文件会随着App卸载而被删除,也可以由用户手动在设置界面里面清除。

如果不设置,则默认为/{外卡根目录}/{应用包名}/nim/,其中外卡根目录获取方式为 Environment.getExternalStorageDirectory().getPath()

如果你的 APP 需要清除缓存功能,可扫描该目录下的文件,按照规则清理即可。 在 SDK 初始化完成后可以通过 NimClient#getSdkStorageDirPath 获取 SDK 数据缓存目录。

SDK数据缓存目录下面包含:

子目录 内容
log SDK日志文件:如nim_sdk.log,大小一般不超过 8M。
image 图片消息中的原图
audio 语音消息中的音频
video 视频消息中的原视频
thumb 图片/视频消息中的缩略图
file 文件消息中的文件

初始化

初始化

将SDK集成到客户端后,使用SDK前需要先完成初始化工作。此外请注意:v6.9.0起,改用AndroidX支持库,Target API 改为28,不再支持support库

推荐在应用的 Application#onCreate 中,加入 SDK 的初始化代码:

/**
 * 在Application#onCreate()中初始化SDK
 *
 * @param context 调用上下文
 * @param info 登录用户信息。如果提供,将同时进行自动登录。如果当前还没有登录用户,请传入null。详见自动登录章节。
 * @param options 初始化配置参数
 */
public static void init(Context context, LoginInfo info, SDKOptions options);

示例:

public class NimApplication extends Application {
/**
     * 注意:每个进程都会创建自己的Application 然后调用onCreate()方法,
     * 如果用户有自己的逻辑需要写在Application#onCreate()(还有Application的其他方法)中,一定要注意判断进程,不能把业务逻辑写在core进程,
     * 理论上,core进程的Application#onCreate()(还有Application的其他方法)只能做与im sdk 相关的工作
     */
    public void onCreate() {
        // ... your codes

        // SDK初始化(启动后台服务,若已经存在用户登录信息, SDK 将进行自动登录)。不能对初始化语句添加进程判断逻辑。
        NIMClient.init(this, loginInfo(), options());

        // ... your codes

        // 使用 `NIMUtil` 类可以进行主进程判断。
        // boolean mainProcess = NIMUtil.isMainProcess(context)
        if (NIMUtil.isMainProcess(this)) {
            // 注意:以下操作必须在主进程中进行
            // 1、UI相关初始化操作
            // 2、相关Service调用
        }
    }

    // 如果提供,将同时进行自动登录。如果当前还没有登录用户,请传入null。详见自动登录章节。
    private LoginInfo loginInfo() {
        return null;
    }

    // 设置初始化配置参数,如果返回值为 null,则全部使用默认参数。
    private SDKOptions options() {
        SDKOptions options = new SDKOptions();
        ...
        // 配置是否需要预下载附件缩略图,默认为 true
        options.preloadAttach = true;
        ...

        return options;
    }
}

初始化配置参数

初始化时,支持通过SDKOptions设置部分属性来满足不同的业务需求。

SDKOptions 参数说明:

参数 说明
appKey 设置云信SDK的appKey。appKey还可以在AndroidManifest文件中,通过meta-data的方式设置。
statusBarNotificationConfig 云信封装的消息提醒配置
userInfoProvider 用户信息提供者,目前主要用于通知栏显示用户昵称和头像
messageNotifierCustomization 通知栏提醒文案定制
sdkStorageRootPath 外置存储根目录,用于存放多媒体消息文件
preloadAttach 是否需要SDK自动预加载多媒体消息的附件
thumbnailSize 消息缩略图的尺寸
sessionReadAck 是否开启会话已读多端同步
improveSDKProcessPriority 是否提高SDK进程优先级(默认提高,可以降低SDK核心进程被系统回收的概率)
serverConfig 配置私有化的服务器地址
preLoadServers 预加载服务,默认true,不建议设置为false,预加载连接可以优化登陆流程
teamNotificationMessageMarkUnread 群通知消息是否计入未读数,默认不计入未读
useXLog 使用性能更好的SDK日志模式。默认使用普通日志模式。
animatedImageThumbnailEnabled 开启对动图缩略图的支持,默认为 false,截取第一帧
asyncInitSDK 是否异步初始化SDK,默认为 false。开启可降低 Application#onCreate 中 SDK 初始化函数的同步响应时间
reducedIM 是否是弱IM场景,默认为 false。如果您的APP 仅在部分场景按需使用 IM 能力(不需要在应用启动时就做自动登录),并不需要保证消息通知、数据的实时性,那么这里可以填 true。弱 IM 场景下,push 进程采用懒启动策略(延迟到用户登录阶段),启动后其生命周期将跟随 UI 进程,降低弱 IM 场景的APP的后台功耗开销。
checkMainifestConfig 是否在 SDK 初始化时检查清单文件配置是否完全,默认为 false,建议开发者在调试阶段打开,上线时关掉
mixPushConfig 配置第三方推送appid、appkey、证书
enableBackOffReconnectStrategy 是否使用随机退避重连策略,默认true,强烈建议打开。如需关闭,请咨询云信技术支持。
enableLBSOptimize 是否启用网络连接优化策略,默认开启。
enableTeamMsgAck 是否启用群消息已读功能,默认关闭
shouldConsiderRevokedMessageUnreadCount 撤回消息时未读数减一
mNosTokenSceneConfig nos token 场景配置
loginCustomTag 登录时的自定义字段 , 登陆成功后会同步给其他端 ,获取可参考 AuthServiceObserver#observeOtherClients()
disableAwake 禁止后台进程唤醒ui进程
fetchServerTimeInterval 获取服务器时间连续请求间隔时间, 最小1000ms, 默认2000ms
customPushContentType 离线推送不显示详情时,要显示的文案对应的类型名称
notifyStickTopSession 置顶会话是否同步

任意位置初始化SDK

v5.0.0版本开始支持在任意位置初始化SDK,一方面能够降低在Application.onCreate中初始化的耗时,另一方面为了更充分的支持按需使用的弱IM场景。采用此方式初始化SDK,将采用以下两个接口:

还可以通过以下配置,

与在Application#onCreate中初始化SDK相比,新的方式不再需要做进程判断,SDKOptions的应用方式相同。

登录

在调用SDK登录接口之前,需要先完成IM账号的注册(注册一次即可),为应用下的每一位IM用户注册一个唯一的账号(account,又称accid)。推荐开发者首先阅读这里)来加深对云信账号体系流程的认知。 目前,云信提供两种注册方式:

手动登录

在新设备上初次登录,以及被踢、切换账号与注销登录后下一次登录,需要使用手动登录。对应用户手动输入登录账号密码的场景。

/**
 * 登录接口。sdk会自动连接服务器,传递用户信息,返回登录结果。
 * 该操作中途可取消。如果因为网络比较差,或其他原因导致服务器迟迟没有返回,用户也没有主动取消,
 * 在45秒后AbortableFuture的onFailed会被调用到。
 *
 * @param info 登录的用户信息
 * @return AbortableFuture
 */
public AbortableFuture<LoginInfo> login(LoginInfo info);
LoginInfo 参数 说明
account 用户帐号
token 登录 token
appKey(可选) 当前应用的 appKey,一个 appKey 对应一个账号体系。
如果不填,则优先使用 SDKOptions 中配置的 appKey,
如果没有则使用 AndroidManifest 中配置的appKey
customClientType(可选) 自定义客户端类型
public class LoginActivity extends Activity {
    public void doLogin() {
        LoginInfo info = new LoginInfo(); 
        RequestCallback<LoginInfo> callback =
            new RequestCallback<LoginInfo>() {
                    @Override
                    public void onSuccess(LoginInfo param) {
                        LogUtil.i(TAG, "login success");
                        // your code
                    }

                    @Override
                    public void onFailed(int code) {
                        if (code == 302) {
                            LogUtil.i(TAG, "账号密码错误");
                            // your code
                        } else {
                            // your code
                        }
                    }

                    @Override
                    public void onException(Throwable exception) {
                        // your code
                    }
        };

        //执行手动登录
        NIMClient.getService(AuthService.class).login(info).setCallback(callback);
    }
}

针对 onFailed 中的错误码说明如下:

错误码 说明
302 appKey/account/token 三者不对应导致
408 连接超时
415 网络断开或者与云信服务器建立连接失败
416 调用频次过高
1000 登录成功之前,调用本地数据库相关接口(手动登录的情况下数据库未打开)

自动登录

手动登录成功后,保存至本地的用户账号和密码,可用作自动登录时使用。自动登录主要针对应用被清理掉后,如再次点击图标等启动时,无需输入用户名密码即可完成登录的场景。此时可以在无网络,未登录成功的状态下直接访问用户本地SDK数据。

// 在初始化SDK的时候,将本地所存的account与token传入loginInfo(),用以自动登录
NIMClient.init(this, loginInfo(), options());
public class NimApplication extends Application {

    public void onCreate() {
        // ... your codes

        NIMClient.init(this, loginInfo(), options());

        // ... your codes
    }

    private LoginInfo loginInfo() {
        // 从本地读取上次登录成功时保存的用户登录信息
        String account = Preferences.getUserAccount();
        String token = Preferences.getUserToken();

        if (!TextUtils.isEmpty(account) && !TextUtils.isEmpty(token)) {
            DemoCache.setAccount(account.toLowerCase());
            return new LoginInfo(account, token);
        } else {
            return null;
        }
    }
}

登录状态监听

可以通过以下接口来监听当前登录状态:

/**
 * 注册/注销在线状态变化观察者。
 * 注册后,Observer的onEvent方法会被立即调用一次,告知观察者当前状态。
 *
 * @param observer 观察者, 参数为当前状态
 * @param register true为注册,false为注销
 */
public void observeOnlineStatus(Observer<StatusCode> observer, boolean register);

StatusCode为一个包含多个属性的枚举类型,每个属性包含一个int类型的value和一个String类型的desc。服务端踢人时如果配置描述字段,在此回调中会表现在desc变量中。

StatusCode属性 说明
INVALID 未定义
UNLOGIN 未登录/登录失败
NET_BROKEN 网络连接已断开
CONNECTING 正在连接服务器
LOGINING 正在登录中
SYNCING 正在同步数据
LOGINED 已成功登录
KICKOUT 被其他端的登录踢掉,此时应该跳转至手动登录界面
KICK_BY_OTHER_CLIENT 被同时在线的其他端主动踢掉,此时应该跳转至手动登录界面
FORBIDDEN 被服务器禁止登录
VER_ERROR 客户端版本错误
PWD_ERROR 用户名或密码错误
NIMClient.getService(AuthServiceObserver.class).observeOnlineStatus(
    new Observer<StatusCode> () {
        public void onEvent(StatusCode status) {
      //获取状态的描述
      String desc = status.getDesc();
            if (status.wontAutoLogin()) {
                // 被踢出、账号被禁用、密码错误等情况,自动登录失败,需要返回到登录界面进行重新登录操作
            }
        }
}, true);

主动查询登录状态

SDK支持主动查询当前账号是否处于在线状态:

/**
 * 获取当前用户状态
 *
 * @return 当前状态
 */
public static StatusCode getStatus();

数据同步

SDK 在登录成功后,会自动同步群信息,离线消息,漫游消息,系统通知等数据。数据同步过程可以通过以下接口监听:

/**
 * 注册/注销登录后同步数据过程通知
 *
 * @param observer 观察者,参数为同步数据的过程状态(开始/结束)
 * @param register true为注册,false为注销
 */
public void observeLoginSyncDataStatus(Observer<LoginSyncStatus> observer, boolean register);
LoginSyncStatus属性 说明
NO_BEGIN 未开始
BEGIN_SYNC 开始同步(正在同步)。
同步开始时,SDK 数据库中的数据可能还是旧数据。
(如果是首次登录,那么 SDK 数据库中还没有数据,
重新登录时 SDK 数据库中还是上一次退出时保存的数据)
在同步过程中,SDK 数据的更新会通过相应的监听接口发出数据变更通知。
SYNC_COMPLETED 同步完成 。SDK 数据库已完成更新
NIMClient.getService(AuthServiceObserver.class).observeLoginSyncDataStatus(new Observer<LoginSyncStatus>() {
    @Override
    public void onEvent(LoginSyncStatus status) {
        if (status == LoginSyncStatus.BEGIN_SYNC) {
            LogUtil.i(TAG, "login sync data begin");
        } else if (status == LoginSyncStatus.SYNC_COMPLETED) {
            LogUtil.i(TAG, "login sync data completed");
        }
    }
}, register);

在数据同步完成后,整个登录过程才算真正完成。

断网重连

SDK 提供了自动重连机制(自动重新建立与云信服务器的连接并重新登录),所有重连的登录状态变更都会在 observeOnlineStatus 方法中回调。

SDK 在两种场景下会自动进行重连:

满足上述中一个条件,当用户遇到普通网络问题如连接超时等,会自动进行重连登录,不需要上层开发者去做额外的重登逻辑

多端登录与互踢

云信SDK支持配置多种多端登录策略:

多端登录监听

登录成功后,可以注册多端登录状态观察者。

/**
 * 注册/注销多端登录状态观察者。
 *
 * @param observer 观察者,参数为同时登录的其他端信息。
 *                 如果有其他端注销,参数为剩余的在线端。如果没有剩余在线端了,参数为null。
 * @param register true为注册,false为注销
 */
public void observeOtherClients(Observer<List<OnlineClient>> observer, boolean register);
参数 说明
observer 观察者,参数为同时登录的其他端信息。
如果有其他端注销,参数为剩余的在线端。
如果没有剩余在线端了,参数为 null。
register 是否注册观察者,注册为 true, 注销为 false

OnlineClient 接口说明:

返回值 方法 说明
String getOs() 客户端的操作系统信息
int getClientType() 客户端类型
long getLoginTime() 登录时间
String getClientIp() 客户端 IP
String getCustomTag() 登录自定义属性
Observer<List<OnlineClient>> clientsObserver = new Observer<List<OnlineClient>>() {
        @Override
        public void onEvent(List<OnlineClient> onlineClients) {
            if (onlineClients == null || onlineClients.size() == 0) {
                return;
            }
            OnlineClient client = onlineClients.get(0);
            switch (client.getClientType()) {
                case ClientType.Windows:
                // PC端
                    breakcase ClientType.MAC:
                // MAC端
                    break;
                case ClientType.Web:
                // Web端
                    break;
                case ClientType.iOS:
                // IOS端
                    breakcase ClientType.Android:
                // Android端
                    break;
                default:
                    break;
            }
        }
    };

NIMClient.getService(AuthServiceObserver.class).observeOtherClients(clientsObserver, true);

互踢

SDK支持本端主动踢掉其他登录端:

/**
 * 踢掉多端同时在线的其他端
 * @param client 被踢端信息
 * @return InvocationFuture 可设置回调函数,监听操作结果。
 */
public InvocationFuture<Void> kickOtherClient(OnlineClient client);
NIMClient.getService(AuthService.class).kickOtherClient(client).setCallback(new RequestCallback<Void>() {
    @Override
    public void onSuccess(Void param) {
        // 踢出其他端成功
    }

    @Override
    public void onFailed(int code) {
        // 踢出其他端失败,返回失败code
    }

    @Override
    public void onException(Throwable exception) {
        // 踢出其他端错误
    }
});

当被其他端踢掉,可以通过observeOnlineStatus来监听。收到被踢回调后,建议进行注销并切换到登录界面。

此外,还可以通过 AuthService 的getKickedClientType() 方法来获取发起踢掉登录的客户端类型;通过getKickedCustomClientType()方法来获取发起踢掉登录的自定义客户端类型。

注销登录

应用登出/注销自己的账号时需要调用 SDK 的登出操作,该方法没有回调。注意: 登出操作,不要放在 Activity(Fragment) 的 onDestroy 方法中

/**
 * 注销接口
 */
public void logout();
NIMClient.getService(AuthService.class).logout();

其他辅助方法

对于一些弱 IM 场景,需要在登录成功前或者未登录状态下访问指定账号的数据(聊天记录、好友资料等)。 SDK 提供两种方案:

/**
 * 离线时打开本地数据
 * 适用场景:在手动登录没有成功前(可能由于网络问题,登录时间较长),可以访问SDK本地数据。
 * 此外,不调用本接口,采用自动登录也能达到同样的效果。
 *
 * @return 是否成功打开SDK本地数据
 */
public boolean openLocalCache(String account);

NIMClient中提供获取版本号的方法:

/**
 * 运行时获取当前 SDK 版本号
 *
 */
public static java.lang.String getSDKVersion();

MiscService中提供查询云信服务器当前时间的方法:

/**
 * 获取服务器时间 当前服务器时间戳,有频控限制。如果处于频控限制内,返回的时间为上一次获取时间+两次时间的偏移量。接口频控限制为1秒/次。
 *
 */
InvocationFuture<java.lang.Long> getServerTime();