本文介绍Android端AIMSDK的支持系统、集成方法和简单使用示例,通过本文您将了解如何进行SDK集成。

支持系统

支持Android4.1及以上版本,minSDKVersion为16。

基于NDK18b编译。

集成方法

  1. 配置权限
        <uses-permission android:name="android.permission.WAKE_LOCK"/>
        <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
        <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
        <uses-permission android:name="android.permission.INTERNET"/>
        <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
  2. App导入所需依赖
    // 下载Android SDK,并解压到libs目录
    dependencies {
        implementation fileTree(dir: 'libs', include: ['*.aar'])
    }
  3. 加载动态库
        static {
            // 1. 基座
            // 钉钉定制的sqlite3数据库
            System.loadLibrary("sqlite3");
            // 网络相关动态库
            System.loadLibrary(“gaea”);
            System.loadLibrary("openssl");
            // 基座动态库
            System.loadLibrary("dps");
            // 2. IM 模块
            System.loadLibrary("aim");
        }
    说明 Java层调用AIM相关API前,需先确保System.LoadLibrary(aim)加载完毕。

    动态库会在JNI_OnLoad时进行JNI相关初始化,如在此之前调用Java接口,则可能导致crash。

  4. 启动DingPaaS引擎
    // 创建引擎,仅需创建一次
    DPSPubEngine.CreateDPSEngine();
    
    // 获取引擎实例
    DPSPubEngine engine = DPSPubEngine.GetDPSEngine();
    
    // 获取DingPaaS设置
    DPSPubSettingService setting = engine.getSettingService();
    // 设置必要信息
    setting.setAppKey("appkey");
    setting.setAppID("apitest");
    // 设置本地数据库/数据存储路径, 该路径必须存在,并可有可写权限
    setting.setDataPath("...");
    // 设备唯一ID
    setting.setDeviceId("DeviceID");
    // 构造UA所需的参数
    setting.setAppName("MyDemo"));
    setting.setAppVersion("1.0");
    setting.setDeviceName("...");
    setting.setDeviceType("...");
    setting.setDeviceLocale("...");
    setting.setOSName("...");
    setting.setOSVersion("...");
    setting.setEnvType(DPSEnvType.ENV_TYPE_ONLINE);
    // 向 DingPaaS 服务申请的长链接域名
    setting.setLonglinkServerAddress("...");
    // 向 DingPaaS 服务申请的文件上传服务域名
    setting.setFileUploadServerAddress(ConnectionUtil.getFileAddr());
    //设置登录token获取回调
    setting.setAuthTokenCallback(new DPSPubAuthTokenCallback() {
        @Override
        public void onCallback(String userId, DPSAuthTokenGotCallback onGot,
                               DPSAuthTokenExpiredReason reason) {
            // 向服务端发起请求,获取token
            Auth.getToken(userId, onGot);
        }
    });
    
    // 注册 IM 模块
    DPSModuleInfo imInfo = AIMPubModule.GetModuleInfo();
    engine.registerModule(imInfo);
    
    // 启动引擎,为异步,成功后,将回调listener.onSuccess()
    engine.start(listener)
  5. 混淆配置

    在proguard-rules.pro中增加如下keep项。

    -keep class com.alibaba.dingpaas.** { *; }
    -keep class com.alipay.mars.** { *; }
    -keep class com.alipay.bifrost.** { *; }
    -keep class com.alipay.mobile.** { *; }
    -keep class org.android.spdy.** { *; }
    说明 DingPaaS及AIMSDK需要通过C++进行反向调用Java,上述Java package不能进行混淆。

