700字范文,内容丰富有趣,生活中的好帮手!
700字范文 > Unity接入讯飞语音听写(Android)

Unity接入讯飞语音听写(Android)

时间:2021-08-02 16:58:59

相关推荐

Unity接入讯飞语音听写(Android)

使用的引擎工具:

Unity.3.19

android-studio-.1.21

第一步:

新建一个Android项目(工程名字随便啦)

然后新建一个library

(同上,库名自己命名吧)

Android环境目前就算是初步建立好了。

第二步:

导包

libs文件夹里面放入这4个文件,arm64-v8a,armeabi-v7a,Msc.jar这三个文件是讯飞官网下载下来的demo项目里面的,直接复制到libs里面就好,classes.jar包是在下面这个路径下的

(注:Classes.jar用mono还是IL2CPP得和Unity-PlayerSetting-ScriptBackend一致)

第三步:

倒入UnityPlayerActivity

最新版本Unity里面的classes.jar包文件里面以及不包含UnityPlayerActivity了,所以我们需要自己导入UnityPlayerActivity(或者自己编写一个也可以,回头可以再出一篇)

文件位置:

第四步:

在AndroidStudio实现供unity调用的接口方法,直接上代码了(讯飞APPID自己填写)

package com.example.mylibrary;import android.content.Context;import android.os.Bundle;import android.util.Log;import android.widget.Toast;import com.iflytek.cloud.ErrorCode;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.SpeechRecognizer;import com.iflytek.cloud.SpeechUtility;import com.unity.upa.UnityPlayerActivity;import com.unity3d.player.UnityPlayer;import org.json.JSONException;import org.json.JSONObject;import java.util.HashMap;import java.util.LinkedHashMap;public class XunFeiSdk extends UnityPlayerActivity {private HashMap<String, String> mIatResults = new LinkedHashMap<String, String>();SpeechRecognizer mIAT;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);SpeechUtility.createUtility(this, SpeechConstant.APPID + "=xxxxxx");//这里是你在讯飞官网上的APPIDmIAT=SpeechRecognizer.createRecognizer(this,null);mIAT.setParameter(SpeechConstant.DOMAIN,"iat");// 语言mIAT.setParameter(SpeechConstant.LANGUAGE,"zh_cn");// 接收语言的类型mIAT.setParameter(SpeechConstant.ACCENT,"mandarin");// 使用什么引擎mIAT.setParameter(SpeechConstant.ENGINE_TYPE,SpeechConstant.TYPE_CLOUD);}public void StartListening() {mIAT.startListening(recognizerListener);}RecognizerListener recognizerListener = new RecognizerListener() {@Overridepublic void onVolumeChanged(int i, byte[] bytes) {UnityPlayer.UnitySendMessage("XfManager","OnVolumeChanged","");}@Overridepublic void onBeginOfSpeech() {UnityPlayer.UnitySendMessage("XfManager","OnBeginOfSpeech","");}@Overridepublic void onEndOfSpeech() {UnityPlayer.UnitySendMessage("XfManager","OnEndOfSpeech","");}@Overridepublic void onResult(RecognizerResult recognizerResult, boolean b) {printResult(recognizerResult);}@Overridepublic void onError(SpeechError speechError) {UnityPlayer.UnitySendMessage("XfManager","OnError",speechError.getErrorDescription());}@Overridepublic void onEvent(int i, int i1, int i2, Bundle bundle) {}};private void printResult(com.iflytek.cloud.RecognizerResult results) {// JsonParser是一个工具类String text = JsonParser.parseIatResult(results.getResultString());String sn = null;// 读取json结果中的sn字段try {JSONObject resultJson = new JSONObject(results.getResultString());sn = resultJson.optString("sn");} catch (JSONException e) {e.printStackTrace();}mIatResults.put(sn, text);// resultBuffer 为最终返回的结果StringBuffer resultBuffer = new StringBuffer();for (String key : mIatResults.keySet()) {resultBuffer.append(mIatResults.get(key));}// 把得到的结果返回给Unity 第一个参数为unity种的游戏物体 第二个参数为 这个游戏物体身上脚本的方法 第三个参数为讯飞返回的最终结果UnityPlayer.UnitySendMessage("XfManager","OnResult",resultBuffer.toString());}public void VoidTest(){UnityPlayer.UnitySendMessage("XfManager","FromAndroid","Android:消息发送至Unity");}}

