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

   

     


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值