LAYABOX游戏实时语音之APP版本

一.前期准备
1.注册账号申请接口的APPID与密钥
www.youme.im
2下载SDK
https://www.youme.im/download.php

TIM截图20170722132357.jpg

开发工具:Android Studio 2.3.3(WIN版本)
开发环境:WIN7

TIM截图20170722132556.jpg


TIM截图20170722132822.jpg

接下来LAYABOX构建APP项目

TIM截图20170722132917.jpg


TIM截图20170722132947.jpg

然后Android Studio导入我们刚刚构建好的项目

TIM截图20170722133119.jpg


TIM截图20170722133229.jpg


接下来 把我们刚刚下载好的游密的SDK导入到  (复制粘贴都会吧)

TIM截图20170722133548.jpg
复制到项目的libs里
TIM截图20170722133651.jpg


现在项目的构建与SDK的导入都完成了,现在开始敲代码
AndroidManifest.xml
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.layabox.game"
android:versionCode="1"
android:versionName="1.0" >

<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="23" />

<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>
<uses-permission android:name="android.permission.RECORD_AUDIO"/>
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS"/>
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
<uses-permission android:name="android.permission.VIBRATE"/>
<uses-permission android:name="android.permission.FLASHLIGHT" />
<uses-permission android:name="android.permission.CAMERA"/>
<!-- 获取地理位置的权限,可选 -->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />

<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name">
<activity
android:name="demo.MainActivity"
android:screenOrientation="landscape"
android:windowSoftInputMode="stateHidden|adjustPan"
android:configChanges="keyboard|keyboardHidden|screenLayout|screenSize|orientation"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<receiver android:name="com.youme.im.NetworkStatusReceiver" android:label="NetworkConnection" >
<intent-filter>
<action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
</intent-filter>
</receiver>
</application>

</manifest>
app\build.gradle
TIM截图20170722133957.jpg

app\proguard-rules.pro 添加
-keep class demo.*
-keep com.youme.imsdk.*
-keep com.youme.imsdk.**{*;}
-keep class com.youme.IMEngine.**
-keep class com.youme.IMEngine.**{*;}
-keep class com.iflytek.**{*;}
-keepattributes Signature
新建目录
TIM截图20170722134335.jpg

“YIMChat”
建军类文件   反射
TIM截图20170722134538.jpg

打开 src\main\java\demo\MainActivity.java
添加
TIM截图20170722134800.jpg

打开app\src\main\java\YIMChat\YIMMain.java
package YIMChat;
import java.util.UUID;

import com.youme.imsdk.*;
import com.youme.imsdk.YIMService.*;
import com.youme.imsdk.internal.OnPlayCompleteNotify;


import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.os.Environment;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.util.Log;

import org.json.JSONException;
import org.json.JSONObject;

import java.util.ArrayList;


import demo.MainActivity;
import layaair.game.browser.ConchJNI;
import layaair.game.browser.ExportJavaFunction;
/**
* Created by Administrator on 2017/7/19.
*/

