修订历史
日期 | 版本 | 说明 |
---|---|---|
2020-12-10 | 5.0.3 | 新增JS接入方式 |
CLIm语音IM聊天在cocos2d-x引擎集成方法,及提供C++及JS集成接口参考。
术语 | 定义 |
---|---|
appId | 应用编号(需申请获取) |
PC版: win32/win64
Android: Android4.0以上
iOS:iOS5.0以上
cocos2d-x引擎版本: 2.x及3.x
cocos2d-x引擎语言: CPP
提供APP或游戏名称、包名和公司名称等信息。在sdk对接交流群@相关对接人既可。
第一步:将代码拷贝至您的工程,也就是Classes目录。如图所示,
第二步,将SDK目录下的所有的的*.lib及*.dll文件拷贝到你的project.win32下的Debug.win32和 Release.win32。
第三步:右键工程->属性->链接器->输入。在左上角切换配置为所有配置。并在附加依赖项里添加刚才拷贝过来的lib文件名。配置完后,确认即可。
第三步便捷的做法还可以,直接在您的代码里加入
#ifdef WIN32
#pragma comment(lib,“CLImpacket.lib”) #pragma comment(lib,“LoginSDK.lib”)
#endif
第一步:下面的要求修改proj.android目录下的jni目录里的Android.mk文件
b、将下面代码添加到LOCAL_MODULE := cocos2dcpp_shared的下一行
LOCAL_SHARED_LIBRARIES += libCLImSdk
c、在LOCAL_C_INCLUDES := $(LOCAL_PATH)/…/…/…/Classes \的下一行
如下图所示:
d、在文件的最后一行加入
$(call import-module,IM_SDK)
如下所示:
第二步:在java代码里,在AppActivity (继承Cocos2dxActivity的那个类)里加入如下代码:
static
{
System.loadLibrary(“CLImSdk”);
}
第四步:添加SDK依赖jar包
1、将SDK目录下的jar包拷贝至proj.android目录下的libs里(如果没有这个目录,请新建一个)。
包名与发包的名称为准
第五步:修改AndroidManifest.xml文件
1、加入如下权限(注:文件中manifest标签之后以内,application以外,和application同一层)
uses-permission android:name=“android.permission.RECORD_AUDIO”/
注意上面申请录音权限的方式在Android6.0系统一下都可以成功,但在Android6.0系统以上,可能会弹出要使用录音权限的提示,但是并没有真正获得录音权限,所以Android6.0以上申请录音权限必须要在代码中动态申请,不然有的厂商机型获取不到录音权限,导致录音失败。
2、在此设置的appid与代码 init里的appid要一致。
在 Application的oncreate()中在初始化添加com.chuanglan.im.sdk.lib.ImLoginInit.initApplicationOnCreate(this.getApplication(), “300000”);
300000 填写你们自已的appid。
4、在 Application 的onDestroy函数中添加com.chuanglan.im.sdk.lib.ImLoginInit.release();
第六步:打release包可能会出现jar方法找不到。请在proguard-rules.pro文件中加入混淆代码,混淆码在压缩包混淆文件中。
注意iOS下还需要设置-force_load libCLImToolsManager.a 如图:
注意该地方不设置,运行时会奔溃
C++用户参考如下代码:
//通过此接口实例化,您就可以凭借些实例调用SDK的方法
ImTool* pImTool = ImTool::getInstance();
//例如,调用初使化SDK的api
pImTool->initSDK(300000, “writablePath”);
JS用户参考如下代码:
this.voiceIm = imcc. IMDispatchMsgNode.getInstance ()
//例如,调用初使化SDK的api
this.voiceIm.initSDK(300000, 0) //0表示使用国内环境,1表示使用海外环境,第二个参数不填,默认使用国内环境。
在本文档会提供SDK目前所有可调用API接口说明。
JS层需要注册个事件回调函数,接收所有SDK返回的回调事件。
this. voiceIm.onMessage = function (data) {xxxxxxxxx}
this.voiceIm. setListener (this.voiceIm.onMessage, this),具体使用代码,可参照demo中实现自己的调用方式。
l 函数参数data数据为json格式。
由于采用了异步派发事件,事件的回调线程和UI线程不在同一个线程。所以需要UI线程定时从回调线程获取数据。本SDK已经为用户完成此步骤,但需要用户自己编写定时器定时调用 ImTool::getInstance()->dispatchMsg(dt); 下面以cocos2d-x 3.x为例,
1、实现一个定时派发的CCNode
//=============CLImSDK事件Dispatch类====================
2、class DispatchMsgNode : public cocos2d::Node
3、{
4、public:
5、 bool init()
6、 {
7、 isschedule = false;
8、 return Node::init();
9、 }
10、 CREATE_FUNC(DispatchMsgNode);
11、 void startDispatch()
12、 {
13、 if (isschedule) return;
14、 isschedule = true;
15、 Director::getInstance()->getScheduler()->scheduleUpdate(this, 0, false);
16、 }
17、 void stopDispatch()
18、 {
19、 if (!isschedule) return;
20、 isschedule = false;
21、 Director::getInstance()->getScheduler()->unscheduleUpdate(this);
22、 }
23、 void update(float dt)
24、 {
25、 CLImTool::getInstance()->dispatchMsg(dt);
26、 }
27、private:
28、 bool isschedule;
29、};
30、在AppDelegate类中申明一个 DispatchMsgNode* m_dispathMsgNode; 并分别修改AppDelegate的构造及析构函数
31、AppDelegate::AppDelegate()
32、{
33、 m_dispathMsgNode = NULL;
34、}
35、AppDelegate::~AppDelegate()
36、{
37、 if (m_dispathMsgNode != NULL)
38、 {
39、 m_dispathMsgNode->stopDispatch();
40、 m_dispathMsgNode->release();
41、 m_dispathMsgNode = NULL;
42、 }
43、}
以及sc->addRegisterCallback(register_all_IMDispatchMsgNode); 此代码功能为将二次封装好的接口,注入到JS层中。这部分代码,可以直接使用Classes文档中AppDelegate.h与AppDelegate.cpp中代码。
使用pthread做现场锁,屏蔽CImSyncQueue.h代码中加入#define _IS_USE_PTHREAD_在VS工程include配置属性里添加(其它平台似乎默认已经加入了)$(ProjectDir)…\cocos2dx\platform\third_party\win32\pthread
this.voiceIm:initSDK(100041, false)
协议字段 | 类型 | 是否必填 | 说明 |
---|---|---|---|
appId | unsigned long | 是 | 应用编号(需向CLIm申请获取) |
isOversea | bool | 否 | False:国内版, true:海外版 |
this.voiceIm.cpLogin(“xxxxxxxxxxx”, “xxxxxxxxxxxxx”)
协议字段 | 类型 | 是否必填 | 说明 |
---|---|---|---|
nickname | std::string | 是 | 用户名称(由CP自己提供) |
uid | std::string | 是 | 用户ID,(由CP自己提供,请确保唯一性) |
该接口为必须调用接口,但是可以不用关心该接口的返回,该接口返回失败也不会影响
功能的正常使用。Nickname字段可以用uid代替,这样可以避免sdk对一些特殊字符兼容问题
JS层接收到JSON数据:{“name”:“CLImSDK_LOGIN_COMPLETED”,“result”:0},
name表示当前回调事件名称,reslut表示结果,0为成功。
接入用户如有需要可以自定义更改 IMDispatchMsgNode::onLoginListern函数中,返回的json内容,比如增加msg、userid、nickname等字段内容。
this.voiceIm.setRecord(timenum, volumeNotify)
协议字段 | 类型 | 是否必填 | 说明 |
---|---|---|---|
timenum | unsigned int | 是 | 尽量不超过60秒 |
volumeNotify | unsigned int | 否 | 0表示不开启音量变动回调,1表示开启 |
JS层接收到JSON数据:{“name”:“CLImSDK_SDK_RECONNECT”,“userid”:xxxxx}。json具体定义可参考IMDispatchMsgNode::onReConnectListern中内容。
this.voiceIm.startRecord(speech, ext)
协议字段 | 类型 | 是否必填 | 说明 |
---|---|---|---|
speech | uint8 | 否 | 注:参数speech = 0-2路径必须是带amr后缀的音频文件路径而非目录路径 注:参数speech = 10-12路径必须是带mp3后缀的音频文件路径而非目录路径。 如果不想设置录音路径,该字段就传“”空字符串,sdk会自动生成,录音结束回调会回调录音文件路径。 |
ext | std::string | 否 |
注意该接口:
speech=0为普通录音,当调用停止录音接口时,会收到停止录音回调,返回amr格式录音文件。
speech=1为边录边上传加识别,当调用停止录音接口时,会收到停止录音回调和上传录音返回回调以及语音识别的回调。(如果没有用到语音识别功能不建议传此参数,影响效率)。停止录音回调接口返回amr 录音文件,上传录音回调接口返回amr文件url,识别回调接口返回录音转文字结果。
speech=2为边录边上传,当调用停止录音接口时,会收到停止录音回调和上传录音返回回调。停止录音回调接口返回amr 录音文件,上传录音回调接口返回amr文件url。
speech=10为普通录音,当调用停止录音接口时,会收到停止录音回调,返回mp3格式录音文件。
speech=11为边录边上传加识别,当调用停止录音接口时,会收到停止录音回调和上传录音返回回调以及语音识别的回调。(如果没有用到语音识别功能不建议传此参数,影响效率)。停止录音回调接口返回mp3录音文件,上传录音回调接口返回mp3文件url,识别回调接口返回录音转文字结果。
speech=12为边录边上传,当调用停止录音接口时,会收到停止录音回调和上传录音返回回调。停止录音回调接口返回mp3录音文件,上传录音回调接口返回mp3文件url。
警示:如果是2019年3月之前的老用户,请不要使用【10,11,12】三个参数,因为该参数返回的是mp3格式,不能与之前的接入的老版本互通兼容。
ext:用户特殊标记的,录音完后,可以通过回调带回,用以区分录音情况。用户可以不管。
JS层收到上传回调的json数据为:{“name”:“CLImSDK_UPLOAD_COMPLETED”,“result”:0,“url”:“xxxxxxx”},如需修改json内容可参考IMDispatchMsgNode:: onUpLoadFileListern。
JS层收到识别回调的json数据:result为0时为,{“name”:“CLImSDK_SPEECH_FINISH”,“result”:0,“url”:“xxxxxxxx”,“speech_msg”:“xxxxxxxxxxx”, “ext”:“xxxx”}。
result不为0时,json为{“name”:“CLImSDK_SPEECH_FINISH”,“result”:1,“url”:“xxxxxxxx”,“err_msg”:“xxxxxxxx”, “ext”:“xxxx”}。
ext与录音时候设置的ext值一样,不传则为"",如需修改json内容可参考IMDispatchMsgNode::onFinishSpeechListern。
JS层接收到的数据为:
{“name”:“CLImSDK_STOP_RECORD”,“result”:0 ,“time”:12,“path”:“xxxxxxxx”,“ext”:“xxxxx”}。
播放录音有2种,一种为播放本地录音,一种为播放url录音,url录音需要先下载后再进行播放,相应会多一条回调通知(下载回调通知)。
this.voiceIm.playLocalRecord(localpath, ext)
协议字段 | 类型 | 是否必填 | 说明 |
---|---|---|---|
localpath | String | 是 | 系统本地文件路径 |
ext | string | 否 | 特殊标记,如不为空。播放回调后会将次标记符带回 |
self.voiceIm:playUrlRecord (url)
注意:此接口有二个事件,分别是ImDownloadVoiceListern和ImFinishPlayListern。
其中ImDownloadVoiceListern是用于做UI上语音文件下载展示用的,比如下载菊花。
协议字段 | 类型 | 是否必填 | 说明 |
---|---|---|---|
url | string | 是 | 存放语音文件的(http)URL地址 |
ext | string | 否 | 特殊标记,如不为空。播放回调后会将次标记符带回 |
JS层接收到的数据为:{“name”:“CLImSDK_PLAY_COMPLETED”,“result”:0,“ext”:“xxxx”}。如需要更详细json数据,可以参考修改IMDispatchMsgNode::onFinishPlayListern中json拼接内容。
JS层接收到的数据为:{“name”:“CLImSDK_VOICE_DOWNLOAD”,“percent”:xx,“ext”:“xxxx”}, percent表示当前下载进度百分百。
this.voiceIm::setSpeechType(inType, outType)
协议字段 | 类型 | 是否必填 | 说明 |
---|---|---|---|
inType | unsigned int | 是 | 识别语音类型(默认普通话) |
outType | unsigned int | 是 | 输出语音的文本类型 |
inType的选择范围为1-3,1表示中文、2表示粤语、3表示英语。
outType的选择范围为0-1,0表示简体中文,1表示繁体中文。
JS层接收到的数据为:result为0时为,{“name”:“CLImSDK_SPEECH_FINISH”,“result”:0,“url”:“xxxxxxxx”,“speech_msg”:“xxxxxxxxxxx”,“ext”:“xxxx”},
result不为0时,json为{“name”:“CLImSDK_SPEECH_FINISH”,“result”:1,“url”:“xxxxxxxx”,“err_msg”:“xxxxxxxx”,“ext”:“xxxx”}
this.voiceIm.upLoadFile(path, ext)
协议字段 | 类型 | 是否必填 | 说明 |
---|---|---|---|
path | string | 是 | 带绝对路径的文件名(例:xx/test.amr) |
ext | string | 否 | 特殊标识符 |
JS层收到上传回调的json数据为:{“name”:“CLImSDK_UPLOAD_COMPLETED”,“result”:0,“url”:“xx”,“ext”:“xxxx”},如需修改json内容可参考IMDispatchMsgNode:: onUpLoadFileListern。
this.voiceIm.downLoadFile(url, saveName,ext)
协议字段 | 类型 | 是否必填 | 说明 |
---|---|---|---|
url | string | 是 | 所下载的文件所在的URL地址 |
saveName | string | 是 | 要保存的文件名称,不需要带后缀 |
ext | string | 否 | 特殊标记符 |
JS层接收到的数据为{“name”:“CLImSDK_DOWNLOAD”,“result”:0,“localpath”:“xx”,“percent”:“xx”, “ext”:“xx”}
解决方法:返回至本文档的Android环境配置栏目下,严格按照此说明来配置您的工程。
解决方案:解决方案:没有在android工程下加入完整权限,请参考本文档的Android环境配置栏目配置此权限。
解决方案:检查录音调用传的参数,第一个参数(savePath)需要是带绝对路径的文件名(例:xx/test.amr)
注:路径必须是带amr后缀的音频文件路径而非目录路径
解决方案:1.确认网络是否是好的;2.切换登录环境试试(测试/正式)
解决方案:添加ImageIO.framework还有CoreMedia.framework
//请在定时器运行下面这个方法 具体代码可以看AppDelegate.cpp里面的代码
void dispatchMsg(float t);
初始化、登录接口只需要调用一次就好。在使用功能前必须先调用初始化和登录否则调用失败。
之前老版更新、Android下老版的接入的时间有在AndroidManifest.xml加入了一些Service。这些Service现在都不需要了,需要将它全部删除,不然可能因为找不到Service导致一些异常现象。