• Android中谷歌语音识别应用探究


    引言  

      由于为期半年的项目结束了,进入了一段“疗养”的真空期,因此有时间可以去归纳整理项目的经验,学习新的姿势与技巧,对自己技术水平也是一种提升。另外,个人懒癌症严重,为强迫自己努力学习,立了一些福来阁(比如没有写出博客女装什么的咳咳,我一定会拔旗成功的,哼),总体来说督促效果还是挺不错的。

      项目中使用的Android和linux进行客户端的开发,结合项目的实战经验,七月份写的博客内容主要围绕Android开发进行,研究的内容预定为:Android中谷歌语音搜索功能探究(开篇),app应用意外关闭后MediaPlayer进行断点播放(预计两到三章左右)

      为何选择Android谷歌语音搜索作为第一篇正式的博文?第一实现功能较为简单,代码量很小,可以为后续的文章热热身;第二语音搜索这个功能强大的,尤其是谷歌作为IT巨头,语音搜索体感非常棒,识别快而精准。谷歌的语音搜索可以广泛应用与基于LBS的Android应用程序中,调用谷歌api获取搜索结果,然后根据这个结果做自己想要的功能。

      言归正传,下面开始正式介绍谷歌的语音搜索。

     谷歌语音搜索基础

       语音识别是Google在API Level3,也就是SDK1.5中引入的。根据官方的SDK的资料,语音检索的模式行为(action)有4种:

          ACTION_GET_LANGUAGE_DETAILS           --->   API Level8引入

          ACTION_RECOGNIZE_SPEECH                        --->   API Level3引入

          ACTION_VOICE_SEARCH_HANDS_FREE                   --->   API Level16引入

          ACTION_WEB_SEARCH                        --->   API Level3引入

      大致的功能为:

      ACTION_GET_LANGUAGE_DETAILS:一个广播性质的intent,用于获取meta-data, 不常用。

      ACTION_RECOGNIZE_SPEECH:起一个activity将用户所说的内容发送至语音识别器,结果将会从onActivityResult中返回。(注: 官方不再支持startActivity的方式起intent, 改为startActivityResult)。该部分是核心功能。

      ACTION_VOICE_SEARCH_HANDS_FREE:API16中新引入的功能,不常用,目的是让用户在不使用客户端的情况下也能进行语音搜索,例如处于锁屏的安全模式中。如果要想使用该模式必须在manifest中加入如下:

    1 <action android:name="android.speech.action.VOICE_SEARCH_HANDS_FREE" />

      ACTION_WEB_SEARCH:通过Web网络检索来实现。

       自定义设置项(Option)主要有以下3个:

      EXTRA_LANGUAGE_MODEL:语音识别的语言设置

      EXTRA_PROMPT: 语音输入时显示的提示文字

      EXTRA_MAX_RESULTS: 语音搜索结果最大值设定

       此外需要注意一点,在没有谷歌服务的地区是不能进行谷歌语音服务的,括弧笑。而且手机不支持语音搜索的话,本地需要预先安装一个语音包:Voice_Search_2.1.4.apk, 这个版本非常老,2011年出的一直没有更新,原生态的皮肤令人怀念。如果没有在google-market中下载到,可以到如下网址下载:

      http://www.coolapk.com/apk/com.google.android.voicesearch

     谷歌语音搜索的实现

      实现的方法可以概括为以下四步:

      1 起一个名为RecognizerIntent的Intent活动

      2 putExtra中填入语音搜索的常量设定

      3 startActivityResult

      4 onActivityResult等待搜索结果。

     核心代码示例:

      添加一个RadiaGroup, 设置3种常用的语音搜索模式。

    <RadioGroup
    
            android:id="@+id/search_group"
    
            android:orientation="vertical"
    
            android:layout_marginLeft="90dp"
    
            android:layout_width="wrap_content"
    
            android:layout_height="wrap_content">
    
            <RadioButton
    
                android:checked="true"
    
                android:text="ACTION_RECOGNIZE_SPEECH"
    
                android:layout_width="wrap_content"
    
                android:layout_height="wrap_content" />
    
     
    
            <RadioButton
    
                android:text="ACTION_WEB_SEARCH"
    
                android:layout_width="wrap_content"
    
                android:layout_height="wrap_content" />
    
     
    
            <RadioButton
    
                android:text="ACTION_VOICE_SEARCH_HANDS_FREE"
    
                android:layout_width="wrap_content"
    
                android:layout_height="wrap_content" />
    
        </RadioGroup>

      在MainActivity中获取RadioGroup所选的内容,代码如下

     1 private String getRecognizerMode() {
     2 
     3         for (int i=0; i<radioBtn.getChildCount(); i++) {
     4 
     5             RadioButton btn = (RadioButton) radioBtn.getChildAt(i);
     6 
     7             if (btn.isChecked()) {
     8 
     9                 if (btn.getText().equals(RecognizerIntent.ACTION_RECOGNIZE_SPEECH)) {
    10 
    11                     return RecognizerIntent.ACTION_RECOGNIZE_SPEECH;
    12 
    13                 } else if (btn.getText().equals(RecognizerIntent.ACTION_WEB_SEARCH)) {
    14 
    15                     return RecognizerIntent.ACTION_WEB_SEARCH;
    16 
    17                 } else if (btn.getText().equals(RecognizerIntent.ACTION_VOICE_SEARCH_HANDS_FREE)) {
    18 
    19                     return RecognizerIntent.ACTION_VOICE_SEARCH_HANDS_FREE;
    20 
    21                 }
    22 
    23                 else {
    24 
    25                     return null;
    26 
    27                 }
    28 
    29             }
    30 
    31         }
    32 
    33         return null;
    34 
    35 }

      然后是点击语音按钮后,执行startVoiceRecognition这个方法起intent操作

     1 private void startVoiceRecognition(String mode) {
     2 
     3         try {
     4 
     5             Intent intent = new Intent(mode);
     6 
     7             intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL,
     8 
     9                     RecognizerIntent.LANGUAGE_MODEL_FREE_FORM);
    10 
    11             intent.putExtra(RecognizerIntent.EXTRA_PROMPT, R.string.voice_begin);
    12 
    13             intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE, "zh-HK");
    14 
    15             startActivityForResult(intent, VOICE_RECOGNITION_REQUEST_CODE);
    16 
    17         } catch (Exception e) {
    18 
    19             e.printStackTrace();
    20 
    21             Toast.makeText(this, "No Google Voice app, plz download.", Toast.LENGTH_SHORT).show();
    22 
    23         }
    24 
    25     }

             在测试中发现,语音搜索所识别的内容依赖于机器的系统环境,如果是中文系统识别出的是中文的搜索内容,如果是日文系统的则是日文的搜索内容。RecognizerIntent.EXTRA_LANGUAGE这个属性似乎没有什么乱用。

             最后是onActivityResult回调结果部分

     protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    
            super.onActivityResult(requestCode, resultCode, data);
    
            Log.d("lsy", "onActivityResult --> requestCode: " + requestCode + " resultCode: " + resultCode);
    
            if (requestCode == VOICE_RECOGNITION_REQUEST_CODE && resultCode == RESULT_OK) {
    
                ArrayList<String > results = data.getStringArrayListExtra(RecognizerIntent.EXTRA_RESULTS);
    
                if (results.size() > 0) {
    
                    String result = results.get(0).toString().trim();
    
                    if (null != result && result.length() > 0) {
    
                        searchResult.setText(result);
    
    //                    获取所有检索结果
    
    //                    for (String str : results) {
    
    //                        searchResult.append(str + "/n");
    
    //                    }
    
                    } else {
    
                        Toast.makeText(this, "Voice Content Fail", Toast.LENGTH_SHORT).show();
    
                    }
    
                } else {
    
                    Log.d("lsy", "onActivityResult --> Voice Content Fail");
    
                    Toast.makeText(this, "Voice Content Fail", Toast.LENGTH_SHORT).show();
    
                }
    
     
    
            }
    
        }

             所有搜索的结果保存在一个ArrayList的列表中,第一个数据是匹配值最高,代码中因为需要拿最匹配的值去做地图搜索才会选择第一个数据。注释部分可以打印出所有满足搜索条件的值。

    总结

             谷歌的语音搜索可以帮助我们实现在LBS类应用中进行语音定位,其搜索精度高,速度快,只是不可描述的存在限制了这个好用的功能,很是可惜。后续基于谷歌语音开发的内容可以包括:历史语音搜索记录、语音联想功能、与自主开发导航软件的协同工作等,由于时间仓促没有来的及实现,有兴趣的朋友可以实验下。

             本文对网上关于谷歌语音搜索的文章进行总结和部分拓展,做了点微小的贡献,甚是惭愧。

    参考博文

    http://blog.csdn.net/h7870181/article/details/11151773

    http://blog.csdn.net/gumanren/article/details/6771265

  • 相关阅读:
    Redis5设计与源码分析 (第17章 HyperLogLog相关命令的实现)
    Redis5设计与源码分析 (第16章 GEO相关命令)
    ES5和ES6函数的this指向
    vue响应式原理 (响应式并不等于数据双向绑定,千万不要混淆)
    vue中data为什么是函数而不是对象
    vue-enum 前端常量 枚举工具
    Vue3 写业务逻辑不适合用TS(TypeScript)
    vue-property-decorator vue3 ts 用的装饰器
    github git clone下载加速 && npm install 下载加速
    vue3 如果用ts,导出时候要用 defineComponent,这俩是配对的,为了类型的审查正确
  • 原文地址:https://www.cnblogs.com/yessirpopesama/p/5658458.html
Copyright © 2020-2023  润新知