参考自:
https://blog.csdn.net/yang8456211/article/details/51356193
https://blog.csdn.net/li5852258/article/details/78978252
https://github.com/Super0410/Unity_XunFeiSDK
unity sdk两种接入方式:
1.继承自UnityPlayerActivity 这时AndroidMainifest需要创建一个Main Activity覆盖Unity自带的Androidmainfest中的Main Activity。否则使用unity自动合并AndroidMainifest会产生两个
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
因为有两个android.intent.category.LAUNCHER安装之后会产生两个图标
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.test.df">
<application
android:allowBackup="true"
android:label="@string/app_name"
android:supportsRtl="true">
<activity android:label="@string/app_name" android:name=".MainActivity" android:screenOrientation="sensorLandscape" android:launchMode="singleTask" android:configChanges="mcc|mnc|locale|touchscreen|keyboard|keyboardHidden|navigation|orientation|screenLayout|uiMode|screenSize|smallestScreenSize|fontScale|layoutDirection">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
<category android:name="android.intent.category.LEANBACK_LAUNCHER" />
</intent-filter>
<meta-data android:name="unityplayer.UnityActivity" android:value="true" />
</activity>
</application>
<!--连接网络权限,用于执行云端语音能力 -->
<uses-permission android:name="android.permission.INTERNET"/>
<!--获取手机录音机使用权限,听写、识别、语义理解需要用到此权限 -->
<uses-permission android:name="android.permission.RECORD_AUDIO"/>
<!--读取网络信息状态 -->
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<!--获取当前wifi状态 -->
<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"/>
<!--外存储写权限,构建语法需要用到此权限 -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<!--外存储读权限,构建语法需要用到此权限 -->
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<!--摄相头权限,拍照需要用到 -->
<uses-permission android:name="android.permission.CAMERA" />
</manifest>
package com.test.df;
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.widget.Toast;
import com.iflytek.cloud.InitListener;
import com.iflytek.cloud.RecognizerListener;
import com.iflytek.cloud.RecognizerResult;
import com.iflytek.cloud.SpeechConstant;
import com.iflytek.cloud.SpeechError;
import com.iflytek.cloud.SpeechSynthesizer;
import com.iflytek.cloud.SpeechUtility;
import com.iflytek.cloud.SpeechRecognizer;
import com.iflytek.cloud.SynthesizerListener;
import com.unity3d.player.UnityPlayer;
import com.unity3d.player.UnityPlayerActivity;
import org.json.JSONArray;
import org.json.JSONObject;
import org.json.JSONTokener;
public class MainActivity extends UnityPlayerActivity{
public SpeechRecognizer speechRecognizer;
public SpeechSynthesizer speechSynthesizer;
private String ttsSpeakerName = "yefang";
private String ttsSpeakerPitch = "50";
@Override
protected void onCreate(Bundle bundle) {
super.onCreate(bundle);
//注意这里的appid为
SpeechUtility.createUtility(getApplicationContext(),"appid=58880d30");
initRecognizer();
}
private void initRecognizer(){
speechRecognizer = SpeechRecognizer.createRecognizer(getApplicationContext(),mInitListener);
speechSynthesizer = SpeechSynthesizer.createSynthesizer(getApplicationContext(),mInitSpeaking);
}
public InitListener mInitListener = new InitListener() {
@Override
public void onInit(int i) {
UnityPlayer.UnitySendMessage("FlyTalk", "OnInit", "init Listener success!");
}
};
public InitListener mInitSpeaking = new InitListener() {
@Override
public void onInit(int i) {
UnityPlayer.UnitySendMessage("FlyTTS", "OnInit", "init Speaking success!");
}
};
//TTS是Text To Speech的缩写,即“从文本到语音”
public void setTTSSpeaker(String targetName) {
ttsSpeakerName = targetName;
}
public void setTTSPitch(String targetPitch) {
ttsSpeakerPitch = targetPitch;
}
public void doTTS(String ttsStr){
//设置发音人
speechSynthesizer.setParameter(SpeechConstant.VOICE_NAME,ttsSpeakerName);
//设置音调
speechSynthesizer.setParameter(SpeechConstant.PITCH,ttsSpeakerPitch);
//设置音量
speechSynthesizer.setParameter(SpeechConstant.VOLUME,"50");
int code = speechSynthesizer.startSpeaking(ttsStr, mTTSListener);
//UnityPlayer.UnitySendMessage("FlyTTS", "IsSpeaking", ttsStr+String.valueOf(code));
}
private SynthesizerListener mTTSListener = new SynthesizerListener() {
@Override
public void onSpeakBegin() {
UnityPlayer.UnitySendMessage("FlyTTS", "SpeakingBegin", "SpeakingStart");
}
@Override
public void onBufferProgress(int i, int i1, int i2, String s) {
}
@Override
public void onSpeakPaused() {
}
@Override
public void onSpeakResumed() {
}
@Override
public void onSpeakProgress(int i, int i1, int i2) {
}
@Override
public void onCompleted(SpeechError speechError) {
UnityPlayer.UnitySendMessage("FlyTTS", "SpeakingEnd", speechError.toString());
}
@Override
public void onEvent(int i, int i1, int i2, Bundle bundle) {
}
};
//开始听写
public void startSpeechListener(){
UnityPlayer.UnitySendMessage("FlyTalk", "Result", "");
speechRecognizer.setParameter(SpeechConstant.DOMAIN, "iat");
speechRecognizer.setParameter(SpeechConstant.LANGUAGE, "zh_cn");
speechRecognizer.setParameter(SpeechConstant.ACCENT, "mandarin");
speechRecognizer.startListening(mRecognizerListener);
}
public RecognizerListener mRecognizerListener = new RecognizerListener(){
@Override
public void onBeginOfSpeech() {
// TODO Auto-generated method stub
UnityPlayer.UnitySendMessage("FlyTalk", "OnSpeechStart", "SpeechBegin");
}
@Override
public void onEndOfSpeech() {
// TODO Auto-generated method stub
UnityPlayer.UnitySendMessage("FlyTalk", "OnSpeechEnd","SpeechEnd");
}
@Override
public void onError(SpeechError arg0) {
// TODO Auto-generated method stub
UnityPlayer.UnitySendMessage("FlyTalk", "OnSpeechError", arg0.getErrorDescription());
}
@Override
public void onEvent(int arg0, int arg1, int arg2, Bundle arg3) {
// TODO Auto-generated method stub
//UnityPlayer.UnitySendMessage("FlyTalk", "Result", "onEvent");
}
@Override
public void onResult(RecognizerResult recognizerResult, boolean isLast) {
printResult(recognizerResult);
}
@Override
public void onVolumeChanged(int arg0, byte[] arg1) {
//UnityPlayer.UnitySendMessage("FlyTalk", "Result", "onVolumeChanged");
// TODO Auto-generated method stub
}
};
//解析
private void printResult(RecognizerResult results) {
String json = results.getResultString();
StringBuffer ret = new StringBuffer();
try {
JSONTokener tokener = new JSONTokener(json);
JSONObject joResult = new JSONObject(tokener);
JSONArray words = joResult.getJSONArray("ws");
for (int i = 0; i < words.length(); i++) {
// 转写结果词,默认使用第一个结果
JSONArray items = words.getJSONObject(i).getJSONArray("cw");
JSONObject obj = items.getJSONObject(0);
ret.append(obj.getString("w"));
}
} catch (Exception e) {
e.printStackTrace();
}
//将解析结果“"result:" + ret.toString()”发送至“Manager”这个GameObject,中的“Result”函数
//UnityPlayer.UnitySendMessage("FlyTalk", "Result", ret.toString());
UnityPlayer.UnitySendMessage("FlyTalk", "OnSpeechResult", ret.toString());
}
public void ShowToast(final String mStr2Show){
//UnityPlayer.UnitySendMessage("FlyTalk", "OnResult", "toast");
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(getApplicationContext(),mStr2Show,Toast.LENGTH_LONG).show();
}
});
}
}
使用时将android studio导出的.arr文件拷贝Assets\Plugins\Android下面,将Unity本身生成的不是android studio生成的AndroidMainfest.xml也拷贝到这个目录下面。android打包时后自动合并这个xml和.arr里面的xml成新的xml使用(这时需要修改将android studioandroid studio生成的Activity替换Unity导出的Activity,否则会出现两个图标)
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.youxigu.df" xmlns:tools="http://schemas.android.com/tools" android:versionName="1.0" android:versionCode="1" android:installLocation="preferExternal">
<supports-screens android:smallScreens="true" android:normalScreens="true" android:largeScreens="true" android:xlargeScreens="true" android:anyDensity="true" />
<application android:theme="@style/UnityThemeSelector" android:icon="@drawable/app_icon" android:label="@string/app_name" android:isGame="true" android:banner="@drawable/app_banner">
<activity android:label="@string/app_name" android:screenOrientation="sensorLandscape" android:launchMode="singleTask" android:configChanges="mcc|mnc|locale|touchscreen|keyboard|keyboardHidden|navigation|orientation|screenLayout|uiMode|screenSize|smallestScreenSize|fontScale" android:name="com.test.df.MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
<category android:name="android.intent.category.LEANBACK_LAUNCHER" />
</intent-filter>
<meta-data android:name="unityplayer.UnityActivity" android:value="true" />
</activity>
</application>
<uses-sdk android:minSdkVersion="9" android:targetSdkVersion="26" />
<uses-feature android:glEsVersion="0x00020000" />
<supports-gl-texture android:name="GL_OES_compressed_ETC1_RGB8_texture" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-feature android:name="android.hardware.touchscreen" android:required="false" />
<uses-feature android:name="android.hardware.touchscreen.multitouch" android:required="false" />
<uses-feature android:name="android.hardware.touchscreen.multitouch.distinct" android:required="false" />
</manifest>
这种方式适合只有一个主Activity 然后这个Activity里面整合其他的sdk接口
2.第二种方式
1)实现SDK时一定要存在一个中间件Activity继承UnityPlayerActivity吗?
网上几乎所有教程都是这样教的,新建一个MyActivity,然后继承UnityPlayerActivity,在MyActivity里面写接口,然而根本没有讲清楚为什么要这样做。。
对于1)的问题,答案是NO,简单说一下我的理解,只有当需要在Activity的生命周期中执行一些操作时,我们才需要一个中间Activity去完成这些与生命周期相关的操作,而其他情况下,一个Class足以。
package com.test.df;
import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.util.Log;
import android.widget.Toast;
import com.iflytek.cloud.InitListener;
import com.iflytek.cloud.RecognizerListener;
import com.iflytek.cloud.RecognizerResult;
import com.iflytek.cloud.SpeechConstant;
import com.iflytek.cloud.SpeechError;
import com.iflytek.cloud.SpeechSynthesizer;
import com.iflytek.cloud.SpeechUtility;
import com.iflytek.cloud.SpeechRecognizer;
import com.iflytek.cloud.SynthesizerListener;
import com.unity3d.player.UnityPlayer;
import com.unity3d.player.UnityPlayerActivity;
import org.json.JSONArray;
import org.json.JSONObject;
import org.json.JSONTokener;
public class MainActivity{
public SpeechRecognizer speechRecognizer;
public SpeechSynthesizer speechSynthesizer;
private String ttsSpeakerName = "yefang";
private String ttsSpeakerPitch = "50";
private Activity mActivity;
public static MainActivity mInstance = null;
public static MainActivity getInstance()
{
if (mInstance == null)
{
mInstance = new MainActivity();
}
return mInstance;
}
private Context getApplicationContext()
{
return mActivity.getApplicationContext();
}
protected void onCreate(Context context) {
mActivity = (Activity)context;
//注意这里的appid为
SpeechUtility.createUtility(getApplicationContext(),"appid=58880d30");
initRecognizer();
}
private void initRecognizer(){
speechRecognizer = SpeechRecognizer.createRecognizer(getApplicationContext(),mInitListener);
speechSynthesizer = SpeechSynthesizer.createSynthesizer(getApplicationContext(),mInitSpeaking);
}
public InitListener mInitListener = new InitListener() {
@Override
public void onInit(int i) {
UnityPlayer.UnitySendMessage("FlyTalk", "OnInit", "init Listener success!");
}
};
public InitListener mInitSpeaking = new InitListener() {
@Override
public void onInit(int i) {
UnityPlayer.UnitySendMessage("FlyTTS", "OnInit", "init Speaking success!");
}
};
//TTS是Text To Speech的缩写,即“从文本到语音”
public void setTTSSpeaker(String targetName) {
ttsSpeakerName = targetName;
}
public void setTTSPitch(String targetPitch) {
ttsSpeakerPitch = targetPitch;
}
public void doTTS(String ttsStr){
//设置发音人
speechSynthesizer.setParameter(SpeechConstant.VOICE_NAME,ttsSpeakerName);
//设置音调
speechSynthesizer.setParameter(SpeechConstant.PITCH,ttsSpeakerPitch);
//设置音量
speechSynthesizer.setParameter(SpeechConstant.VOLUME,"50");
int code = speechSynthesizer.startSpeaking(ttsStr, mTTSListener);
//UnityPlayer.UnitySendMessage("FlyTTS", "IsSpeaking", ttsStr+String.valueOf(code));
}
private SynthesizerListener mTTSListener = new SynthesizerListener() {
@Override
public void onSpeakBegin() {
UnityPlayer.UnitySendMessage("FlyTTS", "SpeakingBegin", "SpeakingStart");
}
@Override
public void onBufferProgress(int i, int i1, int i2, String s) {
}
@Override
public void onSpeakPaused() {
}
@Override
public void onSpeakResumed() {
}
@Override
public void onSpeakProgress(int i, int i1, int i2) {
}
@Override
public void onCompleted(SpeechError speechError) {
UnityPlayer.UnitySendMessage("FlyTTS", "SpeakingEnd", speechError.toString());
}
@Override
public void onEvent(int i, int i1, int i2, Bundle bundle) {
}
};
//开始听写
public void startSpeechListener(){
UnityPlayer.UnitySendMessage("FlyTalk", "Result", "");
speechRecognizer.setParameter(SpeechConstant.DOMAIN, "iat");
speechRecognizer.setParameter(SpeechConstant.LANGUAGE, "zh_cn");
speechRecognizer.setParameter(SpeechConstant.ACCENT, "mandarin");
speechRecognizer.startListening(mRecognizerListener);
}
public RecognizerListener mRecognizerListener = new RecognizerListener(){
@Override
public void onBeginOfSpeech() {
// TODO Auto-generated method stub
UnityPlayer.UnitySendMessage("FlyTalk", "OnSpeechStart", "SpeechBegin");
}
@Override
public void onEndOfSpeech() {
// TODO Auto-generated method stub
UnityPlayer.UnitySendMessage("FlyTalk", "OnSpeechEnd","SpeechEnd");
}
@Override
public void onError(SpeechError arg0) {
// TODO Auto-generated method stub
UnityPlayer.UnitySendMessage("FlyTalk", "OnSpeechError", arg0.getErrorDescription());
}
@Override
public void onEvent(int arg0, int arg1, int arg2, Bundle arg3) {
// TODO Auto-generated method stub
//UnityPlayer.UnitySendMessage("FlyTalk", "Result", "onEvent");
}
@Override
public void onResult(RecognizerResult recognizerResult, boolean isLast) {
printResult(recognizerResult);
}
@Override
public void onVolumeChanged(int arg0, byte[] arg1) {
//UnityPlayer.UnitySendMessage("FlyTalk", "Result", "onVolumeChanged");
// TODO Auto-generated method stub
}
};
//解析
private void printResult(RecognizerResult results) {
String json = results.getResultString();
StringBuffer ret = new StringBuffer();
try {
JSONTokener tokener = new JSONTokener(json);
JSONObject joResult = new JSONObject(tokener);
JSONArray words = joResult.getJSONArray("ws");
for (int i = 0; i < words.length(); i++) {
// 转写结果词,默认使用第一个结果
JSONArray items = words.getJSONObject(i).getJSONArray("cw");
JSONObject obj = items.getJSONObject(0);
ret.append(obj.getString("w"));
}
} catch (Exception e) {
e.printStackTrace();
}
//将解析结果“"result:" + ret.toString()”发送至“Manager”这个GameObject,中的“Result”函数
//UnityPlayer.UnitySendMessage("FlyTalk", "Result", ret.toString());
UnityPlayer.UnitySendMessage("FlyTalk", "OnSpeechResult", ret.toString());
}
public void ShowToast(final String mStr2Show){
//UnityPlayer.UnitySendMessage("FlyTalk", "OnResult", "toast");
mActivity.runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(getApplicationContext(),mStr2Show,Toast.LENGTH_LONG).show();
}
});
}
}
这个没有继承UnityPlayerActivity 使用一个单例和onCreate将Unity中的Activity传入到这里面用来获得当前acticity上下文环境
这时AndroidMainfest.xml就可以不需要Activity了 只需要配置权限打包aar后Unity会自动融合
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.youxigu.df" >
<!--连接网络权限,用于执行云端语音能力 -->
<uses-permission android:name="android.permission.INTERNET"/>
<!--获取手机录音机使用权限,听写、识别、语义理解需要用到此权限 -->
<uses-permission android:name="android.permission.RECORD_AUDIO"/>
<!--读取网络信息状态 -->
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<!--获取当前wifi状态 -->
<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"/>
<!--外存储写权限,构建语法需要用到此权限 -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<!--外存储读权限,构建语法需要用到此权限 -->
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<!--摄相头权限,拍照需要用到 -->
<uses-permission android:name="android.permission.CAMERA" />
</manifest>
ajc = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
AndroidJavaObject jo = ajc.GetStatic<AndroidJavaObject>("currentActivity");
ajc = new AndroidJavaClass("com.test.df.MainActivity");
ajo = ajc.CallStatic<AndroidJavaObject>("getInstance");
Debug.Log("getInstance call" + ajo.GetType().ToString());
ajo.Call("onCreate", jo);
Debug.logger.logEnabled = true;
这个将log打印到adb logcat中
这样就可以调用了