使用示例

  • 创建用户实例及登录
    // 创建用户 manager
    DPSPubEngine engine = DPSPubEngine.GetDPSEngine();
    // 创建 1234 用户实例,异步,通过listener监听是否创建完成(内部会进行数据库初始化等操作)
    engine.createDPSManager(“1234”, listener);
    ...
    // 创建manager成功后,获取对应用户的Manger
    DPSPubManager manager = engine.getDPSManager("1234");
    DPSAuthService authService = manager.getAuthService();
    authService.addListener(new DPSAuthListener() {
        // 连接状态通知
        @Override
        public void onConnectionStatusChanged(DPSConnectionStatus aimConnectionStatus) {
            Logger.i("OnConnectionStatusChanged " + aimConnectionStatus.toString());
        }
    
        // 登录失败回调
        @Override
        public void onGetAuthCodeFailed(int error_code, String error_msg) {
            Logger.i("OnGetAuthCodeFailed " + s);
        }
    
        // 本地登录成功,可进入IM或其他业务UI
        @Override
        public void onLocalLogin() {
            Logger.i("local login succeed");
        }
    
        // 被踢事件回调,message为被踢下线附带的信息
        @Override
        public void onKickout(String message) {
            Logger.i("OnKickout " + message);
        }
    
        /**
         * 其他端设备在(离)线情况
         * @param type 事件类型(1:事件通知,包括上下线,2:状态通知,在线状态)
         * @param deviceType 设备类型
         * (0:default,1:web,2:Android,3:iOS,4:Mac,5:Windows,6:iPad)
         * @param status      设备状态(1:上线或在线,2:下线或离线)
         * @param time        时间(上线或下线时间)
         */
        @Override
        public void onDeviceStatus(int type, int deviceType, int status, long time) {
            Logger.i("OnDeviceStatus changed:");
        }
    
        /**
         * 下载资源cookie变更事件,仅当需要http下载资源时需要
         * @param cookie      新cookie
         */
        @Override
        public void onMainServerCookieRefresh(String cookie) {
            Logger.i("Cookie refreshed: " + cookie);
        }
        });
    
    authService.login();
    
    // 退出登录,当用户主动登出时调用,正常退出应用无需调用,下次启动可免登,内部自动刷新token
    authService.logout();
  • IM相关:获取会话列表
    // 获取用户(1234)对应的 IM module 实例
    AIMPubModule imModule = AIMPubModule.GetModuleInstance("1234");
    // 获取会话服务
    AIMPubConvService convService = imModule.getConvService();
    if (convService == null) {
        return;
    }
    // 获取100条会话列表
    convService.listLocalConversationsWithOffset(0, 100, new AIMPubConvGetConvListener() {
        @Override
        public void onSuccess(final ArrayList<AIMPubConversation> arrayList) {
            // 注:SDK 的回调均在单独的callback 线程,不能进行UI操作,也不能进行耗时的操作
            new Handler(Looper.getMainLooper()).post(new Runnable() {
                @Override
                public void run() {
                    if (callback != null) {
                        callback.onSuccess(arrayList);
                    }
                }
            });
        }
    
        @Override
        public void onFailure(DPSError aimError) {
            Logger.e("Failed to get convs:" + aimError);
        }
    });
  • IM相关:创建会话
    // 获取用户(1234)对应的 IM module 实例
    AIMPubModule imModule = AIMPubModule.GetModuleInstance("1234");
    // 获取会话服务
    AIMPubConvService convService = imModule.getConvService();
    if (convService == null) {
        return;
    }
    
    // 创建单聊
    ArrayList<String> uidlist = new ArrayList<>();
    uidlist.add("1234"); // 自己的uid
    uidlist.add("5678"); // 对方的uid
    
    AIMPubConvCreateSingleConvParam param = new AIMPubConvCreateSingleConvParam();
    param.uids = uidlist;
    convService.createSingleConversation(param, new AIMPubConvCreateSingleConvListener() {
        @Override
        public void onSuccess(AIMPubConversation AIMPubConversation) {
            // 创建成功
        }
    
        @Override
        public void onFailure(DPSError DPSError) {
            // 创建失败
        }
    });
    
    // 创建群聊
    AIMPubGroupService groupService = imModule.getGroupService();
    if (groupService == null) {
        return;
    }
    AIMPubGroupCreateGroupConvParam param = new AIMPubGroupCreateGroupConvParam();
    param.userInfos = new ArrayList<>();
    HashMap<String, String> extension = new HashMap<String, String>(); 
    param.userInfos.add(new AIMPubGroupUserInfo(“12345”, “nick_name”, extension));
    param.userInfos.add(new AIMPubGroupUserInfo("5678", "张三", null));
    param.userInfos.add(new AIMPubGroupUserInfo("2233", "李四", null));
    param.title = "群名称";
    groupService.createGroupConversation(param, new AIMPubGroupCreateGroupConvListener() {
        @Override
        public void onSuccess(AIMPubConversation AIMPubConversation) {
            // 创建群聊成功
        }
    
        @Override
        public void onFailure(DPSError DPSError) {
            // 创建群聊失败
        }
    });
  • IM相关:发送消息
    // 获取 MsgService
    AIMPubModule imModule = AIMPubModule.GetModuleInstance(uid);
    AIMPubMsgService msgService = imModule.getMsgService();
    
    // 构造文本消息内容
    AIMMsgTextContent textContent = new AIMMsgTextContent();
    Date date = new Date();
    textContent.text = "Hello " + date;
    
    // 构造消息内容
    AIMMsgContent msgContent = new AIMMsgContent();
    msgContent.contentType = AIMMsgContentType.CONTENT_TYPE_TEXT;
    msgContent.textContent = textContent;
    
    // 构造消息
    AIMPubMsgSendMessage sendMessage = new AIMPubMsgSendMessage();
    sendMessage.content = msgContent;
    sendMessage.receivers = conv.userids;
    sendMessage.cid = conv.cid;
    
    Logger.i("Send message begin");
    msgService.sendMessage(sendMessage, new AIMPubMsgSendMsgListener() {
        // 图片等多媒体消息的发送进度
        @Override
        public void onProgress(double progress) {
            Logger.i("Send Message progress: " + progress);
        }
    
        // 消息发送成功
        @Override
        public void onSuccess(AIMPubMessage message) {
            Logger.i("Send Message succeed");
        }
    
        // 消息发送失败
        @Override
        public void onFailure(DPSError aimError) {
            Logger.i("Send Message failed:" + aimError);
        }
    });
  • IM相关:接收消息
    // 获取 MsgService
    AIMPubModule imModule = AIMPubModule.GetModuleInstance(uid);
    AIMPubMsgService msgService = imModule.getMsgService();
    msgService.addMsgListener(new AIMPubMsgListener() {
        @Override
        public void onAddedMessages(final ArrayList<AIMPubNewMessage> arrayList) {
            // 收到新消息的回调,可通过newMsg.type 区分是自己发送的,或在线/离线状态收到的消息
        }
        @Override
        public void onRemovedMessages(ArrayList<AIMPubMessage> arrayList) {
            // 消息被删除的回调
        }
        @Override
        public void onStoredMessages(ArrayList<AIMPubMessage> arrayList) {
            // 消息入库时的回调,如拉消息时,会存入本地数据库
            // 可在该回调内进行消息的加工处理
        }
    });