Android开发Android开发经验谈Android进阶之路

VoiceTranslation项目解析

2017-03-29  本文已影响223人  tuionf

Github的地址—VoiceTranslation项目

功能

实现

思路

整体思路

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

翻译模块

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

  1. 通过网址拼接的形式来获取翻译的数据
  2. http://fanyi.youdao.com/openapi.do?keyfrom=<keyfrom>&key=<key>&type=data&doctype=<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的三个参数,

不需要参数可以传 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);  

听写回调

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 hereenter description here enter description hereenter description here
  1. 分析数据结构

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

JSONArray words = joResult.getJSONArray("ws");
enter description hereenter description here
  1. ws的目录结构
    取ws这个array 里面的第一个值
enter description hereenter description here
words.getJSONObject(i)

3.ws下第一个jsonobject的结构

enter description hereenter description here

取 cw这个数组

JSONArray items = words.getJSONObject(i).getJSONArray("cw");
  1. cw 这个数组的结构


    enter description hereenter description here

    取第一个值

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

取 key为 w 的值

obj.getString("w")

坑。。。

导包 jar 和 so文件

导包 jar

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

添加so文件

enter description hereenter description here
  1. 建立目录jniLibs
  2. 拷贝so文件进去
  3. 在该目录 enter description hereenter 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;
 }
上一篇下一篇

猜你喜欢

热点阅读