集成步骤

下载开发包

点击下载

Android

编译链接

亲加API要求您使用的NDK版本不低于android-ndk-r8b,android-SDK不低于2.3。一般而言,cocos2d-x安卓工程由一个libcocos2dx库工程和一个 app工程组成,如下图红色标注所示(以cocos2d-x-3.3为例),app工程依赖libcocos2dx工程。 解压开发包后,根目录有一个android文件夹,参照步骤将里面的gotyeapi目录拷贝至app工程的jni目录里( libs-ifly请先跳过,后面会做介绍), 然后将gotyeapi目录下的gotyeapi.jar文件移动至libcocos2dx工程的libs目录下,如步骤所示 (点此查看大图):

拷贝之后对jni目录下的Android.mk做以下修改(如上图步骤):

链接Android日志库(如果已链接可忽略):

LOCAL_LDLIBS += -llog

链接gotyeapi静态模块:

LOCAL_WHOLE_STATIC_LIBRARIES += gotyeapi_static

include $(BUILD_SHARED_LIBRARY)

$(call import-add-path,$(LOCAL_PATH))
$(call import-module, gotyeapi)

配置AndroidManifest.xml文件

添加以下权限(网络访问、音频录制及读写外部存储)到AndroidManifest.xml文件中:

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

亲加API要求在libcocos2dx工程的Cocos2dxActivity.java中加入初始化操作,而且初始化接口调用必须紧跟随动态库加载操作执行完成,如上图所示。onLoadNativeLibraries()函数实现如下,完成对cocos2dx动态库的加载:

protected void onLoadNativeLibraries() {
    try {
        ApplicationInfo ai = getPackageManager().getApplicationInfo(getPackageName(), PackageManager.GET_META_DATA);
        Bundle bundle = ai.metaData;
        String libName = bundle.getString("android.app.lib_name");
        System.loadLibrary("cocos2dcpp");
    } catch (Exception e) {
        e.printStackTrace();
    }
}

紧随其后初始化亲加API:

GotyeAPI.getInstance().init(this, "9c236035-2bf4-40b0-bfbf-e8b6dec54928", GotyeAPI.SCENE_COCOS2DX);

注意:cocos2d-x版本不同,加载动态库的时机可能不尽一样,不管如何变化,只要保证在加载操作执行(System.loadLibrary)之后马上调用亲加API的初始化接口就OK(可在libcocos2dx工程搜索System.loadLibrary)。

亲加API在新版本中内置了讯飞语音转文字功能,如果使用该功能,则需要将libs-ifly目录下面的libmsc.so,Msc.jar及Sunflower.jar拷贝至工程中对应位置,同时将两个jar包添加到工程的build Path下。另外还需要添加以下权限:

<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_NETWORK_STATE" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.READ_CONTACTS" />

设置JVM

亲加API需要设置JavaVM实例(仅针对Android), 否则api无法正常工作:

#include “GotyeAPI.h”
apiist->setJVM(JniHelper::getJavaVM());/*如果是cocos2d-x引擎,可引用JniHelper.h,调用getJavaVM接口即可,确保调用前JniHelper::setJavaVM接口已经被系统调用;对一般JNI来说,可在jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved)设置api的JVM*/

驱动GotyeAPI(仅针对Android)

GotyeAPI通过接口mainLoop将异步回调通知到主线程,因此,GotyeAPI需要得到主线程驱动,具体方法是, 在cocos2d-x调度器CCScheduler.cpp的update函数里面,调用GotyeAPI::mainLoop函数:

#include “GotyeAPI.h”
void Scheduler::update(float dt)
{
    …
    apiist->mainLoop();/* api在主线程循环驱动下,将各类异步回调通知到调用层 */
}

提示:引用GotyeAPI.h接口,需要将开发包中的platform目录下的include目录拷贝到你们的工程,同时把include所在路径加入到Android.mk的LOCAL_C_INCLUDES变量中,否则NDK会找不到头文件导致编译失败。

下面的代码演示了安卓平台下使用亲加API实现登录、发送文本消息、发送语音短信、语音识别、接收消息,下载和播放消息等功能:

#include "AppDelegate.h"
#include "cocos2d.h"
#include "platform/android/jni/JniHelper.h"
#include <jni.h>
#include <android/log.h>
#include "GotyeAPI.h"

USING_NS_GOTYEAPI;

#define  LOG_TAG    "main"
#define  LOGD(...)  __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__)

using namespace cocos2d;

class MyDelegate:public GotyeDelegate
{
public:
// 监听登录回调
 virtual void onLogin(GotyeStatusCode code, const GotyeLoginUser& user){
     LOGD("login result: %d", code);

     // 登录成功,发送一条文本消息给Finn
     GotyeUser someone("Finn");
     GotyeMessage message = GotyeMessage::createTextMessage(someone, "hello,this is a simple text message from gotyeapi for cocos2d-x.");
     apiist->sendMessage(message);
 }

// 监听登出回调
 virtual void onLogout(GotyeStatusCode code){
     LOGD("logout, code(%d)", code);
 }

// 监听消息发送回调
 virtual void onSendMessage(GotyeStatusCode code, const GotyeMessage& message){
     LOGD("sendMessage result: %d", code);
 }