public class YIMMain {
private final String TAG = "MarketTest";
private final static String strAppKey = "123132123";//你申请的App Key
private final static String strSecrect = "1231312312312312312312";//你申请的App Secret
private static String mUserId = "";
private final static String mPassword = "123456";
private static String mChatRoomId = "";
private String mMsgContent = null;
private String mStoragePath = null;
private boolean mAudioDownloaded = false;
private long mRecvAudioMsgId = 0;
private String mRecvAudioPath = null;
private String mSendAudioPath = null;
private long mPTTStartTime = 0;
private YouMeIMCallback mCallback = new YouMeIMCallback();
public Handler m_Handler = new Handler(Looper.getMainLooper());
public Looper m_looper = Looper.getMainLooper();
private Context context;
private static YIMMain that = null;

public void initYouMeIMEngine(final Context activity){
Log.d("YouMinit",">>>>>>>>>>>>>>>>YIMCAHT init ok");

context = activity;

YIMService.getInstance().init(context, strAppKey, strSecrect, 0);
YIMService.getInstance().registerLoginListener(mCallback);
YIMService.getInstance().registerChatRoomListenr(mCallback);
YIMService.getInstance().registerMessageListener(mCallback);
YIMService.getInstance().registerAudioPlayListener(mCallback);
setStoragePath();


}

public void LeavePlatform() {
leaveChatRoom();
logout();
uninit();
}
private void uninit(){
YIMService.getInstance().uninit();
}

public void login( final String userId){

that = this;//反射需要指定的对像,在抛到主线程后this的对像不一样了,先把他用that存这,如果你们有更好的办法可以说下,我是临时用两天时间边学边做,不太懂JAVA(PS:压根就没有懂的开发语言,都是半调子水准)

//这块就是抛到主线程去运行SDK,否则这个SDK的监听不能正常运行
final Runnable mRunnable0 = new Runnable()
{
@Override
public void run() {

YIMService.getInstance().login(userId, mPassword,"");
}
};
new Thread()
{
public void run()
{
m_Handler.post(mRunnable0);
}
}.start();


}



private void logout(){
YIMService.getInstance().logout();
}

public void joinChatRoom(final String RoomId){
Log.d(TAG,">>>>>>>>>>>>>>>>joinChatRoom:"+RoomId);
mChatRoomId = RoomId;
final Runnable mRunnable0 = new Runnable()
{
@Override
public void run() {
YIMService.getInstance().joinChatRoom(RoomId);
}
};
new Thread()
{
public void run()
{
m_Handler.post(mRunnable0);
}
}.start();

}

public void leaveChatRoom(){
YIMService.getInstance().leaveCharRoom(mChatRoomId);
}
private void startRecordAudio(){
final Runnable mRunnable0 = new Runnable()
{
@Override
public void run() {
YIMService.getInstance().startOnlyRecordAudioMessage (mChatRoomId, YIMService.ChatType.RoomChat);
}
};
new Thread()
{
public void run()
{
m_Handler.post(mRunnable0);
}
}.start();

}

private void stopAndSendAudio(){
final Runnable mRunnable0 = new Runnable()
{
@Override
public void run() {
YIMService.getInstance().stopAndSendAudioMessage("");
YIMService.getInstance().cancleAudioMessage();
}
};
new Thread()
{
public void run()
{
m_Handler.post(mRunnable0);
}
}.start();

}

private void cancelRecordAudio(){
YIMService.getInstance().cancleAudioMessage();
}

private void downloadAudioMessage(){
final Runnable mRunnable0 = new Runnable()
{
@Override
public void run() {
YIMService.getInstance().downloadAudioMessage(mRecvAudioMsgId, getAudioPath());
}
};
new Thread()
{
public void run()
{
m_Handler.post(mRunnable0);
}
}.start();

}

private void setStoragePath(){
if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){
mStoragePath = Environment.getExternalStorageDirectory().getAbsolutePath().toString();
}
}

