VoiceTranslation项目解析

Github的地址—VoiceTranslation项目

功能

  • 英文翻译成中文
  • 英文语音翻译
  • [x] 翻译时没有网络的提示

实现

思路

整体思路

  1. 使用 AsyncTask 发起网络请求
    • .doInBackground 做真正的后台网络请求
    • onPostExecute 对返回的结果作处理
  2. 利用接口将请求的数据(翻译的结果)返回给 UI

翻译模块

翻译使用有道翻译 的 API,参考 http://fanyi.youdao.com/openapi?path=data-mode

  1. 通过网址拼接的形式来获取翻译的数据
  2. http://fanyi.youdao.com/openapi.do?keyfrom=&key=&type=data&doctype=&version=1.1&q=要翻译的文本
  3. 需要修改的地方
    1. key需要替换为自己申请的key ;
    2. doctype - 返回结果的数据格式,xml或json或jsonp,此处是json
  4. 返回码errorCode是0 的时候表示 正常

讯飞语音接口

  1. 下载相应的SDK,集成到项目中
  2. 根据文档 http://www.xfyun.cn/doccenter/awd 调用接口

关键点

网络请求

AsyncTask

AsyncTask的三个参数,
- Params 启动任务执行的输入参数,比如HTTP请求的URL————决定了doInBackground方法、execute方法的参数类型
- Progress 后台任务执行的百分比————决定了publishProgress方法、onProgressUpdate方法的参数类型
- Result 后台执行任务最终返回的结果,比如String,Integer等————决定了doInBackground方法的返回值类型、onPostExecute方法的参数类型

不需要参数可以传 void,此处 doInBackground方法 执行后台翻译的网络请求,所以参数类型是 String ,返回的结果也是 String 类型,在onPostExecute中处理返回的结果,第二个参数百分比目前不需要,设置为void

HttpURLConnection

//执行网络请求
            URL url = null;
            HttpURLConnection httpURLConnection = null;
            BufferedReader reader = null;
            StringBuilder response = new StringBuilder();

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

                Log.e(TAG,"网络请求链接-----"+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,"网络请求-----"+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();
                }

请求结果与UI交互

onPostExecute中来处理返回的结果
与UI交互,利用接口

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

回调接口

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

网络请求实例写成单例

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

语音识别

初始化

  1. 在OnCreate方法中初始化
SpeechUtility.createUtility(context, SpeechConstant.APPID +"=APPID");   
  1. 创建SpeechRecognizer对象
SpeechRecognizer mIat = SpeechRecognizer.createRecognizer(MainActivity.this,mInitListener);

    /**
     * 初始化监听器。
     */
    private InitListener mInitListener = new InitListener() {

        @Override
        public void onInit(int code) {

            if (code != ErrorCode.SUCCESS) {
                Toast.makeText(MainActivity.this, "初始化失败,错误码:" + code, Toast.LENGTH_SHORT).show();
            }
        }
    };
  1. 设置参数
public void setParam() {
        // 清空参数
        mIat.setParameter(SpeechConstant.PARAMS, null);

        // 设置听写引擎
        mIat.setParameter(SpeechConstant.ENGINE_TYPE, mEngineType);
        // 设置返回结果格式
        mIat.setParameter(SpeechConstant.RESULT_TYPE, "json");
        // 设置语言
        mIat.setParameter(SpeechConstant.LANGUAGE, "en_us");
        // 设置音频保存路径,保存音频格式支持pcm、wav,设置路径为sd卡请注意WRITE_EXTERNAL_STORAGE权限
        // 注:AUDIO_FORMAT参数语记需要更新版本才能生效
        mIat.setParameter(SpeechConstant.AUDIO_FORMAT,"wav");
        mIat.setParameter(SpeechConstant.ASR_AUDIO_PATH, Environment.getExternalStorageDirectory()+"/msc/iat.wav");
    }

4.开始听写

mIat.startListening(mRecoListener);  

听写回调

  • 听写结果回调接口(返回Json格式结果
  • 一般情况下会通过onResults接口多次返回结果,完整的识别内容是多次结果的累加;
  • 关于解析Json的代码可参见MscDemo中JsonParser类;
  • isLast等于true时会话结束
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();
        }

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

        //一般情况下会通过onResults接口多次返回结果,完整的识别内容是多次结果的累加
        @Override
        public void onResult(RecognizerResult recognizerResult, boolean isLast) {
            printResult(recognizerResult);
            Log.d("Result:",recognizerResult.getResultString ());
        }

        //会话发生错误回调接口
        @Override
        public void onError(SpeechError speechError) {
        }

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

        }
    };

语音返回数据处理

数据格式-json

enter description here

enter description here

  1. 分析数据结构

需要的数据在 ws 这个array下,先去这个array

JSONArray words = joResult.getJSONArray("ws");

enter description here

  1. ws的目录结构
    取ws这个array 里面的第一个值

enter description here

words.getJSONObject(i)

3.ws下第一个jsonobject的结构

enter description here

取 cw这个数组

JSONArray items = words.getJSONObject(i).getJSONArray("cw");
  1. cw 这个数组的结构
    enter description here
    取第一个值
JSONObject obj = items.getJSONObject(0);

enter description here

取 key为 w 的值

obj.getString("w")

坑。。。

导包 jar 和 so文件

导包 jar

enter description here
1. 按照上图创建libs目录
2. 拷贝jar包到libs下
3. 选中jar包,右键

enter description here

  1. enter description here

添加so文件

enter description here
1. 建立目录jniLibs
2. 拷贝so文件进去
3. 在该目录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'] } }
}

网络权限

开发过程中,打包完成之后讯飞在录音时报错,进行排查
1. 检查需要的录音权限是否申请——已申请
2. 检查是否有其他程序占用麦克风——无
3. 重启手机——重启之后还是不行

最后发现应用安装在手机上之后手机没有给应用权限

小技巧

快捷键

Ctrl+F3 跳转到下一个相同变量——向下搜索
Shift+F3 跳转到上一个相同变量——向上搜索
Ctrl+F12 查看类中所有的参数和方法

每次设置参数或者给Edittext内容之前都应该先清空内容

第三方引入的库中对象的初始化在使用前应该首先判断是否为空,并弹框提示,方便定位问题。

if( null == mIat )
{ // 创建单例失败
          Toast.makeText(this, "创建对象失败,请确认 libmsc.so 放置正确,且有调用 createUtility 进行初始化" , Toast.LENGTH_SHORT).show();
         return;
 }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值