Unity+Android+訊飛離線命令詞識別(HLYH)


1.下載SDK之前要先創建自己的應用。去訊飛官網注冊個賬號,然后創建完成之后打開控制台創建應用。我塗掉的這部分是我自己的appid,這個東西在后面會用到。

 

 

1.下載離線版SDK。下載方法參考網上一些例子。這里就不多說,有很多文章。

 

2.下載SDK如下圖。

 

 

4.直接打開SDK下sample中的demo,build出錯“ERROR: Plugin with id 'com.android.application' not found.”

官網解決方案(用了但是並沒有解決)

如果編譯時出現“ERROR: Plugin with id 'com.android.application' not found.”錯誤,請在build.gradle文件中添加以下代碼。

buildscript {
    repositories {
        google()
        jcenter()
    }
    dependencies {
         //版本號請根據自己的gradle插件版本號自行更改
        classpath 'com.android.tools.build:gradle:3.4.0'
        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
    }
}

如在導入項目中還出現其他問題,可參考帖子:安卓demo常見錯誤排查

打開file-->project structure ,可查看gradle version,

 

 

 

 

 

 

解決方案(導入module方式):

新建一個空的Android Studio項目,file--new--import  module導入下載SDK中sample下的demo

 (打開Android Studio,在菜單欄File--->new--->import module當前解壓sdk路徑,使用離線服務能力選擇導入mscV5PlusDemo,導入成功之后sync編譯下,編譯無誤可連接手機,開啟手機USB開發調試模式,直接在Android Studio運行導入的mscV5PlusDemo,最后生成的apk可直接安裝在對應的手機上。)

(點擊Tool-->SDK Manager可選擇版本號)

 

 5主要代碼如下:

 Android Studio

AsrDemo
package com.iflytek.mscv5plusdemo;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.os.Bundle;
import android.os.Environment;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.Window;
import android.widget.EditText;
import android.widget.RadioGroup;
import android.widget.RadioGroup.OnCheckedChangeListener;
import android.widget.Toast;