Json类(这个是讯飞demo里面的)

package com.example.mylibrary;import org.json.JSONArray;import org.json.JSONObject;import org.json.JSONTokener;/*** Json结果解析类*/public class JsonParser {public static String parseIatResult(String json) {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"));//如果需要多候选结果,解析数组其他字段//for(int j = 0; j < items.length(); j++)//{// JSONObject obj = items.getJSONObject(j);// ret.append(obj.getString("w"));//}}} catch (Exception e) {e.printStackTrace();}return ret.toString();}public static String parseGrammarResult(String json, String engType) {StringBuffer ret = new StringBuffer();try {JSONTokener tokener = new JSONTokener(json);JSONObject joResult = new JSONObject(tokener);JSONArray words = joResult.getJSONArray("ws");// 云端和本地结果分情况解析if ("cloud".equals(engType)) {for (int i = 0; i < words.length(); i++) {JSONArray items = words.getJSONObject(i).getJSONArray("cw");for (int j = 0; j < items.length(); j++) {JSONObject obj = items.getJSONObject(j);if (obj.getString("w").contains("nomatch")) {ret.append("没有匹配结果.");return ret.toString();}ret.append("【结果】" + obj.getString("w"));ret.append("【置信度】" + obj.getInt("sc"));ret.append("\n");}}} else if ("local".equals(engType)) {ret.append("【结果】");for (int i = 0; i < words.length(); i++) {JSONObject wsItem = words.getJSONObject(i);JSONArray items = wsItem.getJSONArray("cw");if ("<contact>".equals(wsItem.getString("slot"))) {// 可能会有多个联系人供选择,用中括号括起来,这些候选项具有相同的置信度ret.append("【");for (int j = 0; j < items.length(); j++) {JSONObject obj = items.getJSONObject(j);if (obj.getString("w").contains("nomatch")) {ret.append("没有匹配结果.");return ret.toString();}ret.append(obj.getString("w")).append("|");}ret.setCharAt(ret.length() - 1, '】');} else {//本地多候选按照置信度高低排序,一般选取第一个结果即可JSONObject obj = items.getJSONObject(0);if (obj.getString("w").contains("nomatch")) {ret.append("没有匹配结果.");return ret.toString();}ret.append(obj.getString("w"));}}ret.append("【置信度】" + joResult.getInt("sc"));ret.append("\n");}} catch (Exception e) {e.printStackTrace();ret.append("没有匹配结果.");}return ret.toString();}public static String parseGrammarResult(String json) {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");for (int j = 0; j < items.length(); j++) {JSONObject obj = items.getJSONObject(j);if (obj.getString("w").contains("nomatch")) {ret.append("没有匹配结果.");return ret.toString();}ret.append("【结果】" + obj.getString("w"));ret.append("【置信度】" + obj.getInt("sc"));ret.append("\n");}}} catch (Exception e) {e.printStackTrace();ret.append("没有匹配结果.");}return ret.toString();}public static String parseLocalGrammarResult(String json) {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");for (int j = 0; j < items.length(); j++) {JSONObject obj = items.getJSONObject(j);if (obj.getString("w").contains("nomatch")) {ret.append("没有匹配结果.");return ret.toString();}ret.append("【结果】" + obj.getString("w"));ret.append("\n");}}ret.append("【置信度】" + joResult.optInt("sc"));} catch (Exception e) {e.printStackTrace();ret.append("没有匹配结果.");}return ret.toString();}public static String parseTransResult(String json, String key) {StringBuffer ret = new StringBuffer();try {JSONTokener tokener = new JSONTokener(json);JSONObject joResult = new JSONObject(tokener);String errorCode = joResult.optString("ret");if (!errorCode.equals("0")) {return joResult.optString("errmsg");}JSONObject transResult = joResult.optJSONObject("trans_result");ret.append(transResult.optString(key));/*JSONArray words = joResult.getJSONArray("results");for (int i = 0; i < words.length(); i++) {JSONObject obj = words.getJSONObject(i);ret.append(obj.getString(key));}*/} catch (Exception e) {e.printStackTrace();}return ret.toString();}}

代码就是以上这些了,接下来就是修改AndroidManifest

第五步:

AndroidManifest.xml文件

<?xml version="1.0" encoding="utf-8"?><manifest xmlns:tools="/tools"xmlns:android="/apk/res/android"package="com.example.mylibrary"><applicationandroid:allowBackup="true"android:supportsRtl="true"><activity android:name=".XunFeiSdk"android:exported="true"><intent-filter><action android:name="android.intent.action.MAIN" /><category android:name="android.intent.category.LAUNCHER" /></intent-filter></activity><meta-data android:name="unityplayer.UnityActivity" android:value="true"/></application><uses-permission android:name="android.permission.RECORD_AUDIO" /><uses-permission android:name="android.permission.INTERNET" /><uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /><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.ACCESS_FINE_LOCATION" /><uses-permission android:name="android.permission.READ_CONTACTS" /><uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /><uses-permission android:name="android.permission.WRITE_SETTINGS"tools:ignore="ProtectedPermissions" /><uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /><uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /><uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /></manifest>

第六步:

完成以上这些步骤就可以打包成arr文件了

选中你的库文件然后点击build-Make Module,如图所示

arr生成路径是

结果如下

把mylibrary.arr文件根目录里的classes.jar和AndroidManifest复制出来(拖出来)

下面这个是从arr包里取出来的AndroidManifest文件,把<uses-sdk android:minSdkVersion="26" />删掉

第七步:

下面就是Unity这边了,Unity端比较简单,直接看图吧

这个AndroidManifest文件就是第六步的AndroidManifest文件,

classes.jar文件放在Plugins-Android-bin目录下

libs目录下放的是同第二步一样的3个文件

然后Unity测试界面

using System;using System.Collections;using System.Collections.Generic;using TMPro;using UnityEngine;using UnityEngine.UI;public class XfManager : MonoBehaviour{private AndroidJavaClass ajc;private AndroidJavaObject ajo;//private AndroidJavaObject XunFeiSdk;public Button StartButton,testBtn;public TextMeshProUGUI ResultText;private void Start(){ajc = new AndroidJavaClass("com.unity3d.player.UnityPlayer");ajo = ajc.GetStatic<AndroidJavaObject>("currentActivity");//XunFeiSdk = new AndroidJavaObject("com.example.mylibrary.XunFeiSdk");testBtn.onClick.AddListener(TestConnect);if (StartButton){StartButton.onClick.AddListener(() => { StartListening(); });}}private void TestConnect(){ajo.Call("VoidTest");}public void FromAndroid(string s) {ResultText.text = s;}public void StartListening(){ajo.Call("StartListening");}public void OnStartListening(string ret){int result = int.Parse(ret);StartButton.interactable = result == 0;}public void OnResult(string result){ResultText.text = result;}public void OnError(string errorMessage){ResultText.text = errorMessage;}public void OnEndOfSpeech(){StartButton.GetComponentInChildren<TextMeshProUGUI>().text = "已结束,点击聆听";StartButton.interactable = true;}public void OnBeginOfSpeech(){StartButton.GetComponentInChildren<TextMeshProUGUI>().text = "聆听ing";StartButton.interactable = false;}}

最后就是打包了

注:这里的包名必须跟你配置文件里面的一致才行,还有就是再重复一遍,Classes.jar用mono还是IL2CPP得和Unity-PlayerSetting-ScriptBackend一致。

打包成功,测试正常(注意开启权限哦)

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。