一导入相关的包
二添加相应的权限
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.voice" android:versionCode="1" android:versionName="1.0" > <!-- 连接网络权限,用于执行云端语音能力 --> <uses-permission android:name="android.permission.INTERNET" /> <!-- 获取手机录音机使用权限,听写、识别、语义理解需要用到此权限 --> <uses-permission android:name="android.permission.RECORD_AUDIO" /> <!-- 读取网络信息状态 --> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <!-- 获取当前wifi状态 --> <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /> <!-- 允许程序改变网络连接状态 --> <uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" /> <!-- 读取手机信息权限 --> <uses-permission android:name="android.permission.READ_PHONE_STATE" /> <!-- 读取联系人权限,上传联系人需要用到此权限 --> <uses-permission android:name="android.permission.READ_CONTACTS" /> <uses-sdk android:minSdkVersion="8" android:targetSdkVersion="21" /> <application android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme" > <activity android:name=".MainActivity" android:label="@string/app_name" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest>
三整体布局
activity_main.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <ListView android:id="@+id/list" android:layout_width="match_parent" android:layout_height="0dp" android:cacheColorHint="@android:color/transparent" android:divider="@null" android:dividerHeight="0dp" android:layout_weight="1" /> <RelativeLayout android:layout_width="fill_parent" android:layout_height="wrap_content" android:background="@drawable/bottom_bar" > <Button android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_centerInParent="true" android:onClick="start" android:background="@drawable/btn_selector" android:text="语音识别" /> </RelativeLayout> </LinearLayout>
四创建公共类(语音合成和识别)
VoiceUtils.java
package com.example.voice; import com.iflytek.cloud.SpeechConstant; import com.iflytek.cloud.SpeechSynthesizer; import com.iflytek.cloud.SpeechUtility; import com.iflytek.cloud.ui.RecognizerDialog; import com.iflytek.cloud.ui.RecognizerDialogListener; import android.content.Context; public class VoiceUtils { private Context context; public VoiceUtils(Context context) { this.context = context; // 将“12345678”替换成您申请的APPID,申请地址:http://open.voicecloud.cn SpeechUtility.createUtility(context, SpeechConstant.APPID + "= 574d92ab"); } public void listen(RecognizerDialogListener Listener) { // 1.创建SpeechRecognizer对象,第二个参数:本地听写时传InitListener RecognizerDialog iatDialog = new RecognizerDialog(context, null); // 2.设置听写参数,同上节 iatDialog.setParameter(SpeechConstant.DOMAIN, "iat"); iatDialog.setParameter(SpeechConstant.LANGUAGE, "zh_cn"); iatDialog.setParameter(SpeechConstant.ACCENT, "mandarin "); // 3.设置回调接口 iatDialog.setListener(Listener); // 4.开始听写 iatDialog.show(); // //1.创建SpeechRecognizer对象,第二个参数:本地听写时传InitListener // SpeechRecognizer mIat= SpeechRecognizer.createRecognizer(context, // null); // //2.设置听写参数,详见《科大讯飞MSC API手册(Android)》SpeechConstant类 // mIat.setParameter(SpeechConstant.DOMAIN, "iat"); // mIat.setParameter(SpeechConstant.LANGUAGE, "zh_cn"); // mIat.setParameter(SpeechConstant.ACCENT, "mandarin "); // //3.开始听写 // mIat.startListening(mRecoListener); // //听写监听器 } public void speak(String word) { // 1.创建SpeechSynthesizer对象, 第二个参数:本地合成时传InitListener SpeechSynthesizer mTts = SpeechSynthesizer.createSynthesizer(context, null); // 2.合成参数设置,详见《科大讯飞MSC API手册(Android)》SpeechSynthesizer 类 mTts.setParameter(SpeechConstant.VOICE_NAME, "xiaoyan");// 设置发音人 mTts.setParameter(SpeechConstant.SPEED, "50");// 设置语速 mTts.setParameter(SpeechConstant.VOLUME, "80");// 设置音量,范围0~100 mTts.setParameter(SpeechConstant.ENGINE_TYPE, SpeechConstant.TYPE_CLOUD); // 设置云端 // 设置合成音频保存位置(可自定义保存位置),保存在“./sdcard/iflytek.pcm” // 保存在SD卡需要在AndroidManifest.xml添加写SD卡权限 // 如果不需要保存合成音频,注释该行代码 mTts.setParameter(SpeechConstant.TTS_AUDIO_PATH, "./sdcard/iflytek.pcm"); // 3.开始合成 mTts.startSpeaking(word, null); // 合成监听器 } }
五获取按钮的监听,触发公共类的listen(),
public void start(View v) { voiceUtils.listen(new MyRecognizerDialogListener()); }
而MyRecognizerDialogListener类里面有个函数
public void onResult(RecognizerResult result, boolean isLast)
获取的result是json格式,需要进行解析(建立相应的bean类),首先是字符与字符之间的拼接,后是句与句的拼接,这样子才能组成一段话。此外在组成一段话后,需要清空之前的话,新建new StringBuffer()即可,随后对ListView添加数据,建立适配器Myadapter(),最后设置回答内容,并且读出来。
VoiceBean.java(json格式的bean)
package com.example.voice; import java.util.List; public class VoiceBean { public int bg; public int ed; public boolean ls; public int sn; public List<WS> ws; public class WS{ public int bg; public List<CW> cw; } public class CW{ public double sc; public String w; } }
Conversation.java(对布局中显示的数据)
package com.example.voice; public class Conversation { public String word;//展示的文字 public boolean isAsker;//是否是问题 public int imgId;//-1无图片 // 创建构造方法 public Conversation(String word, boolean isAsker, int imgId) { super(); this.word = word; this.isAsker = isAsker; this.imgId = imgId; } }
Resource.java(布局中回答的图片文字内容)
package com.example.voice; public class Resource { public static int[] imgIds = new int[] { R.drawable.cyx, R.drawable.mm14, R.drawable.mm19, R.drawable.mm21, R.drawable.mm23 }; public static String[] words = new String[]{ "就是这样子", "哈哈哒", "500", "烦烦烦", "夜夜夜夜" }; }
MainActivity.java
package com.example.voice; import android.support.v7.app.ActionBarActivity; import java.util.ArrayList; import java.util.List; import java.util.Random; import com.example.voice.VoiceBean.WS; import com.google.gson.Gson; import com.iflytek.cloud.RecognizerResult; import com.iflytek.cloud.SpeechError; import com.iflytek.cloud.ui.RecognizerDialogListener; import android.os.Bundle; import android.view.View; import android.view.ViewGroup; import android.widget.BaseAdapter; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.ListView; import android.widget.TextView; public class MainActivity extends ActionBarActivity { private VoiceUtils voiceUtils; private StringBuffer stringBuffer; private ListView list; ArrayList<Conversation> conversations; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); list = (ListView) findViewById(R.id.list); stringBuffer = new StringBuffer(); voiceUtils = new VoiceUtils(this); conversations = new ArrayList<Conversation>(); } // 步骤一 public void start(View v) { voiceUtils.listen(new MyRecognizerDialogListener()); } class MyRecognizerDialogListener implements RecognizerDialogListener { @Override public void onError(SpeechError arg0) { // TODO Auto-generated method stub } /* * isLast-------是否是最后一句 (non-Javadoc) */ @Override public void onResult(RecognizerResult result, boolean isLast) { // TODO Auto-generated method stub // 打印出来的是json格式,需要解析 System.out.println(result.getResultString()); // 只能获取一句话,如果是一段话,需要把句与句之间拼接起来 String word = processedData(result.getResultString()); System.out.println(word); stringBuffer.append(word); if (isLast) { String question = stringBuffer.toString(); // 我们说的话打印出来 // System.out.println(stringBuffer.toString()); // 清空之前的话,最简单的方法是新建,然后之前的就回收起来。 stringBuffer = new StringBuffer(); // 创建问题数据 Conversation asker = new Conversation(question, true, -1); conversations.add(asker); // 更新ListView if (list.getAdapter() == null) { list.setAdapter(new Myadapter()); } else { ((BaseAdapter) list.getAdapter()).notifyDataSetChanged(); } String answerWord = "听不懂的说"; int imgId = -1; // 更新回答数据 if (question.contains("你好")) { answerWord = "你也好"; } else if (question.contains("美女")) { Random random = new Random(); int newxInt = random.nextInt(Resource.imgIds.length); answerWord = Resource.words[newxInt]; imgId = Resource.imgIds[newxInt]; } Conversation answer = new Conversation(answerWord, false, imgId); conversations.add(answer); ((BaseAdapter) list.getAdapter()).notifyDataSetChanged(); // 回答内容读出来 voiceUtils.speak(answerWord); // 自动滑到最后一个条目 list.setSelection(conversations.size()); } } } class Myadapter extends BaseAdapter { @Override public int getCount() { // TODO Auto-generated method stub return 0; } @Override public Object getItem(int position) { // TODO Auto-generated method stub return null; } @Override public long getItemId(int position) { // TODO Auto-generated method stub return 0; } @Override public View getView(int position, View convertView, ViewGroup parent) { // TODO Auto-generated method stub View view = View.inflate(getApplicationContext(), R.layout.item, null); TextView tv_asker_right = (TextView) view.findViewById(R.id.tv_asker_right); LinearLayout ll_answer_left = (LinearLayout) view.findViewById(R.id.ll_answer_left); TextView tv_answer_left = (TextView) view.findViewById(R.id.tv_answer_left); ImageView iv_answer_left = (ImageView) view.findViewById(R.id.iv_answer_left); // 根据数据判断控件的显示 Conversation conversation = conversations.get(position); if (conversation.isAsker) {// 问题 tv_asker_right.setVisibility(View.VISIBLE); ll_answer_left.setVisibility(View.GONE); tv_answer_left.setText(conversation.word); } else {// 回答 tv_asker_right.setVisibility(View.GONE); ll_answer_left.setVisibility(View.VISIBLE); if (conversation.imgId == -1) {// 是否有图片 iv_answer_left.setVisibility(View.GONE); } else { iv_answer_left.setVisibility(View.VISIBLE); iv_answer_left.setBackgroundResource(conversation.imgId); } tv_answer_left.setText(conversation.word); } return view; } } private String processedData(String string) { // TODO Auto-generated method stub Gson gson = new Gson(); VoiceBean voiceBean = gson.fromJson(string, VoiceBean.class); // 对ws进行遍历 stringBuffer = new StringBuffer(); List<WS> ws = voiceBean.ws; for (int i = 0; i < ws.size(); i++) { // 获取的仅仅是一个字符,还需要拼接起来 stringBuffer.append(ws.get(i).cw.get(0).w); } return stringBuffer.toString(); } }