  // 监听消息接收回调
 virtual void onReceiveMessage(const GotyeMessage& message, bool* downloadMediaIfNeed){
     LOGD("receive a message: type(%d), from %s", message.type, message.sender.name.c_str());

     if(message.hasExtraData()){
         char buf[512] = {0};
         message.getExtraData(buf);
         LOGD("message extra data: %s", buf);
     }

     if(message.type == GotyeMessageTypeText){
         LOGD("text message content: %s", message.text.c_str());
         // 收到内容为sa的文本消息时,开始录制一段10秒的语音发送给<文本消息发送者>
         if(0 == strcmp(message.text.c_str(), "sa"/*send audio*/)){
             int result = apiist->startTalk(message.sender, GotyeWhineModeDefault, false, 10000);
             LOGD("start recording(result:%d)...", result);
         }
     }else if(message.type == GotyeMessageTypeAudio){
         GotyeMessage msg = message;
         apiist->downloadMediaInMessage(msg);
     }
 }

  // 监听录音停止回调
 virtual void onStopTalk(GotyeStatusCode code, bool realtime, GotyeMessage& message, bool *cancelSending){
     if(code != GotyeStatusCodeOK){
         return;
     }

     LOGD("onStopTalk, code(%d), duration(%d), receiver(%s)...", code, (int)message.media.duration, message.receiver.name.c_str());

     if( message.text.length() > 0){ ///< 将语音识别的结果,作为消息附加字段发送出去
         *cancelSending = true; ///< 取消自动发送
         message.putExtraData(message.text.c_str(), strlen(message.text.c_str())); ///< 设置消息附加字段
         apiist->sendMessage(message); ///< 手动发送消息
     }
 }

// 监听消息下载回调
 virtual void onDownloadMediaInMessage(GotyeStatusCode code, const GotyeMessage& message){
     LOGD("downloading completed. start playing...");
     if(message.type == GotyeMessageTypeAudio){
         apiist->playMessage(message); ///< 下载完成马上播放
     }
 }
};

MyDelegate *listener = nullptr;

void cocos_android_app_init (JNIEnv* env, jobject thiz) {
    LOGD("cocos_android_app_init");
    AppDelegate *pAppDelegate = new AppDelegate();

    apiist->setJVM(JniHelper::getJavaVM());///< 设置JVM
    apiist->initIflySpeechRecognition();///< 初始化语音识别(如使用语音识别请加上此行)
    listener = new MyDelegate();
    apiist->addListener(*listener);///< 添加监听器
    apiist->login("cc-an", nullptr); ///< 使用cc-an账号登录
}

iOS

编译链接

将压缩包根目录下的include文件夹添加到您的工程中,将libs目录下的libgotyeapi.a静态库(另外还有一个libgotyeapi_c++11.a,二者只能选其一, 后面会介绍其区别)添加到您的工程,如下图红色框所示。同时请添加下图绿色框中的系统库:

如果您的工程指定了下图所示的工程设置,则必须使用libgotyeapi_c++11.a:

说明

即时通讯云C++ API(后续简称API)接口具备跨平台特性,本文档内容适合iOS/Android/Linux/Windows。如需使用API接口,则在对应平台工程下添加发布版本include目录下的所有头文件,在需要用到API的文件中引用GotyeAPI.h头文件,同时申明API名空间:

//在任何地方引用API,只需要包含GotyeAPI.h头文件即可。
#include "GotyeAPI.h"
USING_NS_GOTYEAPI;///< 使用gotyeapi名空间,后续代码段不再提示。

友情提示:SDK是否有lua接口?
        我们的SDK没有lua接口,这个需要用户自己封装,目前只支持C++版本。

初始化

初始化

API的初始化非常重要,请准确填写您的appkey以及应用程序包名:

//使用您在亲加管理平台申请到的appkey和您的应用程序包名初始化API,请确保两项参数填写均准确无误。
//为了键入方便,在使用GotyeAPI单实例的时候,可以使用宏apiist来代替,下同。参考代码:
apiist->init("6d1c291e-75a8-4a6a-acd8-22cbb951ce80","com.gotye.api.demo");

这里需要注意:如果已经调用了登录接口,不管是在登录中还是已登录成功,调用该接口会失败,除非退出登录。API不允许在登录状态下修改AppKey和应用程序包名。

退出

应用程序退出时请调用如下接口,这个接口会终止API内部所有的子线程,同时会销毁API所有模块组件(该过程不可逆):

apiist->exit();

注册/移除 监听

API的所有异步接口执行结果的回调,都是通过GotyeDelegate类通知到调用层。如果某个类需要监听异步回调,只需要从GotyeDelegate类继承,重写需要监听的回调即可。下面以监听登录回调为例:

class yourClass: public GotyeDelegate
{
    virtual void onLogin(GotyeStatusCode code, const GotyeLoginUser& user){
    if(code==GotyeStatusCodeOK){
        //you have signed in the server successfully, do something you are interested in.
    }
};

//创建该类的一个实例并添加该实例到API,以监听异步回调
yourClass *plistener = new yourClass();
apiist-> addListener(*plistener);

注意:如果被添加到API中的监听对象即将要被释放,一定要在释放前调用以下接口将其从API中及时移除,否则会造成API访问野指针而出现不可预知的错误:

apiist-> removeListener(*plistener);

线程安全

为了简化使用,API的所有异步回调都是在UI主线程被执行,值得注意的是,API的接口本身并非线程安全的,在不同的线程去调用API接口,极有可能导致无法预料的运行结果,因此我们强烈推荐:仅在UI主线程去调用API接口。

常用数据结构定义

多媒体(GotyeMedia)

GotyeMediaType type;    ///<媒体类型(音频/图片/用户数据/附加数据)
GotyeMediaStatus status; ///<下载状态(未下载/下载中/完成/下载失败),只针对音频/图片
std::string url; ///<上传/下载音频/图片的相对Url地址
std::string path;    ///<存储音频/缩略图/图标(头像)/用户数据/附加数据绝对文件路径
std::string pathEx; ///<存储原始图片/解码后的PCM音频绝对文件路径
unsigned duration;  ///<语音时长(单位:毫秒),仅针对音频类型

注意:API会自动为每个多媒体对象创建好文件存储路径,但并不意味着指定路径下的文件就一定存在,有些是需要通过下载接口调用才能获取到指定文件的,比如音频,原始图片,PCM音频数据。

聊天对象基类(GotyeChatTarget)

GotyeChatTargetType type;   ///<聊天对象类型(用户/聊天室/群组)
long long id;    ///<聊天室/群组的唯一标志符,从服务器获取,该字段对用户无效
std::string name;    ///<用户唯一标志符,如果对象类型为聊天室/群组时,这个字段表示其名称     
std::string info; ///<扩展信息字段,可修改并提交服务器
bool hasGotDetail;///<指定该聊天对象是否已经从服务器获取到了详细信息
GotyeMedia icon;    ///<用户/聊天室/群组头像,图片路径存储在其path字段

GotyeChatTarget是用户(GotyeUser)/聊天室(GotyeRoom)/群组(GotyeGroup)的公共基类,使用时请不要直接构造一个GotyeChatTarget基类对象,参考下面其子类构造函数。

用户(GotyeUser)

std::string nickname;///<用户昵称
GotyeUserGender gender;///<用户性别
bool isBlocked;///<是否是黑名单用户
bool isFriend;///<是否为好友

申明一个用户非常简单:

GotyeUser user(“someone”);  ///<构造一个账号为someone的单聊用户

聊天室(GotyeRoom)

bool isTop; ///<是否为顶级聊天室
unsigned capacity; ///<该聊天室可容纳的最多人数
unsigned onlineNumber;  ///<当前在线人数

一般来说聊天室/群组不需要由使用者自己创建,而是通过API接口获取并构造好,除非已经明确知道聊天室/群组的唯一标志ID。

群组(GotyeGroup)

GotyeGroupType ownerType; ///<群类型(公共群/私有群)
std::string ownerAccount; ///<群的所有者账号
bool needAuthentication;///<是否需要认证加入
unsigned capacity; ///<群成员最大数量

通知(GotyeNotify)

long dbID;  ///<本地数据库id
long date; ///<通知发送时间
bool isRead; ///<是否已读
GotyeChatTarget sender;///<发送者
GotyeChatTarget receiver;///<接收者
GotyeChatTarget from; ///<通知来源
bool agree; ///<是否同意
bool isSystemNotify;///<是否是系统通知
GotyeNotifyType type;///<通知类型(群邀请/入群请求/入群回复)
std::string text;   ///<附加文本信息

消息(GotyeMessage)

long long id;   ///<消息在服务器上的唯一存储标识
unsigned date;  ///<消息时间
long long dbID;      ////<消息在本地的唯一存储标识
std::string text;    ///<文本内容,只针对文本消息有效
GotyeMedia media;   ///<保存音频/图片/用户数据
GotyeMedia extra;   ///<保存附加数据
GotyeMessageType type;  ///<消息类型
GotyeMessageStatus status;  ///<消息状态(已读/未读/发送中/已发送/发送失败)
GotyeChatTarget sender, receiver;   ///<发送者和接收者
bool hasMedia() const; ///<检测该消息是否有多媒体文件
bool hasExtraData() const; ///<检测该消息是否有附加数据

接口返回值(状态码)一览表

GotyeStatusCodeWaitingCallback          = -1,   ///<异步调用成功,请等待回调
GotyeStatusCodeOK                       = 0,    ///<操作成功
GotyeStatusCodeSystemBusy               = 1,    ///<系统忙,正在处理中
GotyeStatusCodeNotLoginYet              = 2,    ///<还未登陆
GotyeStatusCodeCreateFileFailed         = 3,    ///<创建文件失败
GotyeStatusCodeTargetIsSelf             = 4,    ///<目标是自己(已废除)
GotyeStatusCodeReloginOK                = 5,    ///<重登陆成功
GotyeStatusCodeOfflineLoginOK           = 6,    ///<离线登陆模式成功
GotyeStatusCodeTimeout                  = 300,  ///<超时
GotyeStatusCodeVerifyFailed             = 400,  ///<验证失败
GotyeStatusCodeNoPermission             = 401,  ///<没有权限
GotyeStatusCodeRepeatOper               = 402,  ///<重复操作
GotyeStatusCodeGroupNotFound            = 403,  ///<群组未找到
GotyeStatusCodeUserNotFound             = 404,  ///<用户未找到
GotyeStatusCodeLoginFailed              = 500,  ///<登录失败(此命名有误,应为操作失败)
GotyeStatusCodeForceLogout              = 600,  ///<强制登出(被其他设备同一账号踢下线).
GotyeStatusCodeNetworkDisConnected      = 700,  ///<网络连接断开
GotyeStatusCodeRoomNotExist             = 33,   ///<聊天室不存在
GotyeStatusCodeRoomIsFull               = 34,   ///<聊天室人数已满
GotyeStatusCodeNotInRoom                = 35,   ///<不在聊天室内
GotyeStatusCodeForbidden                = 36,   ///<操作禁止
GotyeStatusCodeAlreadyInRoom            = 39,   ///<已经在聊天室中
GotyeStatusCodeUserNotExist             = 804,  ///<用户不存在
GotyeStatusCodeRequestMicFailed         = 806,  ///<请求Mic失败
GotyeStatusCodeVoiceTimeOver            = 807,  ///<录音时间超出
GotyeStatusCodeRecorderBusy             = 808,  ///<录音设备正在使用
GotyeStatusCodeVoiceTooShort            = 809,  ///<录音时间过短< 1000ms
GotyeStatusCodeInvalidArgument          = 1000, ///<有不合法参数
GotyeStatusCodeServerProcessError       = 1001, ///<服务器处理失败(可能含有非法参数)
GotyeStatusCodeDBError                  = 1002, ///<操作数据库失败.
GotyeStatusCodeUnkonwnError             = 1100  ///<未知错误

登录退出

登录/退出

//使用指定的用户名登录,应该确保该用户名在整个app数据库系统中是唯一的,否则会出现在同一个appkey之下,使用相同的用户名登录会互相挤掉线的情况,如果没有密码,第二个参数可不填或者填nullptr
apiist->login("username", nullptr);///<对应回调GotyeDelegate::onLogin

apiist->logout();///<退出登录,对应回调GotyeDelegate::onLogout

注意: API大部分接口返回值都是status类型,该类型是个枚举体(GotyeStatusCode), 凡是所有具备对应异步回调的接口,正常返回值应该是GotyeStatusCodeWaitingCallback(-1),后续不再赘述。

登录回调

登录回调(GotyeDelegate::onLogin)中的状态码可能有以下五种情况:
GotyeStatusCodeOK:正常登录成功
GotyeStatusCodeOfflineLoginOK:离线登录成功
GotyeStatusCodeReloginOK:重新登录成功(离线转在线)
GotyeStatusCodeVerifyFailed:认证失败
GotyeStatusCodeNetworkDisConnected:网络请求失败

登出回调

登出回调(GotyeDelegate::onLogout)中的状态码可能有以下三种情况:
GotyeStatusCodeOK:正常登出成功
GotyeStatusCodeNetworkDisConnected:网络异常,转换成离线状态
GotyeStatusCodeForceLogout:账号在其他设备登录,被强制下线

断线重连

如果某个账号已经调用接口登录成功,那么在整个app运行期间,只要用户不调用退出登录接口,期间不管网络状况如何变化,API均会在底层尝试重连,每次重连耗时15秒以上仍未成功则会被认为超时,并在5秒后尝试下一次重连。但期间不管网络是否正常,如果用户不小心调用了logout,API会认为用户有意退出登录,就会回到初始状态,不再有任何重连操作,除非用户重新调用登录接口。

在线状态

API通过以下接口可以获取到当前在线状态:

//调用下面的接口可以获知当前是否处于在线状态
//其返回值可以参考以下宏定义:
//#define NETSTATE_OFFLINE        -1
//#define NETSTATE_BELOWLINE      0  
//#define NETSTATE_ONLINE          1
intonline = apiist->isOnline();

值得注意的是,如果API处于离线状态,一旦网络恢复正常,API会自动重连,重连成功后,API会转换成在线状态。

获取账户信息

API在登录成功后,会自动向服务器获取登录账号的详细信息,如果获取成功,会通过以下回调通知给出:

//详见GotyeDelegate.h
virtual void onGetProfile(GotyeStatusCode code, const GotyeLoginUser& user) Optional;

修改账户信息

GotyeLoginUser loginUser = apiist->getLoginUser();
loginUser.info = “too young, too simple, too naive”;/// <修改扩展信息
std::string imagePath = “/mnt/sdcard /icon.jpg”;///<设定新头像路径,目前仅支持jpg
apiist->reqModifyUserInfo(loginUser, & imagePath);///<对应异步回调GotyeDelegate:: onModifyUserInfo

注意: 如果不需要对头像进行修改,第二个参数传nullptr(默认形参值即为nullptr)。

好友系统

用户搜索

apiist-> resetUserSearch();/// <重置用户搜索,会将本地搜索结果列表和当前页搜索结果列表清空

调用以下接口可以获取到搜索结果列表引用,该列表属于全局变量,可以直接保存其指针并使用,而不用担心其内存被释放:

const std::vector<GotyeUser>* pSearchList =&apiist->getLocalUserSearchList();

这个列表会将每次搜索请求返回的结果累计保存起来,以便用于添加好友或者界面展示等应用场景。

下面的接口调用返回单次搜索结果列表:

const std::vector<GotyeUser>* pSearchList =&apiist->getLocalUserSearchCurPageList ();

同理,该列表引用也是全局变量,可直接保存其指针并使用。

搜索用户的接口原型如下:

status reqSearchUserList(unsigned pageIndex = 0, /// <搜索结果页索引,默认从0开始
const std::string& username = "", /// <设定用户名关键字,默认为空串
const std::string& nickname="", /// <设定昵称关键字,默认为空串
GotyeUserGender gender = SEX_IGNORE); /// <设定性别关键字,默认忽略性别

以下接口的调用将会向服务器请求appkey中所有用户的第一页:

apiist->reqSearchUserList();/// <对应回调GotyeDelegate::onSearchUserList

注意:

1.如果pageIndex 为0,API会先清除上述两个搜索列表,相当于默认调用了resetUserSearch

2.搜索结果会保存在上述两个列表中,区别在于getLocalUserSearchCurPageList仅保存本次页面的搜索结果,而getLocalUserSearchList则会累计保存多次搜索请求的所有结果。

3.搜索结果中的GotyeUser已经包含了最新用户详情

4.异步回调中的两个列表引用参数curPageList和allList与上述两个接口是一个意思:curPageList和getLocalUserSearchCurPageList是同一个列表;allList对应getLocalUserSearchList。

5.搜索关键字的设定是并且的关系,而不是或者。如果指定username=”abc”同时指定nickname=”abc”的话,则表示搜索结果必须同时满足这两个条件。

好友和黑名单简介

亲加API支持好友和黑名单,这两个概念是互不干涉的,例如用户A可以是用户B的好友,同时A也可以在B的黑名单列表中。另外这两个概念,都是单向的,即A在B的好友列表, B却不一定在A的好友列表。A在B的黑名单列表,B可以不在A的黑名单列表。发送消息时,即便AB之间不存在任何好友关系,A和B都可以相互通讯。但是,如果A在B的黑名单时,A给B发送消息会失败。

获取好友列表/黑名单

调用以下接口可以返回本地数据库存储的好友列表,该列表也属于全局变量:

const std::vector<GotyeUser>* pFriendList =&apiist->getLocalFriendList ();

如需向服务器请求更新该列表,可以调用以下接口:

apiist->reqFriendList();/// <对应回调GotyeDelegate::onGetFriendList

成功获取后,通过getLocalFriendList接口获取到的本地好友列表也会被更新,因此收到回调后,使用保存的列表指针即可刷新UI(如果需要的话)。

获取本地黑名单列表:

const std::vector<GotyeUser>* pBlockedList =&apiist->getLocalBlockedList ();

请求更新:

apiist->reqBlockedList ();/// <对应回调GotyeDelegate::onGetBlockedList

添加/删除好友/黑名单

添加好友(参数user为GotyeUser类型):
apiist->reqAddFriend (user);/// <对应回调GotyeDelegate::onAddFriend,同时会更新本地好友列表

删除好友:

apiist->reqRemoveFriend (user);/// <对应回调GotyeDelegate::onRemoveFriend,同时会更新本地好友列表

添加黑名单:

apiist->reqAddBlocked (user);/// <对应回调GotyeDelegate::onAddBlocked,同时会更新本地黑名单列表

从黑名单移除:

apiist->reqRemoveBlocked (user);/// <对应回调GotyeDelegate::onRemoveBlocked,同时会更新本地黑名单列表

获取用户详情

在API消息数据类型中(后续会有详细介绍),发送者和接收者通常都是GotyeChatTarget类型,它是用户(GotyeUser),群(GotyeGroup)以及聊天室(GotyeRoom)的共同父类,包含了这3类数据结构的基本属性,但有时候仅有这些基本信息还不够,为了能通过GotyeChatTarget变量获取到更多的详情,可以使用如下接口(以用户为例,其中target是GotyeChatTarget类型):

GotyeUser user = apiist->getUserDetail (target,false);

注意:

1.这个接口会直接从本地数据库查询用户详情,如果发现本地数据库查询不到,则会忽略掉第二个参数,自动向服务器请求详情,请求成功会通过回调GotyeDelegate:: onGetUserDetailList给出通知;

2.第二个参数forceRequest的含义是:当该值为false时,只要本地数据库有详情,则不会再向服务器请求,否则一定会发起查询请求;如果为true,则不管本地数据库是否存在数据,都会强制向服务器发起查询请求。

获取聊天室和群详情同理:

GotyeRoom room = apiist->getRoomDetail (target);
GotyeGroup group = apiist->getGroupDetail (target,false);

获取用户头像:

有时候我们会希望在界面上展示好友(群/聊天室)头像,这个时候可以调用如下接口去下载其头像到本地(其中user为GotyeUser类型,当然也可以是GotyeRoom或者GotyeGroup):

apiist->downloadMedia (user.icon);/// <对应回调GotyeDelegate::onDownloadMedia

聊天室

获取聊天室列表

调用以下接口可以获取到本地数据库缓存聊天室列表,该列表也是全局变量:

const std::vector<GotyeRoom>* pRoomList =&apiist->getLocalRoomList ();

清除本地聊天室列表缓存:

apiist->clearLocalRoomList ();

向服务器请求更新聊天室信息:

apiist->reqRoomList ();/// <对应回调GotyeDelegate::onGetRoomList

请求成功的话,API会自动更新本地聊天室列表,同时写入数据库。

进入聊天室

调用下述代码可以进入指定聊天室(其中的room为GotyeRoom类型):

apiist->enterRoom (room);/// <对应回调GotyeDelegate::onEnterRoom

退出聊天室

退出指定聊天室:

apiist->leaveRoom (room);/// <对应回调GotyeDelegate::onLeaveRoom

获取聊天室成员列表

获取聊天室成员列表(请求第0页成员表):

apiist->reqRoomMemberList (room, 0);/// <对应回调GotyeDelegate::onGetRoomMemberList

回调原型:

virtual void onGetRoomMemberList(GotyeStatusCode code, 
GotyeRoom& room, /// <请求的聊天室
unsigned pageIndex, /// <请求时传入的页索引
const std::vector<GotyeUser>& curPageMemberList, /// <当前页所对应的成员列表(全局变量)
const std::vector<GotyeUser>& allMemberList) Optional; /// <获取到的累计所有成员表(全局变量)

提示:

  1. 这里回调返回的curPageMemberList以及allMemberList与前面提到的列表一样,也是全局变量,在单次登录过程中始终有效;
  2. 返回的列表中的用户详细信息已经是服务器最新、 判断是否在指定聊天室

判断是否已经在聊天室中

bool isIn = apiist->isInRoom (room);/// <返回 true表示已经在聊天室中

判断该房间是否支持实时语音

以下接口的返回值可以直接用来判断一个聊天室是否支持实时语音:

bool support = apiist->supportRealtime(room);

群组

公共群搜索

群组在即时通讯云中分为公共群和私有群,API提供了对公共群的搜索功能,相关接口的调用方式,和用户搜索几乎一致:

apiist->resetGroupSearch ();/// <重置群组搜索,会将本地搜索结果列表和当前页搜索结果列表清空

调用以下接口可以获取到群组搜索结果列表引用,该列表属于全局变量,会将单次搜索请求的返回结果累计保存起来:

const std::vector<GotyeGroup>* pSearchList =&apiist->getLocalUserSearchList();

获取单页群组搜索结果列表:

const std::vector< GotyeGroup>* pSearchList =&apiist->getLocalGroupSearchCurPageList ();

发起单页群组搜索,和搜索用户相比,群组搜索只有一个搜索关键字,即群组名字:

apiist->reqSearchGroup (“vacation”, 0); /// <对应回调GotyeDelegate::onSearchGroupList

注意: 与用户搜索一样,群组搜索的异步回调GotyeDelegate:: onSearchGroupList中的curPageList和allList分别和getLocalGroupSearchCurPageList与getLocalUserSearchList返回值其实都是指向相同的列表对象。

获取群列表

调用以下接口可以获取到本地数据库缓存的群组列表,该列表也是全局变量,这里的群组是指登录账号所在的群组(包括自己创建的以及自己加入的):

const std::vector<GotyeGroup>* pGroupList =&apiist->getLocalGroupList ();

如果想更新该列表,可以发起如下请求:

apiist-> reqGroupList();/// <对应回调GotyeDelegate::onGetGroupList

注意:

  1. 回调中的grouplist引用和上述本地群组指向同一个列表,如果请求成功,本地列表会被及时更新
  2. 回调中的群组信息已经是包含有最新详情的,可以直接使用

获取群成员列表

获取群组成员列表(请求第0页成员表):

apiist->reqRoomMemberList (room, 0);/// <对应回调GotyeDelegate::onGetRoomMemberList

回调原型:

virtual void onGetRoomMemberList(GotyeStatusCode code, 
GotyeRoom& room, /// <请求的聊天室
unsigned pageIndex, /// <请求时传入的页索引
const std::vector<GotyeUser>& curPageMemberList, /// <当前页所对应的成员列表(全局变量)
const std::vector<GotyeUser>& allMemberList) Optional; /// <获取到的累计所有成员表(全局变量)

提示:

  1. 这里回调返回的curPageMemberList以及allMemberList与前面提到的列表一样,也是全局变量,在单次登录过程中始终有效;
  2. 返回的列表中的用户详细信息已经是服务器最新、

创建/解散群

创建群组时可以指定一系列参数:

GotyeGroup group;
group.name = “client team”; /// <设定群名字
group.info = “api development guys”; /// <设定群扩展信息
group.ownerType = GotyeGroupTypePublic; /// <设定群类型(公共群/私有群)
group.needAuthentication = false; /// <是否需要验证才能加入
apiist->createGroup (group);/// <对应回调GotyeDelegate::onCreateGroup

如果登录账号是群主,则拥有解散群的权限:

apiist->dismissGroup (group);/// <对应回调GotyeDelegate::onDismissGroup

修改群详情

与创建群组时指定的参数一样,修改群详情时这些参数都可以在后续再次更改,并且,修改群信息时还可以指定群图标(如果需要的话):

group.name = “server team”; /// <设定群名字
std::string imagePath = “/mnt/sdcard /icon.jpg”;///<设定新图标路径,目前仅支持jpg
apiist->reqModifyGroupInfo (group, & imagePath);/// <对应回调GotyeDelegate::onModifyGroupInfo

注意:

如果不需要对图标进行修改,第二个参数传nullptr(默认形参值即为nullptr)。 加入/离开群 如果想加入某个群组(群组信息可能来自群搜索,或者入群邀请),调用以下接口即可(前提是group已经有详情,否则群id必须> 0):

apiist->joinGroup (group); /// <对应回调GotyeDelegate::onJoinGroup

对应离开群接口

apiist->leaveGroup (group); /// <对应回调GotyeDelegate::onLeaveGroup

踢出群成员

如果登录账号拥有群主权限,则可以进行踢人操作(member为GotyeUser类型):

apiist->kickoutGroupMember (group,member); /// <对应回调GotyeDelegate::onKickoutGroupMember

转让群

如果登录账号拥有群主权限,还可以转让群(user为GotyeUser类型):

apiist->changeGroupOwner (group,user); /// <对应回调GotyeDelegate::onChangeGroupOwner

群状态改变

当群状态有改变,所有群成员会收到如下回调:

virtual void onUserJoinGroup(const GotyeGroup& group, const GotyeUser& user) Optional;/// <当有用户加入群时
virtual void onUserLeaveGroup(const GotyeGroup& group, const GotyeUser& user) Optional;/// <当有用户离开群时
virtual void onUserDismissGroup(const GotyeGroup& group, const GotyeUser& user) Optional; /// <当群被群主解散时;
virtual void onUserKickedFromGroup(group, const GotyeUser& kicked, const GotyeUser& actor) Optional;/// <当有用户被群主踢出群时

通知

邀请入群

API允许群成员向其他人发起入群邀请:

apiist->inviteUserToGroup (user, group, “Join us!”);

被邀请方将会收到入群通知:

//详见GotyeDelegate.h
virtual void onReceiveNotify (const GotyeNotify ¬ify) Optional;///<通知主体
notify.type  ///<GotyeNotifyTypeGroupInvite类型为邀请入群的通知
notify.sender///<邀请的发起人
notify.text///<邀请词

申请入群

向某个群的群主提出入群的申请(群可以来自群搜索):

apiist->reqJoinGroup(group, “我要入群!”);

该群群主会收到如下通知

//详见GotyeDelegate.h
virtual void onReceiveNotify (const GotyeNotify ¬ify) Optional;///<通知主体
notify.type  ///<GotyeNotifyTypeJoinGroupRequest类型为申请入群的通知
notify.sender///<申请的发起人
notify.text///<申请词

回复入群申请

群主对入群申请回复(其中notify为入群申请的通知主体):

apiist->replyJoinGroup (notify, “同意!”, true);

申请人会收到如下通知:

//详见GotyeDelegate.h
virtual void onReceiveNotify (const GotyeNotify ¬ify) Optional;///<通知主体
notify.type  ///<GotyeNotifyTypeJoinGroupReply类型为回复申请入群的通知
notify.sender///<回复的发送方
notify.text///<回复词
notify.agree  ///<是否同意

消息

创建消息

即时通讯云支持发送文本,图片,语音,自定义数据四种类型。除语音消息外,其他三种消息都有对应的工厂方法来创建,语音消息虽然也有工厂方法,但一般只由API内部自动调用。

文本消息

创建文本消息的接口参数比较简单:

GotyeMessagemessage = GotyeMessage::createTextMessage(receiver, “Hello”);

注意: API允许发送的文本消息字符串的最大长度为6KB。这里的receiver是GotyeChatTarget类型,可以填入GotyeUser/GotyeRoom/GotyeGroup的任意一种聊天对象变量,其他类型消息也是一样,后续不再赘述。

图片消息

创建图片消息:

std::string imagePath = “/mnt/sdcard /icon.jpg”; ///<设定原始图片路径,目前仅支持jpg
GotyeMessagemessage = GotyeMessage::createImageMessage(receiver,imagePath);

注意: API允许发送的原始图片的文件最大为6MB。发送图片时,API会生成一张原始图片的缩略图,该缩略图的文件大小被限制在6KB以内,随同消息一同到达接收方。而原始图片则被上传到服务器,接收端在收到消息后需要调用下载接口才能获取到原始图片。

语音消息

开始录音:

apiist-> startTalk(const GotyeChatTarget& target, GotyeWhineMode mode, bool realtime, unsigned maxDuration); 
///<realtime如果为true,则开始实时语音,聊天室所有用户会收到onRealPlayStart的回调

结束录音:

apiist-> stopTalk();

语音消息由API内部生成,当录音结束,API会在对应的异步回调中将创建好的语音消息给出:

virtual void onStopTalk(GotyeStatusCode code, ///<录音结束状态码
bool realtime, ///<是否实时模式,false表示语音短信
const GotyeMessage& message, ///<语音短信模式下API生成的语音消息,如果是实时模式,该参数无效!!!
bool *cancelSending) Optional; ///<是否取消自动发送,如果设定*cancelSending = true,则API不会自动发送消息

自定义数据消息

API支持发送用户自定义数据:

const char *userdata = “1234567890”; ///<自定义数据内容不能超过4KB
GotyeMessagemessage = GotyeMessage::createUserDataMessage (receiver,userdata, strlen(userdata));

或者发送指定路径文件里的数据内容:

std::string path = “/mnt/sdcard /userdata.txt”;///<文件内容不能超过4KB
GotyeMessagemessage = GotyeMessage::createUserDataMessage (receiver,path);

消息附加字段

API支持发送消息时附加发送一些额外的数据,其大小不允许超过2.5KB:

char *buf = “This is some extra data info with message”;
message.putExtraData(buf, strlen(buf)); ///<或者传入一个文件路径,API会自动从文件中读取内容

发送消息

消息创建好之后,调用以下接口便可发送:

apiist->sendMessage (message); /// <对应回调GotyeDelegate::onSendMessage

接收/下载消息

当有新消息到达,API会给出以下回调:

//详见GotyeDelegate.h
virtual void onReceiveMessage(const GotyeMessage& message, ///<新接收的消息
bool* downloadMediaIfNeed) Optional; ///<是否下载消息中的多媒体对象,默认为false,不自动下载

注意: 新收到的消息如果是图片或语音类型,图片和语音内容并不随消息一起到达接收方,当接收到上述回调通知,在回调函数中添加以下代码,API会在回调结束后,自动去下载消息中的多媒体对象:

* downloadMediaIfNeed = true;

如果您没有设置该值,API默认不自动下载。如果想在后续使用该消息时再下载里面的多媒体对象,可以手动调用以下接口:

apiist->downloadMediaInMessage(message); /// <对应回调GotyeDelegate::onDownloadMediaInMessage

接收离线消息

即时通讯云支持离线消息存储,当登录账号下线后,服务器会将该账号相关的离线消息保存在数据库中。以便下次登录获取。API获取离线消息的接口很简单:

apiist->beginReceiveOfflineMessage();/// <对应回调GotyeDelegate::onGetMessageList

获取消息列表

如果需要获取跟某个指定对象(好友/聊天室/群组)的聊天消息列表,可以使用以下接口:

const std::vector<GotyeMessage>*pMessageList = apiist-> getMessageList(target, true);

这里获取到的消息列表是指与聊天对象的若干条最新消息,而且返回的列表对象是全局变量,可以保存其指针使用。对好友和群组来说,调用这个接口会首先从本地数据库读取指定条目消息(默认10条),如果接收到离线消息,那么离线消息也会被插入到该列表,同时写入数据库;对聊天室来说,进入聊天室调用该接口,会向服务器请求历史消息记录,请求的条目是固定的(默认10条)。下面的两个接口可以设定从本地数据库读取消息时的条目和每次从服务器拉取历史消息时指定的条目数:

apiist->setMessageReadIncrement(20); /// <设定单次从本地数据库读取消息增量为20,默认10
apiist->setMessageRequestIncrement (15); /// <设定单次向服务器请求消息增量为15,默认10

不论是从本地数据库读取,离线消息接收,还是历史聊天记录获取,通过getMessageList获取到的本地列表都会被自动更新,因此到收到GotyeDelegate:: onGetMessageList回调,该接口总是返回最新消息列表。该接口的第二个参数more的函数是,如果设为false,则返回跟上次调用相同的消息列表,否则消息条目可能会递增。

删除消息

API提供了3个删除消息的接口:

apiist->deleteMessages (target, msglist); /// <删除消息列表, msglist是std::vector<GotyeMessage>类型
apiist->deleteMessage (target, message); /// <删除单条消息
apiist->clearMessage (target); /// <删除和某个聊天对象的所有消息

获取/更新消息状态

GotyeMessage的status字段表征了该消息的当前状态,发送中/已发送/已读/未读,详细请参考头文件GotyeMessage.h。

获取和某个聊天对象target(GotyeChatTarget)的未读消息数:

int  count = apiist->getUnreadMessageCount (target);

获取全部未读消息数:

int  count = apiist->getTotalUnreadMessageCount ();

获取聊天类型列表(GotyeUser/GotyeGroup/GotyeRoom)的全部未读消息数:

std::vector<GotyeChatTargetType>typeList;
typeList.pusk_back(GotyeChatTargetTypeGroup);
int  count = apiist->getUnreadMessageCountOfTypes (typeList); /// <获取群组下面的全部未读消息数

将和某个聊天对象的全部消息标记为已读/未读:

apiist->markMessagesAsRead (target,true ); /// <全部标记为已读状态

将单条消息标记为已读/未读:

apiist->markOneMessageAsRead (message,true ); /// <将message标记为已读状态

播放音频消息

如果消息为音频类型,则可以调用以下接口去播放(如果音频已经被下载):

apiist->playMessage (message); /// <对应回调GotyeDelegate::onPlayStart,onPlaying和onPlayStop

停止播放音频:

apiist->stopPlay();

获取录音时的音量波动值

录音时,如果需要动态显示当前说话时的音量波动,可通过以下接口实时获取:

int power = apiist->getTalkingPower(); /// <power 取值范围[0, 255]

会话

获取会话列表

API支持获取本地会话列表(最近联系人列表,该列表只存在本地,不同步到服务器),该列表也属于全局变量:

const std::vector<GotyeChatTarget>* pTargetList = apiist->getSessionList ();

获取会话详情

如果需要获取某个会话详情,可以使用以下接口:

unsigned pageIndex ;
const std::vector<GotyeMessage>*pMessageList = nullptr;
std::vector<GotyeUser> *pMemberList= nullptr, *pCurPageMemberList = nullptr;
apiist->getSessionInfo(target, & pMessageList, & pMemberList, & pCurPageMemberList, &pageIndex );

提示:这个接口会获取到与target的聊天消息列表,聊天室(群组)成员表缓存,当前页聊天室(群组)成员表缓存,最后一次请求成员表所传入的索引。最为便捷的是,每个列表缓存都属于全局变量,也就是说获取到的指针可作为全局指针保存下来使用。

激活/隐藏 会话

如果激活一个会话,则意味着当API接收到与该聊天对象相关的消息时,该条消息总是被设为已读状态,反之如果隐藏该会话,接收到的消息默认为未读状态。

apiist-> activeSession (target); /// < 激活与target的会话
apiist->deactiveSession (target); /// < 隐藏与target的会话

删除会话

如需删除一个会话,调用下述接口:

apiist-> deleteSession (target);

注意:删除会话并不意味着会删除与该聊天对象的所有本地消息存储。

会话置顶

API允许将某个会话置顶,置顶后该会话将会处于本地会话列表的第一位:

apiist-> markSessionIsTop (target, true);
返回顶部