import com.iflytek.cloud.ErrorCode;
import com.iflytek.cloud.GrammarListener;
import com.iflytek.cloud.InitListener;
import com.iflytek.cloud.LexiconListener;
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.iflytek.cloud.util.ContactManager;
import com.iflytek.cloud.util.ContactManager.ContactListener;
import com.iflytek.cloud.util.ResourceUtil;
import com.iflytek.cloud.util.ResourceUtil.RESOURCE_TYPE;
import com.iflytek.speech.util.FucUtil;
import com.iflytek.speech.util.JsonParser;
import com.iflytek.speech.util.XmlParser;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class AsrDemo /*extends Activity implements OnClickListener*/{
    private final static String TAG = AsrDemo.class.getSimpleName();

    private Toast mToast;
    // 語音識別對象
    private SpeechRecognizer mAsr;
    // 緩存
    private SharedPreferences mSharedPreferences;
    // 本地語法文件
    private String mLocalGrammar = null;
    // 本地詞典
    private String mLocalLexicon = null;
    // 雲端語法文件
    private String mCloudGrammar = null;
    // 本地語法構建路徑
    //private String grmPath = Environment.getExternalStorageDirectory()
            //.getAbsolutePath() + "/msc/test";
    /*
    private String grmPath = Environment.getExternalStorageDirectory()
            .getAbsolutePath() + "/msc/test";
            僅僅這句創建文件夾會報錯,錯誤碼23108,解決方案如下:
    但是,如果要建多層目錄的文件夾的話,可不能一蹴而就。像下面這樣寫代碼的話,執行代碼后,在Android設備的外存里是不會創建文件夾“myApp/sub”的:
String appHome = Environment.getExternalStorageDirectory().getAbsolutePath()+"/myApp";
createDir(appHome)
如果要建多層目錄的文件夾,只能是一步一步的建,如下所示:

String appHome = Environment.getExternalStorageDirectory().getAbsolutePath()+"/myApp";
String subPath = appHome+"/sub";
createDir(appHome);
createDir(subPath);
————————————————
    */
//2021.3.25更改后如下
    private String str = Environment.getExternalStorageDirectory()
            .getAbsolutePath() + "/msc";
    private String grmPath = str+ "/test";

    // 返回結果格式,支持:xml,json
    private String mResultType = "json";

    private  final String KEY_GRAMMAR_ABNF_ID = "grammar_abnf_id";
    private  final String GRAMMAR_TYPE_ABNF = "abnf";
    private  final String GRAMMAR_TYPE_BNF = "bnf";

    private String mEngineType = SpeechConstant.TYPE_LOCAL;
    @SuppressLint("ShowToast")
    public void onCreate(Bundle savedInstanceState)
    {
        //super.onCreate(savedInstanceState);
        //this.requestWindowFeature(Window.FEATURE_NO_TITLE);
        //setContentView(R.layout.isrdemo);
        initLayout();

        // 初始化識別對象
        mAsr = SpeechRecognizer.createRecognizer(getActivity(), mInitListener);
        if(mAsr==null){
            Log.e(TAG,"masr is null");
        }
        // 初始化語法、命令詞
        mLocalLexicon = "開始\n";
        //mLocalLexicon = "張海羊\n劉婧\n王鋒\n";
        mLocalGrammar = FucUtil.readFile(getActivity(),"call.bnf", "utf-8");
        mCloudGrammar = FucUtil.readFile(getActivity(),"grammar_sample.abnf","utf-8");

        // 獲取聯系人,本地更新詞典時使用
        //ContactManager mgr = ContactManager.createManager(AsrDemo.this, mContactListener);
        //mgr.asyncQueryAllContactsName();
        //mSharedPreferences = getSharedPreferences(getPackageName(),    MODE_PRIVATE);

        //mToast = Toast.makeText(this,"",Toast.LENGTH_SHORT);
    }

    /**
     * 初始化Layout。
     */
    private void initLayout(){
        //findViewById(R.id.isr_recognize).setOnClickListener(this);
//
        //findViewById(R.id.isr_grammar).setOnClickListener(this);
        ////findViewById(R.id.isr_lexcion).setOnClickListener(this);
//
        //findViewById(R.id.isr_stop).setOnClickListener(this);
        //findViewById(R.id.isr_cancel).setOnClickListener(this);


        //((EditText)findViewById(R.id.isr_text)).setText(mLocalGrammar);
        //findViewById(R.id.isr_lexcion).setEnabled(true);
        mEngineType =  SpeechConstant.TYPE_LOCAL;
        ////選擇雲端or本地
        //RadioGroup group = (RadioGroup)this.findViewById(R.id.radioGroup);
        //group.setOnCheckedChangeListener(new OnCheckedChangeListener() {
        //    @Override
        //    public void onCheckedChanged(RadioGroup group, int checkedId) {
        //        if(checkedId == R.id.radioCloud)
        //        {
        //            ((EditText)findViewById(R.id.isr_text)).setText(mCloudGrammar);
        //            findViewById(R.id.isr_lexcion).setEnabled(false);
        //            mEngineType = SpeechConstant.TYPE_CLOUD;
        //        }else if(checkedId == R.id.radioLocal)
        //        {
        //            ((EditText)findViewById(R.id.isr_text)).setText(mLocalGrammar);
        //            findViewById(R.id.isr_lexcion).setEnabled(true);
        //            mEngineType =  SpeechConstant.TYPE_LOCAL;
        //        }
        //    }
        //});
    }







    String mContent;// 語法、詞典臨時變量
    int ret = 0;// 函數調用返回值
    //@Override
    //public void onClick(View view) {
    //    if( null == mAsr ){
    //        // 創建單例失敗,與 21001 錯誤為同樣原因,參考 http://bbs.xfyun.cn/forum.php?mod=viewthread&tid=9688
    //        this.showTip( "創建對象失敗,請確認 libmsc.so 放置正確,\n 且有調用 createUtility 進行初始化" );
    //        return;
    //    }
    //
    //    if(null == mEngineType) {
    //        showTip("請先選擇識別引擎類型");
    //        return;
    //    }
    //    switch(view.getId())
    //    {
    //        case R.id.isr_grammar:
    //            showTip("上傳預設關鍵詞/語法文件");
    //            // 本地-構建語法文件,生成語法id
    //            //if (mEngineType.equals(SpeechConstant.TYPE_LOCAL)) {
    //                //((EditText)findViewById(R.id.isr_text)).setText(mLocalGrammar);
    //            Buildsyntax();
    //            //}
    //            //// 在線-構建語法文件,生成語法id
    //            //else {
    //            //    ((EditText)findViewById(R.id.isr_text)).setText(mCloudGrammar);
    //            //    mContent = new String(mCloudGrammar);
    //            //    // 指定引擎類型
    //            //    mAsr.setParameter(SpeechConstant.ENGINE_TYPE, mEngineType);
    //            //    // 設置文本編碼格式
    //            //    mAsr.setParameter(SpeechConstant.TEXT_ENCODING,"utf-8");
    //            //    ret = mAsr.buildGrammar(GRAMMAR_TYPE_ABNF, mContent, grammarListener);
    //            //    if(ret != ErrorCode.SUCCESS)
    //            //        showTip("語法構建失敗,錯誤碼:" + ret+",請點擊網址https://www.xfyun.cn/document/error-code查詢解決方案");
    //            //}
    //            break;
    //        // 本地-更新詞典
    //        //case R.id.isr_lexcion:
    //        //    ((EditText)findViewById(R.id.isr_text)).setText(mLocalLexicon);
    //        //    mContent = new String(mLocalLexicon);
    //        //    mAsr.setParameter(SpeechConstant.PARAMS, null);
    //        //    // 設置引擎類型
    //        //    mAsr.setParameter(SpeechConstant.ENGINE_TYPE, SpeechConstant.TYPE_LOCAL);
    //        //    // 設置資源路徑
    //        //    mAsr.setParameter(ResourceUtil.ASR_RES_PATH, getResourcePath());
    //        //    //使用8k音頻的時候請解開注釋
//    //        //    mAsr.setParameter(SpeechConstant.SAMPLE_RATE, "8000");
    //        //    // 設置語法構建路徑
    //        //    mAsr.setParameter(ResourceUtil.GRM_BUILD_PATH, grmPath);
    //        //    // 設置語法名稱
    //        //    mAsr.setParameter(SpeechConstant.GRAMMAR_LIST, "call");
    //        //    // 設置文本編碼格式
    //        //    mAsr.setParameter(SpeechConstant.TEXT_ENCODING,"utf-8");
    //        //    ret = mAsr.updateLexicon("contact", mContent, lexiconListener);
    //        //    if(ret != ErrorCode.SUCCESS){
    //        //        showTip("更新詞典失敗,錯誤碼:" + ret+",請點擊網址https://www.xfyun.cn/document/error-code查詢解決方案");
    //        //    }
    //        //    break;
    //        // 開始識別
    //        case R.id.isr_recognize:
    //            //((EditText)findViewById(R.id.isr_text)).setText(null);// 清空顯示內容
    //            StartRecognize();
    //            break;
    //        // 停止識別
    //        case R.id.isr_stop:
    //            mAsr.stopListening();
    //            showTip("停止識別");
    //            break;
    //        // 取消識別
    //        case R.id.isr_cancel:
    //            mAsr.cancel();
    //            showTip("取消識別");
    //            break;
    //    }
    //}




    /**
     * 初始化監聽器。
     */
    private InitListener mInitListener = new InitListener() {

        @Override
        public void onInit(int code) {
            Log.d(TAG, "SpeechRecognizer init() code = " + code);
            if (code != ErrorCode.SUCCESS) {
                showTip("初始化失敗,錯誤碼:"+code+",請點擊網址https://www.xfyun.cn/document/error-code查詢解決方案");
            }
        }
    };

    /**
     * 更新詞典監聽器。
     */
    private LexiconListener lexiconListener = new LexiconListener() {
        @Override
        public void onLexiconUpdated(String lexiconId, SpeechError error) {
            if(error == null){
                showTip("詞典更新成功");
            }else{
                showTip("詞典更新失敗,錯誤碼:"+error.getErrorCode());
            }
        }
    };

    /**
     * 構建語法監聽器。
     */
    private GrammarListener grammarListener = new GrammarListener() {
        @Override
        public void onBuildFinish(String grammarId, SpeechError error) {
            if(error == null){
                if (mEngineType.equals(SpeechConstant.TYPE_CLOUD)) {
                    Editor editor = mSharedPreferences.edit();
                    if(!TextUtils.isEmpty(grammarId))
                        editor.putString(KEY_GRAMMAR_ABNF_ID, grammarId);
                    editor.commit();
                }
                showTip("語法構建成功:" + grammarId);
            }else{
                showTip("語法構建失敗,錯誤碼:" + error.getErrorCode());
            }
        }
    };
    /**
     * 獲取聯系人監聽器。
     */
    private ContactListener mContactListener = new ContactListener() {
        @Override
        public void onContactQueryFinish(String contactInfos, boolean changeFlag) {
            //獲取聯系人
            mLocalLexicon = contactInfos;
        }
    };
    /**
     * 識別監聽器。
     */
    private RecognizerListener mRecognizerListener = new RecognizerListener() {

        @Override
        public void onVolumeChanged(int volume, byte[] data) {
            callUnity("Main Camera","FromAndroid", "當前正在說話,音量大小:" + volume);
            //showTip("當前正在說話,音量大小:" + volume);
            Log.d(TAG, "返回音頻數據:"+data.length);
        }

        @Override
        public void onResult(final RecognizerResult result, boolean isLast) {
            if (null != result && !TextUtils.isEmpty(result.getResultString())) {
                Log.d(TAG, "recognizer result:" + result.getResultString());
                String text = "";
                if (mResultType.equals("json")) {
                    text = JsonParser.parseGrammarResult(result.getResultString(), mEngineType);
                    callUnity("Main Camera","FromAndroid", text);
                } else if (mResultType.equals("xml")) {
                    text = XmlParser.parseNluResult(result.getResultString());
                }else{
                    text = result.getResultString();
                }
                // 顯示
                //((EditText) findViewById(R.id.isr_text)).setText(text);
            } else {
                Log.d(TAG, "recognizer result : null");
            }
        }

        @Override
        public void onEndOfSpeech() {
            // 此回調表示:檢測到了語音的尾端點,已經進入識別過程,不再接受語音輸入
            callUnity("Main Camera","FromAndroid", "結束說話");
            //showTip("結束說話");
        }

        @Override
        public void onBeginOfSpeech() {
            // 此回調表示:sdk內部錄音機已經准備好了,用戶可以開始語音輸入
            //showTip("開始說話");
            callUnity("Main Camera","FromAndroid", "開始說話");
            callUnity("Main Camera","FromAndroid", "開始說話22222");
        }

        @Override
        public void onError(SpeechError error) {
            showTip("onError Code:"    + error.getErrorCode());

            callUnity("Main Camera","FromAndroid", "onError Code:"    + error.getErrorCode());
            //2021.3.24測試安卓環境下路徑
            //callUnity("Main Camera","FromAndroid", "onError Code:"    + Environment.getExternalStorageDirectory()
                //    .getAbsolutePath() + "/msc/test"+"_________"+grmPath);
        }

        @Override
        public void onEvent(int eventType, int arg1, int arg2, Bundle obj) {
            // 以下代碼用於獲取與雲端的會話id,當業務出錯時將會話id提供給技術支持人員,可用於查詢會話日志,定位出錯原因
            // 若使用本地能力,會話id為null
            //    if (SpeechEvent.EVENT_SESSION_ID == eventType) {
            //        String sid = obj.getString(SpeechEvent.KEY_EVENT_SESSION_ID);
            //        Log.d(TAG, "session id =" + sid);
            //    }
        }

    };



    private void showTip(final String str) {
        //runOnUiThread(new Runnable() {
        //    @Override
        //    public void run() {
        //        mToast.setText(str);
        //        mToast.show();
        //    }
        //});
    }

    /**
     * 參數設置
     * @return
     */
    public boolean setParam(){
        boolean result = false;
        //callUnity("Main Camera","FromAndroid", "第一行");
        // 清空參數
        mAsr.setParameter(SpeechConstant.PARAMS, null);
        //callUnity("Main Camera","FromAndroid", "第二行");
        // 設置識別引擎
        mAsr.setParameter(SpeechConstant.ENGINE_TYPE, mEngineType);
        //callUnity("Main Camera","FromAndroid", "第三行");
        //if("cloud".equalsIgnoreCase(mEngineType))
        //{
        //    String grammarId = mSharedPreferences.getString(KEY_GRAMMAR_ABNF_ID, null);
        //    if(TextUtils.isEmpty(grammarId))
        //    {
        //        result =  false;
        //    }else {
        //        // 設置返回結果格式
        //        mAsr.setParameter(SpeechConstant.RESULT_TYPE, mResultType);
        //        // 設置雲端識別使用的語法id
        //        mAsr.setParameter(SpeechConstant.CLOUD_GRAMMAR, grammarId);
        //        result =  true;
        //    }
        //}
        //else
        //{
        // 設置本地識別資源
        mAsr.setParameter(ResourceUtil.ASR_RES_PATH, getResourcePath());
        // 設置語法構建路徑
        mAsr.setParameter(ResourceUtil.GRM_BUILD_PATH, grmPath);
        // 設置返回結果格式
        mAsr.setParameter(SpeechConstant.RESULT_TYPE, mResultType);
        // 設置本地識別使用語法id
        mAsr.setParameter(SpeechConstant.LOCAL_GRAMMAR, "call");
        // 設置識別的門限值
        mAsr.setParameter(SpeechConstant.MIXED_THRESHOLD, "30");
        // 使用8k音頻的時候請解開注釋
//            mAsr.setParameter(SpeechConstant.SAMPLE_RATE, "8000");
        result = true;
        //}

        // 設置音頻保存路徑,保存音頻格式支持pcm、wav,設置路徑為sd卡請注意WRITE_EXTERNAL_STORAGE權限
        mAsr.setParameter(SpeechConstant.AUDIO_FORMAT,"wav");
        mAsr.setParameter(SpeechConstant.ASR_AUDIO_PATH, Environment.getExternalStorageDirectory()+"/msc/asr.wav");
        return result;
    }

    //獲取識別資源路徑
    private String getResourcePath(){
        StringBuffer tempBuffer = new StringBuffer();
        //識別通用資源
        tempBuffer.append(ResourceUtil.generateResourcePath(getActivity(), RESOURCE_TYPE.assets, "asr/common.jet"));
        return tempBuffer.toString();
    }

    //@Override
    //protected void onDestroy() {
    //    super.onDestroy();
    //    if( null != mAsr ){
    //        // 退出時釋放連接
    //        mAsr.cancel();
    //        mAsr.destroy();
    //    }
    //}

    private Activity _unityActivity;

    Activity getActivity(){
        if(null == _unityActivity) {
            try {
                Class<?> classtype = Class.forName("com.unity3d.player.UnityPlayer");
                Activity activity = (Activity) classtype.getDeclaredField("currentActivity").get(classtype);
                _unityActivity = activity;
            } catch (ClassNotFoundException e) {

            } catch (IllegalAccessException e) {

            } catch (NoSuchFieldException e) {

            }
        }
        return _unityActivity;
    }

    public boolean InitAsr()
    {

        mEngineType =  SpeechConstant.TYPE_LOCAL;
        StringBuffer param = new StringBuffer();
        //param.append("appid=5e4a3f32");
        param.append("appid=c8d477a3");

        param.append(",");
        // 設置使用v5+
        //param.append(SpeechConstant.ENGINE_MODE+"="+SpeechConstant.MODE_MSC);
        //2021.3.31
        param.append(SpeechConstant.ENGINE_MODE+"="+SpeechConstant.MODE_MSC);
        SpeechUtility.createUtility(getActivity(), param.toString());
        callUnity("Main Camera","FromAndroid", "構建通用組件成功");
        Context UnityContext=getActivity();
        if(UnityContext==null)
        {
            callUnity("Main Camera","FromAndroid", "UnityActivity為空");
            return  false;
        }
        mAsr = SpeechRecognizer.createRecognizer(UnityContext, mInitListener);
        if(mAsr==null){
            Log.e(TAG,"masr is null");
            callUnity("Main Camera","FromAndroid", "初始化識別引擎失敗");
            return  false;
        }
        // 初始化語法、命令詞
        mLocalLexicon = "開始\n";
        mLocalGrammar = FucUtil.readFile(getActivity(),"call.bnf", "utf-8");
        mCloudGrammar = FucUtil.readFile(getActivity(),"grammar_sample.abnf","utf-8");

        mSharedPreferences = UnityContext.getSharedPreferences(UnityContext.getPackageName(),UnityContext.MODE_PRIVATE);
        callUnity("Main Camera","FromAndroid", "初始化識別引擎成功");
        return true;
    }


    public boolean Buildsyntax(){

        mContent = new String(mLocalGrammar);
        mAsr.setParameter(SpeechConstant.PARAMS, null);
        // 設置文本編碼格式
        mAsr.setParameter(SpeechConstant.TEXT_ENCODING,"utf-8");
        // 設置引擎類型
        mAsr.setParameter(SpeechConstant.ENGINE_TYPE, mEngineType);
        // 設置語法構建路徑
        mAsr.setParameter(ResourceUtil.GRM_BUILD_PATH, grmPath);
        //2021.3.23
        // 設置本地識別使用語法id
        mAsr.setParameter(SpeechConstant.LOCAL_GRAMMAR, "call");
        // 設置識別的門限值
        mAsr.setParameter(SpeechConstant.MIXED_THRESHOLD, "30");
        //
        //使用8k音頻的時候請解開注釋
//                    mAsr.setParameter(SpeechConstant.SAMPLE_RATE, "8000");
        // 設置資源路徑
        mAsr.setParameter(ResourceUtil.ASR_RES_PATH, getResourcePath());
        ret = mAsr.buildGrammar(GRAMMAR_TYPE_BNF, mContent, grammarListener);
        if(ret != ErrorCode.SUCCESS){
            //showTip("語法構建失敗,錯誤碼:" + ret+",請點擊網址https://www.xfyun.cn/document/error-code查詢解決方案");
            callUnity("Main Camera","FromAndroid", "語法構建失敗,錯誤碼:" + ret);
            return false;
        }
        callUnity("Main Camera","FromAndroid", "構建語法完成");
        return true;
    }


    public boolean StartRecognize(){
        // 設置參數
        if (!setParam()) {
            //showTip("請先構建語法。");
            callUnity("Main Camera","FromAndroid", "請先構建語法");
            return false;
        };
        //grmPath = Environment.getExternalStorageDirectory().getAbsolutePath() + "/msc/test";
        //callUnity("Main Camera","FromAndroid", Environment.getExternalStorageDirectory()
                //.getAbsolutePath() + "/msc/test");
        ret = mAsr.startListening(mRecognizerListener);
        if (ret != ErrorCode.SUCCESS) {
            //showTip("識別失敗,錯誤碼: " + ret+",請點擊網址https://www.xfyun.cn/document/error-code查詢解決方案");
            callUnity("Main Camera","FromAndroid", "識別失敗,錯誤碼: " + ret+",請點擊網址https://www.xfyun.cn/document/error-code查詢解決方案");
            return false;
        }
        callUnity("Main Camera","FromAndroid", "請說話");
        //callUnity("Main Camera","FromAndroid", "請說話");
        return true;
    }
    //public  void Buildsyntax()
    //{
    //    mContent = new String(mLocalGrammar);
    //    mAsr.setParameter(SpeechConstant.PARAMS, null);
    //    // 設置文本編碼格式
    //    mAsr.setParameter(SpeechConstant.TEXT_ENCODING,"utf-8");
    //    // 設置引擎類型
    //    mAsr.setParameter(SpeechConstant.ENGINE_TYPE, mEngineType);
    //    // 設置語法構建路徑
    //    mAsr.setParameter(ResourceUtil.GRM_BUILD_PATH, grmPath);
    //    //使用8k音頻的時候請解開注釋
//    //                mAsr.setParameter(SpeechConstant.SAMPLE_RATE, "8000");
    //    // 設置資源路徑
    //    mAsr.setParameter(ResourceUtil.ASR_RES_PATH, getResourcePath());
    //    ret = mAsr.buildGrammar(GRAMMAR_TYPE_BNF, mContent, grammarListener);
    //    if(ret != ErrorCode.SUCCESS){
    //        showTip("語法構建失敗,錯誤碼:" + ret+",請點擊網址https://www.xfyun.cn/document/error-code查詢解決方案");
    //    }
    //}

    //public  void  StartRecognize()
    //{
    //    // 設置參數
    //    if (!setParam()) {
    //        showTip("請先構建語法。");
    //        return;
    //    };
//
    //    ret = mAsr.startListening(mRecognizerListener);
//
    //    if (ret != ErrorCode.SUCCESS) {
    //        showTip("識別失敗,錯誤碼: " + ret+",請點擊網址https://www.xfyun.cn/document/error-code查詢解決方案");
    //    }
    //}
//


    /**
     * Toast顯示unity發送過來的內容
     * @param content           消息的內容
     * @return                  調用是否成功
     */
    public boolean showToast(String content){
        Toast.makeText(getActivity(),content,Toast.LENGTH_SHORT).show();
        //這里是主動調用Unity中的方法,該方法之后unity部分會講到
        callUnity("Main Camera","FromAndroid", "hello unity i'm android");
        return true;
    }

    /**
     * 調用Unity的方法
     * @param gameObjectName    調用的GameObject的名稱
     * @param functionName      方法名
     * @param args              參數
     * @return                  調用是否成功
     */
    boolean callUnity(String gameObjectName, String functionName, String args){
        try {
            Class<?> classtype = Class.forName("com.unity3d.player.UnityPlayer");
            Method method =classtype.getMethod("UnitySendMessage", String.class,String.class,String.class);
            method.invoke(classtype,gameObjectName,functionName,args);
            return true;
        } catch (ClassNotFoundException e) {

        } catch (NoSuchMethodException e) {

        } catch (IllegalAccessException e) {

        } catch (InvocationTargetException e) {

        }
        return false;
    }

}

 

SpeechApp
package com.iflytek.mscv5plusdemo;

import android.app.Application;

import com.iflytek.cloud.SpeechConstant;
import com.iflytek.cloud.SpeechUtility;

public class SpeechApp extends Application{

    @Override
    public void onCreate() {
        // 應用程序入口處調用,避免手機內存過小,殺死后台進程后通過歷史intent進入Activity造成SpeechUtility對象為null
        // 注意:此接口在非主進程調用會返回null對象,如需在非主進程使用語音功能,請增加參數:SpeechConstant.FORCE_LOGIN+"=true"
        // 參數間使用“,”分隔。
        // 設置你申請的應用appid

        // 注意: appid 必須和下載的SDK保持一致,否則會出現10407錯誤

        StringBuffer param = new StringBuffer();
        param.append("appid="+"5d20577b");
        //param.append("appid="+getString(R.string.app_id));

        param.append(",");
        // 設置使用v5+
        param.append(SpeechConstant.ENGINE_MODE+"="+SpeechConstant.MODE_MSC);
        SpeechUtility.createUtility(SpeechApp.this, param.toString());
        super.onCreate();
    }
}

build gradle(module mscv5plusdemo)

apply plugin: 'com.android.library'
//apply plugin: 'com.android.application'
android {
    compileSdkVersion 29

    buildToolsVersion "29.0.1"
    defaultConfig {
        minSdkVersion 15
        targetSdkVersion 29
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
      //  testInstrumentationRunner "android.support.mscv5plusdemo.runner.AndroidJUnitRunner"

    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }

    sourceSets {
        main {
            jniLibs.srcDirs = ['libs']
        }
    }

    allprojects {
        repositories {

            // Msc.jar線上maven地址
            jcenter()
            mavenCentral()
        }
    }
}



dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])

    implementation 'com.android.support:appcompat-v7:28.0.0'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'com.android.support.test:runner:1.0.2'
    androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
    implementation files('libs/Msc.jar')

}

 

 

build之后,將arr包導入unity打包 報錯23108(弄了好久才解決)

 

 原因就是創建文件夾失敗,以下test文件根本找不到,沒有創建成功

 

 

解決方案如下

    /*
    private String grmPath = Environment.getExternalStorageDirectory()
            .getAbsolutePath() + "/msc/test";
            僅僅這句創建文件夾會報錯,錯誤碼23108,解決方案如下:
    但是,如果要建多層目錄的文件夾的話,可不能一蹴而就。像下面這樣寫代碼的話,執行代碼后,在Android設備的外存里是不會創建文件夾“myApp/sub”的:
String appHome = Environment.getExternalStorageDirectory().getAbsolutePath()+"/myApp";
createDir(appHome)
如果要建多層目錄的文件夾,只能是一步一步的建,如下所示:

String appHome = Environment.getExternalStorageDirectory().getAbsolutePath()+"/myApp";
String subPath = appHome+"/sub";
createDir(appHome);
createDir(subPath);
————————————————
    */
關鍵詞修改call.bnf
位置

 

 更改:(注意不能定義太多slot,否則會識別不全)

#BNF+IAT 1.0 UTF-8;
!grammar call;
!slot <keyOperation>;
!slot <keyNormal>;
!slot <keyRPV>;
!start <mainAction>;
<mainAction>:<keyOperation>|<keyNormal>|<keyRPV>;
<keyOperation>:放大|縮小|旋轉;
<keyNormal>:主泵爆炸圖|主泵還原|蒸汽發生器爆炸圖|蒸汽發生器還原|燃料組件爆炸圖|燃料組件還原;
<keyRPV>:壓力容器爆炸圖|壓力容器還原|堆內構件爆炸圖|堆內構件還原|體化堆頂結構爆炸圖|體化堆頂結構還原|支承爆炸圖|支承還原|組件吊裝|組件還原;

 

 

導出arr准備給unity使用

代碼寫好了我們選中module然后選擇「Build」「Rebuild Project」

 

接着將這個arr文件找到,就是我們要導入到unity的文件了。

導出的arr文件位置

 


unity腳本:
using UnityEngine;
using UnityEngine.UI;

public class SpeechOffline : MonoBehaviour
{

    /// <summary>
    /// 場景上的文本框用來顯示android發送過來的內容
    /// </summary>
    public Text text;

    /// <summary>
    /// android原生代碼對象
    /// </summary>
    AndroidJavaObject _ajc;

    void Start()
    {
        //通過該API來實例化導入的arr中對應的類
        _ajc = new AndroidJavaObject("com.iflytek.mscv5plusdemo.AsrDemo");
        Debug.Log("test log");
    }

    void Update()
    {

    }

    /// <summary>
    /// 場景上按點擊時觸發該方法
    /// </summary>
    public void OnBtnClick()
    {
        //通過API來調用原生代碼的方法
        bool success = _ajc.Call<bool>("InitAsr");
        if (true == success)
        {
            //請求成功
        }
    }

    public void OnBtnClick2()
    {
        //通過API來調用原生代碼的方法
        bool success = _ajc.Call<bool>("Buildsyntax");
        if (true == success)
        {
            //請求成功
        }
    }

    public void OnBtnClick3()
    {
        //通過API來調用原生代碼的方法
        bool success = _ajc.Call<bool>("StartRecognize");
        if (true == success)
        {
            //請求成功
        }
    }

    /// <summary>
    /// 原生層通過該方法傳回信息
    /// </summary>
    /// <param name="content"></param>
    public void FromAndroid(string content)
    {
        text.text = content;
    }
}

三個方法分別調用了安卓的初始化,構建語法,開始識別三個功能
_ajc = new AndroidJavaObject(“com.iflytek.mscv5plusdemo.AsrDemo”);
尤其要注意的是這行,不能獲取錯了類名,否則會報錯沒辦法運行
將打出來的aar包放在Asset/plugin/Android下,之后將該腳本懸掛至Camera上然后在場景中創建三個button來分別調用這個方法。

 ps(如果還是失敗請將手機或者AR眼鏡的對應用的存儲權限和錄音權限打開)

 (demo位置;TW/訊飛+unity+語音轉文字/unity+Android+訊飛離線命令詞語音識別)

 

講項目整合到AMglass眼鏡中,安裝成功后,初始化,構建語法、點擊開始識別,報錯23002(弄了好久才解決)

 

 由於之前在測試項目中,是成功的,現在是將demo中的內容導入AR眼鏡項目,出了問題,各種測試都不能解決問題,於是,對比兩個項目打包設置,發現在buil setting中的一個選項是問題所在,眼鏡項目build system選項是internal,將該選項改為與demo一樣的gradle就解決問題啦。

原設置:

 

 改后:

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM