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

时间:2024-03-08 18:39:29

引言  

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

  项目中使用的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