private String getAudioPath(){
String audioPath = mStoragePath + "/";
audioPath += UUID.randomUUID().toString() + ".wav";
return audioPath;
}
public boolean onTouch(final String type){
switch(type){
case "d":
mPTTStartTime = System.currentTimeMillis();
startRecordAudio();
return true;
case "u":
mAudioDownloaded = false;
long endTime = System.currentTimeMillis();
if (endTime - mPTTStartTime < 1000){
ExportJavaFunction.CallBackToJS (this, "onTouch", "录音时间过短");
}else{
ExportJavaFunction.CallBackToJS (this, "onTouch", "正在发送语音");
stopAndSendAudio();
}
return true;
default:
break;
}
return false;
}
private class YouMeIMCallback implements YIMService.LoginListener, YIMService.ChatRoomListener,YIMService.MessageListener,YIMService.AudioPlayListener {

/**
* 登录回调
* @param userId 用户Id
* @param errcode 错误码
*/
@Override
public void onLogin(final String userId, Integer errcode){
Log.e("YOUMEJ", "用户: " + userId + " 登录成功");
if (errcode == YIMService.Errorcode.Success){
ExportJavaFunction.CallBackToJS (that, "login", "用户: " + userId + " 登录成功");
}else{
ExportJavaFunction.CallBackToJS (that, "login", "用户: " + userId + " 登录失败:"+errcode);
}
}

/**
* 登出回调
*/
@Override
public void onLogout(){
ExportJavaFunction.CallBackToJS (this, "logout", "用户: " + mUserId + " 已经退出登录");
}

/**
* 发送消息状态
* @param requestId 消息Id
* @param errcode 错误码
*/
@Override
public void onSendMessageStatus(Long requestId, Integer errcode, Boolean isForbidRoom, Integer reasonType, Long forbidEndTime){
if (errcode == YIMService.Errorcode.Success){
//showSend("成功发送消息(非语音消息): " + mMsgContent);
}

}

/**
* 接收到用户发来的消息
* @param message 消息内容结构体
*/
@Override
public void onRecvMessage(YIMMessage message){
Log.e("YOUMEIMonRecvMessage", "onRecvMessage:"+message);
if (null == message)
return;
int msgType = message.getMessageType();
if (YIMService.MessageBodyType.TXT == msgType){
// ExportJavaFunction.CallBackToJS (this, "logout", "接收到一条文本消息: " + ((YIMMessageBodyText)message.getMessageBody()).getMessageContent());
}else if (YIMService.MessageBodyType.Voice == msgType){
Log.e("YOUMEIMonRecvMessage", "接收到一条语音消息请下载:"+message);
YIMMessageBodyAudio audioMessage = (YIMMessageBodyAudio)message.getMessageBody();

int audioDuration = audioMessage.getAudioTime();//录音时长,秒
String param = audioMessage.getParam();//自定义内容
String recognizeText = audioMessage.getText();//语音转文字的识别结果
Log.e("YOUMEIMonRecvMessage", "that:"+message.getSenderID());
Log.e("YOUMEIMonRecvMessage", "that:"+that);
JSONObject objCallBack = new JSONObject();
try {
objCallBack.put("userId", message.getSenderID());
objCallBack.put("AudioTime", audioDuration);
} catch (JSONException e) {
e.printStackTrace();
}
//这句就是执行LAYABOX里的我们写的JS方法(ExportJavaFunction.CallBackToJS这玩意在这好像没法用了,没有对像给他指定了,暂时没想到其他办法)
ConchJNI.RunJS("onRecvMessage('"+objCallBack+"')");

mAudioDownloaded = false;
mRecvAudioMsgId = message.getMessageID();//下载用的消息id
downloadAudioMessage();//这个是异步的,不是调用了就下载完成了
mAudioDownloaded = true;

if (mAudioDownloaded){

}
}
}

/**
* 发送语音消息
* @param requestID 消息Id
* @param errorcode 错误码
* @param strText 文本信息
* @param strAudioPath 语音文件存放路径
* @audioTime 语音时长
*/
@Override
public void onSendAudioMessageStatus(Long requestID, Integer errorcode, String strText, String strAudioPath, Integer audioTime,
Boolean isForbidRoom, Integer reasonType, Long forbidEndTime){
if (errorcode == Errorcode.Success){
Log.e("YOUMEIMonRecvMessage", "成功发送语音:"+mRecvAudioMsgId);
// ExportJavaFunction.CallBackToJS (this, "onTouch", "成功发送语音");
mSendAudioPath = strAudioPath;
}
}

@Override
public void onDownload(Integer errorcode, YIMMessage message , String savePath){
//这个下载完成的通知就可以用来做播放
if (errorcode == Errorcode.Success){
mAudioDownloaded = true;
mRecvAudioPath = savePath;

if (!AudioPlayer.GetInstance().IsPlaying()) {
// AudioPlayer.GetInstance().Play(mRecvAudioPath);

YIMService.getInstance().StartPlayAudio(mRecvAudioPath);

}else {
// AudioPlayer.GetInstance().Pause();
YIMService.getInstance().StopPlayAudio();
}
}
}

@Override
public void onDownloadByUrl(Integer errorcode, String fromUrl, String savePath)
{

}

/**
* 加入群组
* @param errorcode 错误码
* @param roomID 频道id
*/
@Override
public void onJoinChatRoom(Integer errorcode, String roomID) {
// TODO Auto-generated method stub

}

@Override
public void onLeaveChatRoom(Integer errorcode, String roomId) {
// TODO Auto-generated method stub

}

@Override
public void onUserJoinChatRoom(String roomID, String userID)
{

}

@Override
public void onUserLeaveChatRoom(String roomID, String userID)
{

}


public void OnQueryHistoryMessage(Integer errorcode, YIMHistoryMessage message) {
// TODO Auto-generated method stub

}


public void OnRecvNewMessage( Integer chatType, String targetID) {
// TODO Auto-generated method stub

}


public void OnStopAudioSpeechStatus(Integer errorcode, Long iRequestID, String strDownloadURL, Integer iDuration, Integer iFileSize,
String strLocalPath, String strText) {
// TODO Auto-generated method stub

}


public void OnTranslateTextComplete(Integer errorcode, Long requestID, String text, Integer srcLangCode, Integer destLangCode) {
// TODO Auto-generated method stub

}


public void onStartSendAudioMessage(Long requestID, Integer errorcode, String strText, String strAudioPath, Integer audioTime) {
// TODO Auto-generated method stub

}

/**
* 语音播放结束的通知
* @param errorcode 错误码,详细描述见错误码定义
* @param notifyData 播放结束通知类
*/
@Override
public void onPlayCompletion(Integer errorcode, OnPlayCompleteNotify notifyData) {
// TODO Auto-generated method stub
Log.e("YOUMEIM", "onPlayCompletion:"+notifyData.audioPath);
}

/**
* 获取麦克风状态回调
* @param status 状态
*/
@Override
public void onGetMicrophoneStatus(Integer status){

}

/**
* 举报处理结果回调
* @param result 处理结果
* @param userID 被举报用户
* @param accusationTime 举报时间
*/

public void onAccusationResultNotify(Integer result, String userID, Integer accusationTime)
{

}


public void OnGetForbiddenSpeakInfo(Integer errorcode, ArrayList<YIMForbiddenSpeakInfo> forbiddenInfoList )
{
//封禁原因、时间查询结果
}



}
}
下面就是LAYABOX的操作源码,很简单,可以看一下官方的二次开发教程
var YIMChat = Laya.PlatformClass.createClass("YIMChat.YIMMain");
var YIMMain = YIMChat.newObject();
var randomString = function (len: number) { //随机码 
len = len || 32;
var $chars = 'ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz2345678oOLl9gqVvUuI1';
var maxPos = $chars.length;
var str = '';
for (var i = 0; i < len; i++) {
str += $chars.charAt(Math.floor(Math.random() * maxPos));
}
return str;;
}
class LoginView extends ui.LoginUI {
constructor() {
super();
this.login.on(Laya.Event.CLICK, this, this.Loginyim);
this.joinroom.on(Laya.Event.CLICK, this, this.JoinRoom);
this.RecordAudio.on(Laya.Event.MOUSE_DOWN, this, this.StartRecordAudio);
this.RecordAudio.on(Laya.Event.MOUSE_UP, this, this.StopRecordAudio)

}

Loginyim() {


YIMMain.callWithBack(function (n) { alert(n); }, "login",randomString(6));

}
JoinRoom() {
YIMMain.callWithBack(function (n) { alert(n); }, "joinChatRoom","235369");

}
StartRecordAudio() {
YIMMain.callWithBack(function (n) { alert(n); }, "onTouch","d");

}
StopRecordAudio() {
YIMMain.callWithBack(function (n) { alert(n); }, "onTouch","u");

}


}
//监听谁发的语音消息
var onRecvMessage = function (callback){
alert(callback);

}
好了教程结束,不懂的 可以在下面提出来(我也不一定能回答上来,我都是翻着百度做的)
PS:请在手机上调试(个别模拟器不支持麦克风)


下一阶段就是   LAYABOX微信登陆之APP版本  这块可以用官方的区道接口进行二次开发









 
已邀请:

fishg

赞同来自:

很实用的参考,谢谢作者

Monica - 知识达人

赞同来自:

感谢分享~很赞

helingen

赞同来自:

支持一下

KevinWoo

赞同来自:

网页版能用吗??

158*****805

赞同来自:

膜拜一下

凌迟

赞同来自:

感谢一下,留个标记

要回复问题请先

商务合作
商务合作