Android 科大讯飞语音识别 金额数字

最近要在应用里面使用语音识别功能,老板选择了科大讯飞的技术,小可也就开始看文档啦;

这里只嵌入了语音识别,其他的语法什么的没有研究,有需要的各位看文档呗;

需要的资料 :只识别数字,若不过滤则把LSpeechManager中的onResult方法中的LDataFormat过滤去掉即可

1,首先要在科大讯飞开放平台注册开发者,并注册应用,然后下载SDK;

      http://open.voicecloud.cn/index.php/default/index

2,语音识别需要的文件:

      (1)Msc.jar

      (2)libmsc.so

3,需要的权限 :

     

[html]  view plain copy
  1.   
  2. <uses-permission android:name="android.permission.INTERNET" />  
  3.   
  4. <uses-permission android:name="android.permission.RECORD_AUDIO" />  
  5.   
  6. <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />  
  7. <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />  
  8. <uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />  
  9.   
  10. <uses-permission android:name="android.permission.READ_PHONE_STATE" />  
4,需要自己的Application,并在其中初始化语音识别

   

[html]  view plain copy
  1. public class Lapp extends Application {  
  2.     @Override  
  3.     public void onCreate() {  
  4.         // 应用程序入口处调用,避免手机内存过小,杀死后台进程,造成SpeechUtility对象为null  
  5.         // 设置你申请的应用appid  
  6.         SpeechUtility.createUtility(Lapp.this, "appid=5486584a");  
  7.         super.onCreate();  
  8.     }  
  9. }  

5,语音识别  (使用该类可以直接调用start()方法进行语音听写识别)

[java]  view plain copy
  1. /** 
  2.  * 语音识别管理类 
  3.  *  
  4.  * @author li'mingqi 
  5.  *  
  6.  */  
  7. public class LSpeechManager {  
  8.     private Context mContext;  
  9.     // 语音听写  
  10.     private SpeechRecognizer mIat;  
  11.     // handler  
  12.     private Handler mHandler;  
  13.     // 识别结果  
  14.     private LSpeechResultListener resultListener;  
  15.     // 识别成功  
  16.     public static final int SPEECH_SUCCESS = 0;  
  17.     // 识别失败  
  18.     public static final int SPEECH_FAIL = -1;  
  19.     // 开始识别  
  20.     public static final int SPEECH_START = 1;  
  21.     // 识别出错  
  22.     public static final int SPEECH_ERROR = 2;  
  23.   
  24.     /** 
  25.      *  
  26.      */  
  27.     @SuppressLint("HandlerLeak")  
  28.     public LSpeechManager(Context context) {  
  29.         this.mContext = context;  
  30.         // 语音听写部分  
  31.         // 创建SpeechRecognizer对象  
  32.         mIat = SpeechRecognizer.createRecognizer(this.mContext, null);  
  33.         // 设置听写参数  
  34.         // 应用领域 --语音识别  
  35.         mIat.setParameter(SpeechConstant.DOMAIN, "iat");  
  36.         // 语言--中文  
  37.         mIat.setParameter(SpeechConstant.LANGUAGE, "zh_cn");  
  38.         // mandarin 普通话 cantonese广东话  
  39.         mIat.setParameter(SpeechConstant.ACCENT, "mandarin");  
  40.         // 客户端引擎选择模式 --云端msc  
  41.         mIat.setParameter(SpeechConstant.ENGINE_MODE, "msc");  
  42.         // 客户端引擎类型 --云端msc  
  43.         mIat.setParameter(SpeechConstant.ENGINE_TYPE, SpeechConstant.TYPE_CLOUD);  
  44.         // 数据解码方式 --utf-8  
  45.         mIat.setParameter(SpeechConstant.TEXT_ENCODING, "utf-8");  
  46.         // 初始化听写Dialog,如果只使用有UI听写功能,无需创建SpeechRecognizer  
  47.         mHandler = new Handler() {  
  48.             @Override  
  49.             public void handleMessage(Message msg) {  
  50.                 super.handleMessage(msg);  
  51.                 int what = msg.what;  
  52.                 switch (what) {  
  53.                 case SPEECH_SUCCESS:// 识别成功  
  54.                     String result = (String) msg.obj;  
  55.                     if (null != resultListener) {  
  56.                         resultListener.onSuccess(result);  
  57.                     }  
  58.                     break;  
  59.   
  60.                 case SPEECH_FAIL:// 识别失败  
  61.                     Toast.makeText(mContext, "请将金额数字按普通话讲出", Toast.LENGTH_SHORT)  
  62.                             .show();  
  63.                     break;  
  64.   
  65.                 case SPEECH_START://开始识别  
  66.                     if (null != resultListener) {  
  67.                         resultListener.onStart();  
  68.                     }  
  69.                     break;  
  70.                 case SPEECH_ERROR://识别出错  
  71.                     if (null != resultListener) {  
  72.                         String error = (String) msg.obj;  
  73.                         resultListener.onError(error);  
  74.                     }  
  75.                     break;  
  76.                 }  
  77.             }  
  78.         };  
  79.     }  
  80.   
  81.     public void start() {  
  82.         final StringBuilder sb = new StringBuilder();  
  83.         // 开始听写  
  84.         mIat.startListening(new RecognizerListener() {  
  85.   
  86.             @Override  
  87.             public void onVolumeChanged(int arg0) {  
  88.                 // 音量值变化  
  89.             }  
  90.   
  91.             @Override  
  92.             public void onResult(RecognizerResult msg, boolean arg1) {  
  93.                 // 一般情况下会通过onResults接口多次返回结果,完整的识别内容是多次结果的累加;  
  94.                 // 关于解析Json的代码可参见MscDemo中JsonParser类;  
  95.                 // isLast等于true时会话结束。  
  96.                 /*** 
  97.                  * 结果--{"sn":1,"ls":false,"bg":0,"ed":0,"ws":[{"bg":0,"cw":[ 
  98.                  * {"w":"两百","sc":0.00}]}]} 
  99.                  * 结果--{"sn":2,"ls":true,"bg":0,"ed":0,"ws" 
  100.                  * :[{"bg":0,"cw":[{"w":"。","sc":0.00}]}]} 
  101.                  */  
  102.                 try {  
  103.                     JSONObject mRsult = new JSONObject(msg.getResultString());  
  104.                     if (!mRsult.getBoolean("ls")) {  
  105.                         JSONArray data = mRsult.getJSONArray("ws");  
  106.                         for (int i = 0; i < data.length(); i++) {  
  107.                             JSONObject w = data.getJSONObject(i);  
  108.                             JSONArray array = w.getJSONArray("cw");  
  109.                             for (int k = 0; k < array.length(); k++) {  
  110.                                 JSONObject cwdata = array.getJSONObject(k);  
  111.                                 sb.append(cwdata.getString("w"));  
  112.                             }  
  113.                         }  
  114.                     } else {  
  115.                         mIat.stopListening();  
  116.                         String money = LDataFormat.format(sb.toString());  
  117.                         if ("".equals(money) || null == money  
  118.                                 || "0".equals(money)) {  
  119.                             Message msgs = mHandler.obtainMessage();  
  120.                             msgs.what = SPEECH_FAIL;  
  121.                             mHandler.sendMessage(msgs);  
  122.                         } else {  
  123.                             Message msgs = mHandler.obtainMessage();  
  124.                             msgs.what = SPEECH_SUCCESS;  
  125.                             msgs.obj = money;  
  126.                             mHandler.sendMessage(msgs);  
  127.                         }  
  128.                     }  
  129.                 } catch (JSONException e) {  
  130.                     e.printStackTrace();  
  131.                 }  
  132.             }  
  133.   
  134.             @Override  
  135.             public void onEvent(int arg0, int arg1, int arg2, Bundle arg3) {  
  136.                 // 扩展类回调  
  137.             }  
  138.   
  139.             @Override  
  140.             public void onError(SpeechError error) {  
  141.                 // 回话发生错误时回调的函数  
  142.                 String merror = error.getPlainDescription(true);// 获取错误码描述  
  143.                 Message msg=mHandler.obtainMessage();  
  144.                 msg.what=SPEECH_ERROR;  
  145.                 msg.obj=merror;  
  146.                 mHandler.sendMessage(msg);  
  147.             }  
  148.   
  149.             @Override  
  150.             public void onEndOfSpeech() {  
  151.                 // 结束录音  
  152.             }  
  153.   
  154.             @Override  
  155.             public void onBeginOfSpeech() {  
  156.                 // 开始录音  
  157.                 Message msg=mHandler.obtainMessage();  
  158.                 msg.what=SPEECH_START;  
  159.                 mHandler.sendMessage(msg);  
  160.             }  
  161.         });  
  162.     }  
  163.   
  164.     /**识别回调 
  165.          * @param resultListener 
  166.      *            the resultListener to set 
  167.      */  
  168.     public void setResultListener(LSpeechResultListener resultListener) {  
  169.         this.resultListener = resultListener;  
  170.     }  
  171.   
  172.     public interface LSpeechResultListener {  
  173.   
  174.         public void onStart();//开始识别  
  175.   
  176.         public void onError(String error);//识别出现错误  ---错误的内容  
  177.   
  178.         public void onSuccess(String result);//识别成功   ---识别结果  
  179.     }  
  180. }  

6,贴上过滤文字和其他无关的内容的LDateFormat类  (很大一部分是别人写的,谢谢那位大神!)

    

[java]  view plain copy
  1. /** 
  2.  * 数据格式化 
  3.  * 
       
    1.  * 该类主要解决语音输入时携带汉字或者汉字数字混合的字符串情况 
    2.  * 
    3. 该类会将除{'分','毛','块','十','百','千','万','亿','一','二','三'...}以外所有的汉字移除并替换格式补位. 
    4.  * 即'十'放在十位,'百'放在百位... 
    5.  * 
    6. 例如:你好,280元----->280;两百八十元------>280 
    7.  * 
         
      1.  *  
      2.  * @author li'mingqi 
      3.  * @version 1.0 
      4.  */  
      5. public class LDataFormat {  
      6.     // 全局数组,存储单位量级  
      7.     public static String[] strCHup = { "亿""万""千""百""十""元" };  
      8.   
      9.     /*** 
      10.      * 格式化数据 
      11.      *  
      12.      * @param source 
      13.      *            语音输入的数据 
      14.      * @return 返回格式化后的数字字符串 
      15.      *  
      16.      *         li'mingqi 2014-12-11 
      17.      *  
      18.      **/  
      19.     public static String format(String source) {  
      20.         // 1,去除不相干的文字信息  
      21.         char[] pt = source.toCharArray();  
      22.         for (int i = 0; i < pt.length; i++) {  
      23.             char k = pt[i];  
      24.             if (k == '一' || k == '二' || k == '两' || k == '三' || k == '四'  
      25.                     || k == '五' || k == '六' || k == '七' || k == '八' || k == '九'  
      26.                     || k == '十' || k == '百' || k == '千' || k == '万' || k == '亿'  
      27.                     || k == '0' || k == '1' || k == '2' || k == '3' || k == '4'  
      28.                     || k == '5' || k == '6' || k == '7' || k == '8' || k == '9') {  
      29.   
      30.             } else {  
      31.                 source = source.replace(k + """");  
      32.             }  
      33.         }  
      34.         // 去除空格间隙  
      35.         source.trim();  
      36.         // 2,汉字'十','百','千'的转换  
      37.         long money = 0;  
      38.         // 如果不是数字也就是 一千万这样的汉字 ---则需要转换 如 一百五十万----1500000  
      39.         if (source.contains("一") || source.contains("二")  
      40.                 || source.contains("两") || source.contains("三")  
      41.                 || source.contains("四") || source.contains("五")  
      42.                 || source.contains("六") || source.contains("七")  
      43.                 || source.contains("八") || source.contains("九")  
      44.                 || source.contains("十") || source.contains("百")  
      45.                 || source.contains("千") || source.contains("万")  
      46.                 || source.contains("亿")) {  
      47.             money = excuteCharge(source);  
      48.         }  
      49.         // 数据的来源直接就是阿拉伯数字 如200元---此时元已经去掉,即数字200  
      50.         else {  
      51.             if (!"".equals(source)) {  
      52.                 money = Integer.parseInt(source);  
      53.             }  
      54.         }  
      55.         // 3,返回最终格式化结果  
      56.   
      57.         return money + "";  
      58.     }  
      59.   
      60.     /*** 
      61.      * 通过两次递归调用实现分割. 
      62.      *  
      63.      * @param str 
      64.      * @return li'mingqi 2014-12-11 
      65.      */  
      66.     public static long excuteCharge(String str) {  
      67.         // 存储量级单位  
      68.         long midNumber = 0;  
      69.         // 存储是否可以找到最高量级  
      70.         int bre = -1;  
      71.         // 找到后根据索引实行字符串分割  
      72.         int split = 0;  
      73.         // 通过循环查找最高量级  
      74.         for (int i = 0; i < strCHup.length; i++) {  
      75.             bre = str.indexOf(strCHup[i]);  
      76.             if (bre != -1) {  
      77.                 split = i;  
      78.                 switch (i) {  
      79.                 case 0:  
      80.                     midNumber = 100000000;  
      81.                     break;  
      82.                 case 1:  
      83.                     midNumber = 10000;  
      84.                     break;  
      85.                 case 2:  
      86.                     midNumber = 1000;  
      87.                     break;  
      88.                 case 3:  
      89.                     midNumber = 100;  
      90.                     break;  
      91.                 case 4:  
      92.                     midNumber = 10;  
      93.                     break;  
      94.                 case 5:  
      95.                     midNumber = 1;  
      96.                     break;  
      97.                 }  
      98.                 // 只需要找到最高量级,找到即刻跳出循环.  
      99.                 break;  
      100.             }  
      101.   
      102.         }  
      103.         // 如果没有找到量级数.说明该数很小,直接调用add()返回该值.  
      104.         if (bre == -1) {  
      105.             return add(str);  
      106.         }  
      107.         // 否则要根据量级进行字符串侵害和返回侵害前部分的值  
      108.         else {  
      109.             // 如果大型整数,如:十万 等.因为后面不需要再分割  
      110.             if (str.length() == bre + 1) {  
      111.                 // 对于单个量级的值,如:十、百、千、万等。不需要裁减字符串。直接返回量级即可  
      112.                 if (str.length() == 1) {  
      113.                     return midNumber;  
      114.                 } else {  
      115.                     return add(str.substring(0, str.length() - 1)) * midNumber;  
      116.                 }  
      117.             }  
      118.             // 对于只有两位数的.如:十九.直接调用add()返回值即可.不能在此处递归.  
      119.             else if (str.length() == bre + 2) {  
      120.                 return add(str);  
      121.             }  
      122.             // 其他情况则取值和分割.然后再递归调用.  
      123.             else {  
      124.                 String[] strPart = str.split(strCHup[split]);  
      125.                 return (add(strPart[0]) * midNumber) + excuteCharge(strPart[1]);  
      126.             }  
      127.         }  
      128.   
      129.     }  
      130.   
      131.     public static long add(String str) {  
      132.         // 存储strCHup里具体汉字的数字值  
      133.         long mid = 0;  
      134.         // 存储strNumup里具体汉字的数字值  
      135.         int number = 0;  
      136.         // 存储传入字符串的最高级别单位在strCHup数组里的索引.  
      137.         int num = -1;  
      138.         for (int i = 0; i < strCHup.length; i++) {  
      139.             // 取得量级在字符串中的索引.  
      140.             num = str.indexOf(strCHup[i]);  
      141.             // 定义char型变量,存储每个汉字.便于后面比较  
      142.             char ch = ' ';  
      143.             // //////////////////////////////////////////////////////////////  
      144.             if (num != -1) {  
      145.   
      146.                 switch (i) {  
      147.                 case 0:  
      148.                     mid = 100000000;  
      149.                     break;  
      150.                 case 1:  
      151.                     mid = 10000;  
      152.                     break;  
      153.                 case 2:  
      154.                     mid = 1000;  
      155.                     break;  
      156.                 case 3:  
      157.                     mid = 100;  
      158.                     break;  
      159.                 case 4:  
      160.                     mid = 10;  
      161.                     break;  
      162.                 case 5:  
      163.                     mid = 1;  
      164.                     break;  
      165.                 }  
      166.   
      167.                 // 如果以"十"开关的,直接定义number的值.因为在上面能够找到它的量级.  
      168.                 if ((str.toCharArray())[0] == '十') {  
      169.                     number = 1;  
      170.                 }  
      171.                 // 否则,取得量级前的数字进行比较,再确定number的值  
      172.                 else {  
      173.                     if (0 != num) {  
      174.                         ch = (str.toCharArray())[num - 1];  
      175.                     }  
      176.                 }  
      177.   
      178.                 // ////////////////////////////////////////////////////  
      179.             }  
      180.             // 循环结束  
      181.             // ////////////////////////////////////////////////////////////////  
      182.             // 如果整个字符串就一个字,那么就应该取该值进行比较.而不是再取量级前的数字.  
      183.             if (str.length() == 1) {  
      184.   
      185.                 ch = (str.toCharArray())[0];  
      186.             }  
      187.             // 防止几万零几这样的数.  
      188.             else if ((str.length() == 2) && ((str.toCharArray())[0] == '零')) {  
      189.                 ch = (str.toCharArray())[1];  
      190.             }  
      191.             switch (ch) {  
      192.             case '零':  
      193.                 number = 0;  
      194.                 break;  
      195.             case '一':  
      196.                 number = 1;  
      197.                 break;  
      198.             case '二':  
      199.                 number = 2;  
      200.                 break;  
      201.             case '两':  
      202.                 number = 2;  
      203.                 break;  
      204.             case '三':  
      205.                 number = 3;  
      206.                 break;  
      207.             case '四':  
      208.                 number = 4;  
      209.                 break;  
      210.             case '五':  
      211.                 number = 5;  
      212.                 break;  
      213.             case '六':  
      214.                 number = 6;  
      215.                 break;  
      216.             case '七':  
      217.                 number = 7;  
      218.                 break;  
      219.             case '八':  
      220.                 number = 8;  
      221.                 break;  
      222.             case '九':  
      223.                 number = 9;  
      224.                 break;  
      225.             }  
      226.             // ///////////////////////////////////////////////////////////////  
      227.   
      228.             if (num != -1) {  
      229.                 break;  
      230.             }  
      231.   
      232.         }  
      233.         if (num == -1) {  
      234.             return number;  
      235.         }  
      236.   
      237.         String strLeft = str.substring(num + 1);  
      238.         return (number * mid) + add(strLeft);  
      239.     }  
      240. }  
最后在Activity中的使用方法:

    

[java]  view plain copy
  1. public class MainActivity extends Activity {  
  2.     /**语音识别管理**/  
  3.     LSpeechManager manager;  
  4.     /**识别内容输入框**/  
  5.     EditText text;  
  6.   
  7.     @Override  
  8.     protected void onCreate(Bundle savedInstanceState) {  
  9.         super.onCreate(savedInstanceState);  
  10.         setContentView(R.layout.activity_main);  
  11.         text = (EditText) findViewById(R.id.editText1);  
  12.         manager = new LSpeechManager(this);  
  13.         manager.setResultListener(new LSpeechResultListener() {  
  14.   
  15.             @Override  
  16.             public void onSuccess(String result) {  
  17.                 // 识别结束  
  18.                 text.setText(result);  
  19.             }  
  20.   
  21.             @Override  
  22.             public void onError(String error) {  
  23.                 // 识别出现异常  
  24.             }  
  25.   
  26.             @Override  
  27.             public void onStart() {  
  28.                 // 识别开始  
  29.             }  
  30.         });  
  31.     }  
  32.   
  33.     public void onClick(View v) {  
  34.         int id = v.getId();  
  35.         switch (id) {  
  36.         case R.id.button1:// 开始识别  
  37.             manager.start();  
  38.             break;  
  39.         }  
  40.     }  
附上demo: http://download.csdn.net/detail/li352558693/8253035

   

     


你可能感兴趣的:(语音识别)