腾迅的语音SDK的确是个好东西,正如他们所表述的,几行代码就能完成你的游戏或软件语音功能,而且音质专业,效果明显。唯一令人郁闷的是文档太过简单,而且左几句右几句,令人泪奔。
1、首先到腾迅游戏服务注册帐号,申请开通功能,就可以获得游戏ID和游戏key,腾迅提供一个免费体验专区,如果你的游戏或软件上线了,最好还是弄个正式的吧,也不贵,一人一天一分钱左右吧。
cocos 集成GVoice有两种形式,一种是在C++里面去集成,一种是将GVoice集成到Android的JAVA中,通过js反射调用JAVA。我是用Cocos Creator写的游戏,选择后者就简单多了,不用去动cocos的底层代码。
2、下载GVoice的Android版的SDK包,解压后导入工程,下载Android-support-v4包,导入工程,不装v4包的话,有可能在后面打开mic的时候会出权限不对的错误。
3、初始化SDK:在启动Activity的onCreate方法中加入
// GVoice语音初始化
GCloudVoiceEngine.getInstance().init(getApplicationContext(), this);
public class GVoiceNotify implements IGCloudVoiceNotify{
@Override
public void OnJoinRoom(int i, String s, int i1) {
Log.v("语音","OnJoinRoom 事件,加入房间成功:"+s);
Cocos2dxJavascriptJavaBridge.evalString("require(\"CommFun\").OnJoinVoiceRoom();");
}
@Override
public void OnStatusUpdate(int i, String s, int i1) {
Log.v("语音","OnStatusUpdate 事件");
}
@Override
public void OnQuitRoom(int i, String s) {
Log.v("语音","OnQuitRoom 事件,退出房间成功:"+s);
Cocos2dxJavascriptJavaBridge.evalString("require(\"CommFun\").OnQuitVoiceRoom();");
}
@Override
public void OnMemberVoice(int[] ints, int i) {
Log.v("语音","OnMemberVoice 事件");
}
@Override
public void OnUploadFile(int i, String s, String s1) {
Log.v("语音","OnUploadFile 事件");
}
@Override
public void OnDownloadFile(int i, String s, String s1) {
Log.v("语音","OnDownloadFile 事件");
}
@Override
public void OnPlayRecordedFile(int i, String s) {
Log.v("语音","OnPlayRecordedFile 事件");
}
@Override
public void OnApplyMessageKey(int i) {
Log.v("语音","OnApplyMessageKey 事件");
}
@Override
public void OnSpeechToText(int i, String s, String s1) {
Log.v("语音","OnSpeechToText 事件");
}
@Override
public void OnRecording(char[] chars, int i) {
Log.v("语音","OnRecording 事件");
}
}
Cocos2dxJavascriptJavaBridge.evalString是android java调用cocos js 中的代码的一个接口方法,具体可以参见cocos官网的说明。我用的是GVoice的实时语音功能,只有在加入语音房间成功后,才能打开mic说话,所以收到加入语音房间成功的回调消息后,通过Cocos2dxJavascriptJavaBridge.evalString调用cocos js中的代码,表示可以语音了。
5、在AppActivity类中创建用于cocos js调用语音的一些功能函数。
///
//语音
///
// 初始化语音,OpenID是你的程序中客户的唯一标识,
public static void GVoiceInit(String openID){
if(openID.isEmpty()){
Log.v("语音","openID 是空的");
Random r=new Random();
openID=String.valueOf(r.nextInt(9999));
}
gOpenID=openID;
Log.v("语音","openID:"+gOpenID);
int ret=GCloudVoiceEngine.getInstance().SetAppInfo("你申请的游戏ID", "你申请的游戏KEY", gOpenID);
if(ret!= GCloudVoiceErrno.GCLOUD_VOICE_SUCC){
Log.v("语音","SetAppInfo错误:"+ret);
}
GCloudVoiceEngine.getInstance().Init();
GCloudVoiceEngine.getInstance().SetMode(0);
gVoiceNotify = new GVoiceNotify();
GCloudVoiceEngine.getInstance().SetNotify(gVoiceNotify);
Log.v("语音","初始化语音结束");
}
// 反初始化
public static void GVoiceDeinit(){
//GCloudVoiceEngine.getInstance().Deinit();
int ret=GCloudVoiceEngine.getInstance().SetNotify(gVoiceNotify);
}
// 语音轮询poll
public static void GVoicePoll() {
//Log.v("语音","回调中。。。");
GCloudVoiceEngine.getInstance().Poll();
}
// 加入房间
public static void GVoiceJoinRoom(String strRoomName) {
Log.v("语音", "房间名称:" + strRoomName);
if (strRoomName.isEmpty()) return;
gRoomName=strRoomName;
int ret = GCloudVoiceEngine.getInstance().JoinTeamRoom(gRoomName, 10000);
if (GCloudVoiceErrno.GCLOUD_VOICE_SUCC == ret) {
Log.v("语音", "加入房间成功" + ret);
} else {
Log.v("语音", "加入房间失败");
}
}
// 退出房间
public static void GVoiceQuitRoom()
{
GCloudVoiceEngine.getInstance().QuitRoom(gRoomName,10000);
}
// 打开mic并发送语音
public static void GVoiceOpenMic() {
int ret=GCloudVoiceEngine.getInstance().OpenMic();
if(ret!=GCloudVoiceErrno.GCLOUD_VOICE_SUCC){
Log.v("语音","打开Mic错误"+ret);
}else{
Log.v("语音","打开Mic");
}
}
// 打开音箱播放声音
public static void GVoiceOpenSpeaker() {
int ret=GCloudVoiceEngine.getInstance().OpenSpeaker();
if(ret!=GCloudVoiceErrno.GCLOUD_VOICE_SUCC){
Log.v("语音","打开Speaker失败"+ret);
}
else{
Log.v("语音","打开Speaker");
}
}
// 打开mic并发送语音
public static void GVoiceCloseMic() {
int ret=GCloudVoiceEngine.getInstance().CloseMic();
if(ret!=GCloudVoiceErrno.GCLOUD_VOICE_SUCC){
Log.v("语音","关闭Mic错误"+ret);
}else{
Log.v("语音","关闭Mic");
}
}
// 关闭音箱播放声音
public static void GVoiceCloseSpeaker() {
Log.v("语音","关闭Speaker");
GCloudVoiceEngine.getInstance().CloseSpeaker();
}
6、在你的cocos js 要调用语音的场景中,加入轮询函数调用,一般是加到界面的update函数中,这样每一帧刷新时都会查看有没有语音消息。
// 帧更新时响应
update:function(){
if (cc.sys.isNative && cc.sys.os == cc.sys.OS_ANDROID) {
// 处理语音回调
jsb.reflection.callStaticMethod('org/cocos2dx/javascript/AppActivity', 'GVoicePoll', '()V');
}
},
7、根据用户信息初始化语音
if (cc.sys.isNative && cc.sys.os == cc.sys.OS_ANDROID) {
// 初始化语音
jsb.reflection.callStaticMethod('org/cocos2dx/javascript/AppActivity', 'GVoiceInit', '(Ljava/lang/String;)V', config.UserInfo.Id+config.UserInfo.WX_unionid);
// 处理语音加入房间
jsb.reflection.callStaticMethod('org/cocos2dx/javascript/AppActivity', 'GVoiceJoinRoom', '(Ljava/lang/String;)V', myState.dwTableCode.toString());
}
当cocos js 向android java 调用加入房间方法后,不能马上打开 话筒和喇叭进行语音,要等待回调返回加入房间成功后,才可以调用话筒和喇叭进行语音通讯。
// 响应android java的加入语音房间成功
OnJoinVoiceRoom:function(){
config.JoinVoiceRoom=true;
if (cc.sys.isNative && cc.sys.os == cc.sys.OS_ANDROID) {
// 开启扬声器
jsb.reflection.callStaticMethod('org/cocos2dx/javascript/AppActivity', 'GVoiceOpenSpeaker', '()V');
}
},
这时侯如果 房间有人打开mic说话,你就应该可以听到了。
代码基本上就都列出来了,流程还不清楚的可以看官网的流程图,那个图画的还是挺好的。
最后就是要注意的是android的AndroidManifest.xml中把各种权限加进去: