VoiceTranslation項(xiàng)目解析

Github的地址—VoiceTranslation項(xiàng)目

功能

  • 英文翻譯成中文
  • 英文語音翻譯
  • 翻譯時(shí)沒有網(wǎng)絡(luò)的提示

實(shí)現(xiàn)

思路

整體思路

  1. 使用 AsyncTask 發(fā)起網(wǎng)絡(luò)請(qǐng)求
    • .doInBackground 做真正的后臺(tái)網(wǎng)絡(luò)請(qǐng)求
    • onPostExecute 對(duì)返回的結(jié)果作處理
  2. 利用接口將請(qǐng)求的數(shù)據(jù)(翻譯的結(jié)果)返回給 UI

翻譯模塊

翻譯使用有道翻譯 的 API训堆,參考 http://fanyi.youdao.com/openapi?path=data-mode

  1. 通過網(wǎng)址拼接的形式來獲取翻譯的數(shù)據(jù)
  2. http://fanyi.youdao.com/openapi.do?keyfrom=<keyfrom>&key=<key>&type=data&doctype=<doctype>&version=1.1&q=要翻譯的文本
  3. 需要修改的地方
    1. key需要替換為自己申請(qǐng)的key 挡爵;
    2. doctype - 返回結(jié)果的數(shù)據(jù)格式西采,xml或json或jsonp,此處是json
  4. 返回碼errorCode是0 的時(shí)候表示 正常

訊飛語音接口

  1. 下載相應(yīng)的SDK,集成到項(xiàng)目中
  2. 根據(jù)文檔 http://www.xfyun.cn/doccenter/awd 調(diào)用接口

關(guān)鍵點(diǎn)

網(wǎng)絡(luò)請(qǐng)求

AsyncTask

AsyncTask的三個(gè)參數(shù)肛捍,

  • Params 啟動(dòng)任務(wù)執(zhí)行的輸入?yún)?shù),比如HTTP請(qǐng)求的URL————決定了doInBackground方法、execute方法的參數(shù)類型
  • Progress 后臺(tái)任務(wù)執(zhí)行的百分比————決定了publishProgress方法耳高、onProgressUpdate方法的參數(shù)類型
  • Result 后臺(tái)執(zhí)行任務(wù)最終返回的結(jié)果,比如String,Integer等————決定了doInBackground方法的返回值類型所踊、onPostExecute方法的參數(shù)類型

不需要參數(shù)可以傳 void泌枪,此處 doInBackground方法 執(zhí)行后臺(tái)翻譯的網(wǎng)絡(luò)請(qǐng)求,所以參數(shù)類型是 String 秕岛,返回的結(jié)果也是 String 類型碌燕,在onPostExecute中處理返回的結(jié)果误证,第二個(gè)參數(shù)百分比目前不需要,設(shè)置為void

HttpURLConnection

//執(zhí)行網(wǎng)絡(luò)請(qǐng)求
            URL url = null;
            HttpURLConnection httpURLConnection = null;
            BufferedReader reader = null;
            StringBuilder response = new StringBuilder();

            try {
                url = new URL(params[0]);

                Log.e(TAG,"網(wǎng)絡(luò)請(qǐng)求鏈接-----"+url.toString());

                httpURLConnection = (HttpURLConnection) url.openConnection();
                httpURLConnection.setRequestMethod("GET");
                httpURLConnection.setConnectTimeout(5000);
                httpURLConnection.setReadTimeout(5000);

                InputStream is = httpURLConnection.getInputStream();
                reader = new BufferedReader(new InputStreamReader(is));

                Log.e(TAG,"網(wǎng)絡(luò)請(qǐng)求-----"+httpURLConnection.getResponseCode());

                String line ;
                while ((line = reader.readLine()) != null){
                    response.append(line);
                }

            } catch (Exception e) {
                e.printStackTrace();
            }finally {
                if (reader != null) {
                    try {
                        reader.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }

                if (httpURLConnection != null) {
                    httpURLConnection.disconnect();
                }

請(qǐng)求結(jié)果與UI交互

onPostExecute中來處理返回的結(jié)果
與UI交互修壕,利用接口

@Override
        protected void onPostExecute(String s) {
            super.onPostExecute(s);
            if (s != null) {
                onResponseListener.onSuccess(s);
            }
        }

回調(diào)接口

public interface onResponseListener{
        void onSuccess(String result);
        void onFail(String error);
    }

網(wǎng)絡(luò)請(qǐng)求實(shí)例寫成單例

public static HttpUtil getInstance() {
        if (mHttpUtil == null) {
            synchronized (HttpUtil.class){
                if (mHttpUtil == null) {
                    mHttpUtil = new HttpUtil();
                }
            }
        }
        return mHttpUtil;
    }

語音識(shí)別

初始化

  1. 在OnCreate方法中初始化
SpeechUtility.createUtility(context, SpeechConstant.APPID +"=APPID");   
  1. 創(chuàng)建SpeechRecognizer對(duì)象
SpeechRecognizer mIat = SpeechRecognizer.createRecognizer(MainActivity.this,mInitListener);

    /**
     * 初始化監(jiān)聽器愈捅。
     */
    private InitListener mInitListener = new InitListener() {

        @Override
        public void onInit(int code) {

            if (code != ErrorCode.SUCCESS) {
                Toast.makeText(MainActivity.this, "初始化失敗,錯(cuò)誤碼:" + code, Toast.LENGTH_SHORT).show();
            }
        }
    };
  1. 設(shè)置參數(shù)
public void setParam() {
        // 清空參數(shù)
        mIat.setParameter(SpeechConstant.PARAMS, null);

        // 設(shè)置聽寫引擎
        mIat.setParameter(SpeechConstant.ENGINE_TYPE, mEngineType);
        // 設(shè)置返回結(jié)果格式
        mIat.setParameter(SpeechConstant.RESULT_TYPE, "json");
        // 設(shè)置語言
        mIat.setParameter(SpeechConstant.LANGUAGE, "en_us");
        // 設(shè)置音頻保存路徑慈鸠,保存音頻格式支持pcm蓝谨、wav,設(shè)置路徑為sd卡請(qǐng)注意WRITE_EXTERNAL_STORAGE權(quán)限
        // 注:AUDIO_FORMAT參數(shù)語記需要更新版本才能生效
        mIat.setParameter(SpeechConstant.AUDIO_FORMAT,"wav");
        mIat.setParameter(SpeechConstant.ASR_AUDIO_PATH, Environment.getExternalStorageDirectory()+"/msc/iat.wav");
    }

4.開始聽寫

mIat.startListening(mRecoListener);  

聽寫回調(diào)

  • 聽寫結(jié)果回調(diào)接口(返回Json格式結(jié)果
  • 一般情況下會(huì)通過onResults接口多次返回結(jié)果青团,完整的識(shí)別內(nèi)容是多次結(jié)果的累加譬巫;
  • 關(guān)于解析Json的代碼可參見MscDemo中JsonParser類;
  • isLast等于true時(shí)會(huì)話結(jié)束
private RecognizerListener mRecoListener = new RecognizerListener() {
        //音量值0~30
        @Override
        public void onVolumeChanged(int i, byte[] bytes) {
//            Toast.makeText(MainActivity.this, "音量:" + i, Toast.LENGTH_SHORT).show();
        }

        //開始錄音
        @Override
        public void onBeginOfSpeech() {
//            Toast.makeText(MainActivity.this, "開始錄音" , Toast.LENGTH_SHORT).show();
        }

        //結(jié)束錄音
        @Override
        public void onEndOfSpeech() {
//            Toast.makeText(MainActivity.this, "結(jié)束錄音" , Toast.LENGTH_SHORT).show();
            mIatDialog.dismiss();
        }

        //一般情況下會(huì)通過onResults接口多次返回結(jié)果壶冒,完整的識(shí)別內(nèi)容是多次結(jié)果的累加
        @Override
        public void onResult(RecognizerResult recognizerResult, boolean isLast) {
            printResult(recognizerResult);
            Log.d("Result:",recognizerResult.getResultString ());
        }

        //會(huì)話發(fā)生錯(cuò)誤回調(diào)接口
        @Override
        public void onError(SpeechError speechError) {
        }

        //擴(kuò)展用接口
        @Override
        public void onEvent(int i, int i1, int i2, Bundle bundle) {

        }
    };

語音返回?cái)?shù)據(jù)處理

數(shù)據(jù)格式-json

enter description here
enter description here
enter description here
enter description here
  1. 分析數(shù)據(jù)結(jié)構(gòu)

需要的數(shù)據(jù)在 ws 這個(gè)array下缕题,先去這個(gè)array

JSONArray words = joResult.getJSONArray("ws");
enter description here
enter description here
  1. ws的目錄結(jié)構(gòu)
    取ws這個(gè)array 里面的第一個(gè)值
enter description here
enter description here
words.getJSONObject(i)

3.ws下第一個(gè)jsonobject的結(jié)構(gòu)

enter description here
enter description here

取 cw這個(gè)數(shù)組

JSONArray items = words.getJSONObject(i).getJSONArray("cw");
  1. cw 這個(gè)數(shù)組的結(jié)構(gòu)


    enter description here
    enter description here

    取第一個(gè)值

JSONObject obj = items.getJSONObject(0);
enter description here
enter description here

取 key為 w 的值

obj.getString("w")

坑。胖腾。烟零。

導(dǎo)包 jar 和 so文件

導(dǎo)包 jar

enter description here
enter description here
  1. 按照上圖創(chuàng)建libs目錄
  2. 拷貝jar包到libs下
  3. 選中jar包,右鍵
enter description here
enter description here
  1. enter description here
    enter description here

添加so文件

enter description here
enter description here
  1. 建立目錄jniLibs
  2. 拷貝so文件進(jìn)去
  3. 在該目錄
    enter description here
    enter description here

    中的android添加
    sourceSets { main { jni.srcDirs = ['src/main/jni', 'src/main/jniLibs'] }

android {
    compileSdkVersion 25
    buildToolsVersion "25.0.2"
     .....
    sourceSets { main { jni.srcDirs = ['src/main/jni', 'src/main/jniLibs'] } }
}

網(wǎng)絡(luò)權(quán)限

開發(fā)過程中咸作,打包完成之后訊飛在錄音時(shí)報(bào)錯(cuò)锨阿,進(jìn)行排查

  1. 檢查需要的錄音權(quán)限是否申請(qǐng)——已申請(qǐng)
  2. 檢查是否有其他程序占用麥克風(fēng)——無
  3. 重啟手機(jī)——重啟之后還是不行

最后發(fā)現(xiàn)應(yīng)用安裝在手機(jī)上之后手機(jī)沒有給應(yīng)用權(quán)限

小技巧

快捷鍵

Ctrl+F3 跳轉(zhuǎn)到下一個(gè)相同變量——向下搜索
Shift+F3 跳轉(zhuǎn)到上一個(gè)相同變量——向上搜索
Ctrl+F12 查看類中所有的參數(shù)和方法

每次設(shè)置參數(shù)或者給Edittext內(nèi)容之前都應(yīng)該先清空內(nèi)容

第三方引入的庫中對(duì)象的初始化在使用前應(yīng)該首先判斷是否為空,并彈框提示记罚,方便定位問題墅诡。

if( null == mIat )
{ // 創(chuàng)建單例失敗
          Toast.makeText(this, "創(chuàng)建對(duì)象失敗,請(qǐng)確認(rèn) libmsc.so 放置正確桐智,且有調(diào)用 createUtility 進(jìn)行初始化" , Toast.LENGTH_SHORT).show();
         return;
 }
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末末早,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子说庭,更是在濱河造成了極大的恐慌然磷,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,826評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件刊驴,死亡現(xiàn)場(chǎng)離奇詭異姿搜,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)捆憎,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,968評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門舅柜,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人躲惰,你說我怎么就攤上這事致份。” “怎么了础拨?”我有些...
    開封第一講書人閱讀 164,234評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵知举,是天一觀的道長(zhǎng)瞬沦。 經(jīng)常有香客問我,道長(zhǎng)雇锡,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,562評(píng)論 1 293
  • 正文 為了忘掉前任僚焦,我火速辦了婚禮锰提,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘芳悲。我一直安慰自己立肘,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,611評(píng)論 6 392
  • 文/花漫 我一把揭開白布名扛。 她就那樣靜靜地躺著谅年,像睡著了一般。 火紅的嫁衣襯著肌膚如雪肮韧。 梳的紋絲不亂的頭發(fā)上融蹂,一...
    開封第一講書人閱讀 51,482評(píng)論 1 302
  • 那天,我揣著相機(jī)與錄音弄企,去河邊找鬼超燃。 笑死,一個(gè)胖子當(dāng)著我的面吹牛拘领,可吹牛的內(nèi)容都是我干的意乓。 我是一名探鬼主播,決...
    沈念sama閱讀 40,271評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼约素,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼届良!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起圣猎,我...
    開封第一講書人閱讀 39,166評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤士葫,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后样漆,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體为障,經(jīng)...
    沈念sama閱讀 45,608評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,814評(píng)論 3 336
  • 正文 我和宋清朗相戀三年放祟,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了鳍怨。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,926評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡跪妥,死狀恐怖鞋喇,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情眉撵,我是刑警寧澤侦香,帶...
    沈念sama閱讀 35,644評(píng)論 5 346
  • 正文 年R本政府宣布落塑,位于F島的核電站,受9級(jí)特大地震影響罐韩,放射性物質(zhì)發(fā)生泄漏憾赁。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,249評(píng)論 3 329
  • 文/蒙蒙 一散吵、第九天 我趴在偏房一處隱蔽的房頂上張望龙考。 院中可真熱鬧,春花似錦矾睦、人聲如沸晦款。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,866評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽缓溅。三九已至,卻和暖如春赁温,著一層夾襖步出監(jiān)牢的瞬間坛怪,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,991評(píng)論 1 269
  • 我被黑心中介騙來泰國(guó)打工束世, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留酝陈,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,063評(píng)論 3 370
  • 正文 我出身青樓毁涉,卻偏偏與公主長(zhǎng)得像沉帮,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子贫堰,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,871評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容

  • Android開發(fā)者:你真的會(huì)用AsyncTask嗎穆壕? 導(dǎo)讀.1 在Android應(yīng)用開發(fā)中,我們需要時(shí)刻注意保證...
    cxm11閱讀 2,709評(píng)論 0 29
  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,124評(píng)論 25 707
  • “你是女生川背,那么拼干嘛?”回國(guó)后總被問到這句話蛤袒。 而每次被問到熄云,我都不知道怎么回答。誠(chéng)心實(shí)意回答吧妙真,被認(rèn)為作缴允,隨便...
    曹小力閱讀 982評(píng)論 6 5
  • wenwen7446閱讀 148評(píng)論 0 0
  • 轉(zhuǎn)載 1個(gè)月內(nèi):出生一周,寶寶的視力趨向于近視珍德,可以把視力集中于8至15厘米遠(yuǎn)的物體上练般,還能夠用眼追隨移動(dòng)的物體矗漾。...
    上進(jìn)青年歡樂多閱讀 387評(píng)論 0 0