本流程以Android Studio 2.2+Unity5.6來說明
1.安裝Android Studio 2.2(64Bit)
2.安裝Unity 5.6
3.在訊飛平台上創建一個項目,我這裡使用的是喚醒詞體驗包,有三個裝機量,35天,以及三個喚醒詞的限制,然後下載喚醒詞體驗包SDK(如图)
4.在Android studio中創建一個工程,流程如下面圖片
a.創建一個新工程,Application name我這裡設置成IFlyWakeupSDK,Company Domain:按照xxx.com的格式設置,然後Next
b.Next後如圖:默认已经勾选Phone and Tablet 后面的不需要选择 ,Minimum SDK我这里选择:API16:Android 4.1(Jelly Bean),然後Next
c.點Next後如圖:这里选择Empty Activity然後Next
d.點Next後如圖:然后点Finish
點完Finish後,我們可以看到完整的工程結構如圖:到这里项目基本创建完毕,下面讲如何设置工程
5.工程设置
a.在工程名山右鍵,New => Module,选择一个Empty Activity,最后命名为:IFlySDKLibrary 如图:
最后的工程结构如图:
b.選擇File => Project Structure ,然後選擇app,然后点检 - 按钮 刪除app Module,接着回到工程目錄下 右鍵選擇app => Delete
如圖:
c.回到工程目錄下,选择创建的library下的AndroidManifest.xml,删除多余的内容,然后添加上相应的权限,最后的内容如图:
d.打開下載的訊飛語音喚醒SDK目錄,在libs下有Msc.jar和Sunflower
.jar兩個文件,選擇他们然後複製,粘贴到工程中的libs目录下,然後把Unity5.6的jar也複製到這個目錄下,在Unity 5.6中在發布設置中我選擇的是Mono2x 所以我们找到Mono2x对应的目录(Editor\Data\PlaybackEngines\AndroidPlayer\Variations\mono\Release\Classes\classes.jar)复制classes.jar,粘贴到工程中的libs目录下,最后工程截图如下:
e:回到工程 File => Project Structure ,选择mudules下的iflysdklibrary ,在選項卡的最後面有一個叫Dependencies,先删除如图中红色框中内容
然後把之前複製進來的3個jar包添加進來,如图:
然后选择Properties选项,设置Compile sdk version以及Build tools sdk Version版本,我这里都选择26(注意:因为unity中的编译sdk版本为26,所以选择26,不然在unity中编译不通过),然后选择Flavors选项,设置Min sdk Version为16 Target Sdk version为26,如图:
然后打开build.gradle,删除如图红框中的那行:
f:开始编写代码,不贅述直接上代碼:
package com.kingsoft.iflysdklibrary;
import android.content.Context;
import android.os.Bundle;
import android.os.Environment;
import android.util.Log;
import android.app.Fragment;
import com.iflytek.cloud.ErrorCode;
import com.iflytek.cloud.InitListener;
import com.iflytek.cloud.SpeechUtility;
import com.unity3d.player.UnityPlayer;
import org.json.JSONException;
import org.json.JSONObject;
import com.iflytek.cloud.SpeechConstant;
import com.iflytek.cloud.SpeechError;
import com.iflytek.cloud.SpeechEvent;
import com.iflytek.cloud.VoiceWakeuper;
import com.iflytek.cloud.WakeuperListener;
import com.iflytek.cloud.WakeuperResult;
import com.iflytek.cloud.util.ResourceUtil;
import com.iflytek.cloud.util.ResourceUtil.RESOURCE_TYPE;
public class MainActivity extends Fragment
{
private final String TAG = "Unity";
private final String CALLBACK_GAMEOBJECT= "IFlyManager";
// 语音唤醒对象
private VoiceWakeuper mIvw;
private final static int MAX = 60;
private final static int MIN = -20;
private int curThresh = 10;
private String ivwNetMode = "0";
private Context context;
// 唤醒结果内容
private String resultString;
private String keep_alive = "1";
private String gameObjectName;
private static MainActivity Instance = null;
public static MainActivity GetInstance(String gameObject)
{
if (Instance == null)
{
Instance = new MainActivity();
Instance.gameObjectName = gameObject;
UnityPlayer.currentActivity.getFragmentManager().beginTransaction().add(Instance, "MyPlugin").commit();
}
return Instance;
}
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setRetainInstance(true);
context = getActivity().getApplicationContext();
SpeechUtility.createUtility(context,SpeechConstant.APPID+"=xxxxxxx");
Log.d(TAG,"onCreate exec!!!");
}
public void StartWakeUpSpeechListener()
{
mIvw = VoiceWakeuper.createWakeuper(context,initListener);
if(mIvw == null)
{
Log.d(TAG,"VoiceWakeuper.createWakeuper faild!!!");
return;
}
resultString = "";
// 清空参数
mIvw.setParameter(SpeechConstant.PARAMS, null);
// 唤醒门限值,根据资源携带的唤醒词个数按照“id:门限;id:门限”的格式传入
mIvw.setParameter(SpeechConstant.IVW_THRESHOLD, "0:"+ curThresh);
// 设置唤醒模式
mIvw.setParameter(SpeechConstant.IVW_SST, "wakeup");
// 设置持续进行唤醒
mIvw.setParameter(SpeechConstant.KEEP_ALIVE, keep_alive);
// 设置闭环优化网络模式
mIvw.setParameter(SpeechConstant.IVW_NET_MODE, ivwNetMode);
// 设置唤醒资源路径
mIvw.setParameter(SpeechConstant.IVW_RES_PATH, getResource());
// 设置唤醒录音保存路径,保存最近一分钟的音频
mIvw.setParameter( SpeechConstant.IVW_AUDIO_PATH, Environment.getExternalStorageDirectory().getPath()+"/msc/ivw.wav");
mIvw.setParameter( SpeechConstant.AUDIO_FORMAT, "wav" );
// 如有需要,设置 NOTIFY_RECORD_DATA 以实时通过 onEvent 返回录音音频流字节
//mIvw.setParameter( SpeechConstant.NOTIFY_RECORD_DATA, "1" );
// 启动唤醒
int status = mIvw.startListening(mWakeuperListener);
if(status != ErrorCode.SUCCESS)
{
Log.d(TAG,"status:"+status);
}else
{
Log.d(TAG,"start wakeup Listening");
}
}
public void StopWakeUpSpeechListener()
{
if(mIvw != null)
{
mIvw.stopListening();
}
Log.d(TAG,"StopWakeUpSpeechListener");
}
private InitListener initListener = new InitListener()
{
@Override
public void onInit(int code)
{
Log.d(TAG,"onInit code:"+code);
}
};
private WakeuperListener mWakeuperListener = new WakeuperListener() {
@Override
public void onResult(WakeuperResult result)
{
Log.d(TAG, "onResult");
if(!"1".equalsIgnoreCase(keep_alive))
{
}
try
{
String text = result.getResultString();
JSONObject object;
object = new JSONObject(text);
StringBuffer buffer = new StringBuffer();
buffer.append("【RAW】 "+text);
buffer.append("\n");
buffer.append("【操作类型】"+ object.optString("sst"));
buffer.append("\n");
buffer.append("【唤醒词id】"+ object.optString("id"));
buffer.append("\n");
buffer.append("【得分】" + object.optString("score"));
buffer.append("\n");
buffer.append("【前端点】" + object.optString("bos"));
buffer.append("\n");
buffer.append("【尾端点】" + object.optString("eos"));
resultString = buffer.toString();
Log.d(TAG,"resultString:"+resultString);
//SendMsgToUnity("onVolumeChanged", ""+object.optString("score"));
SendMsgToUnity("onResult",""+object.optString("id"));
}
catch (JSONException e)
{
resultString = "结果解析出错";
Log.d(TAG,resultString);
e.printStackTrace();
}
}
@Override
public void onError(SpeechError error)
{
String errorCode = error.getErrorCode()+"";
Log.d( TAG, "errorCode:"+errorCode);
SendMsgToUnity("onError",errorCode);
}
@Override
public void onBeginOfSpeech()
{
Log.d( TAG, "onBeginOfSpeech");
SendMsgToUnity("onBeginOfSpeech","onBeginOfSpeech");
}
@Override
public void onEvent(int eventType, int isLast, int arg2, Bundle obj)
{
switch( eventType ){
// EVENT_RECORD_DATA 事件仅在 NOTIFY_RECORD_DATA 参数值为 真 时返回
case SpeechEvent.EVENT_RECORD_DATA:
final byte[] audio = obj.getByteArray( SpeechEvent.KEY_EVENT_RECORD_DATA );
Log.d( TAG, "ivw audio length: "+audio.length );
break;
}
}
@Override
public void onVolumeChanged(int volume)
{
Log.d( TAG, "onVolumeChanged:"+volume);
SendMsgToUnity("onVolumeChanged", volume+"");
}
};
private String getResource()
{
String resPath = ResourceUtil.generateResourcePath(context, RESOURCE_TYPE.assets, "ivw/595b8757.jet");
Log.d( TAG, "resPath:"+resPath);
return resPath;
}
private void SendMsgToUnity(String methodName,String msg)
{
UnityPlayer.UnitySendMessage(CALLBACK_GAMEOBJECT, methodName, msg);
}
public void Exit()
{
android.os.Process.killProcess(android.os.Process.myPid());
System.exit(0);
}
}
g.接着Build => Build APK 会在iflysdklibrary目录下build=>outputs=>aar目录中生成一个.aar文件,如图:
然后进入到aar目录下 把生成的.aar文件修改扩展名问zip,用解压软件打开,删除libs目录下的classes.jar(不删除在unity中会编译不通过),然后打开下载的讯飞唤醒体验包,把其中的依赖的so文件复制进zip目录下的libs中,最后的结构如图:
然后把zip包重新命名为.aar,到这里为止android studio中的工作就完成了,接着把讯飞唤醒sdk下的语音包复制到unity的Plugins/Android/Assets目录下,下面开始在Unity中的工作
h.unity中的设置如图,unity中的代码直接上图,不多赘述:
如果有不清楚的或者想交流的朋友,请联系QQ:2718390374