开源项目——小Q聊天机器人V1.4
2016-05-19 15:30
281 查看
小Q聊天机器人V1.0 http://blog.csdn.net/baiyuliang2013/article/details/51386281
小Q聊天机器人V1.1 http://blog.csdn.net/baiyuliang2013/article/details/51395163
小Q聊天机器人V1.2 http://blog.csdn.net/baiyuliang2013/article/details/51424971
小Q聊天机器人V1.3 http://blog.csdn.net/baiyuliang2013/article/details/51443156
小Q聊天机器人V1.4 http://blog.csdn.net/baiyuliang2013/article/details/51454161
小Q聊天机器人V1.5 http://blog.csdn.net/baiyuliang2013/article/details/51461008
GitHub:https://github.com/baiyuliang/QRobot
应用市场已上线,扫码体验:
注意:发送消息后如果小Q没回答,或回答“亲爱的,当天请求次数已用完”,表示当天的api调用次数已经超过限制次数,大家可以自己申请apikey用于测试!(音乐和位置功能不受影响)
V1.4版本中,对来聊天界面不同消息布局进行了优化,使得聊天消息类型的扩展性更强!1.4之前的版本我们知道,我是将各种消息类型布局全部集中在了一个xml中,这种方式对少量消息类型的应用还可以,如果消息类型过多,那么这种方式就显得很low了,而且影响性能!1.4版本中,将各种消息类型逐一拆分(并且发送和接收一一对应),在adapter中根据消息类型去加载不同view:
同时使用了通用ViewHolder,我们可以比较下1.4之前版本和1.4版本中adapter的getview部分:
1.4之前:
1.4版本:
就拿代码行数来说就非常直观,而且1.4版本中还增加了语音消息类型!代码简洁,逻辑更加清晰,扩展也更加容易,这也算的上IM应用的标准写法啦!
好了,接下来看看1.4版本中增加了哪些功能:
1.增加语音聊天功能及语音翻译功能:
1.4之前是录音完毕后转为文字并放进输入框,手动发送,而1.4版本中录音完毕后,可以转为语音形式自动发送,可点击播放,也可点击翻译按钮翻译成文字形式,类似QQ,看效果图:
看完你肯定会想问我是如何实现的,是直接识别音频文件并将音频文件转为文字吗?这么高大上?——哈哈,非也,其实我是取巧!在使用讯飞语音(录音)的参数设置代码中,看到如下代码:
这个文件就是每次说话时,自动生成的音频文件,那么你刚说完的话,直接取这个音频文件播放不就可以了吗?!当然,你需要复制这个文件或者说移动这个文件,并修改文件名,否则你原封不动的话,下次录音不久吧上次录音的文件覆盖掉了吗?
音频文件路径有了,而语音识别后的文本也是讯飞直接识别后生成的,现在音频文件路径和对应的语音识别文本都有了,将其存储起来,那么所谓的语音聊天,语音翻译实现也就顺理成章了!(哎,还以为是多么高大上呢,原来是投机取巧啊^^)
2.增加录音发送形式和回复自动朗读设置:
录音以语音形式发送,即录音完毕,直接以语音形式发送;
录音以文字形式发送,即录音完毕,转为文字形式手动发送;
回复内容直接朗读,即文本形式的回复直接朗读出来!
GitHub:https://github.com/baiyuliang/QRobot
小Q聊天机器人V1.1 http://blog.csdn.net/baiyuliang2013/article/details/51395163
小Q聊天机器人V1.2 http://blog.csdn.net/baiyuliang2013/article/details/51424971
小Q聊天机器人V1.3 http://blog.csdn.net/baiyuliang2013/article/details/51443156
小Q聊天机器人V1.4 http://blog.csdn.net/baiyuliang2013/article/details/51454161
小Q聊天机器人V1.5 http://blog.csdn.net/baiyuliang2013/article/details/51461008
GitHub:https://github.com/baiyuliang/QRobot
应用市场已上线,扫码体验:
注意:发送消息后如果小Q没回答,或回答“亲爱的,当天请求次数已用完”,表示当天的api调用次数已经超过限制次数,大家可以自己申请apikey用于测试!(音乐和位置功能不受影响)
V1.4版本中,对来聊天界面不同消息布局进行了优化,使得聊天消息类型的扩展性更强!1.4之前的版本我们知道,我是将各种消息类型布局全部集中在了一个xml中,这种方式对少量消息类型的应用还可以,如果消息类型过多,那么这种方式就显得很low了,而且影响性能!1.4版本中,将各种消息类型逐一拆分(并且发送和接收一一对应),在adapter中根据消息类型去加载不同view:
同时使用了通用ViewHolder,我们可以比较下1.4之前版本和1.4版本中adapter的getview部分:
1.4之前:
@Override public View getView(final int position, View convertView, ViewGroup parent) { final ViewHodler hodler; if (convertView == null) { hodler = new ViewHodler(); convertView = LayoutInflater.from(mContext).inflate(R.layout.chat_lv_item, null); hodler.rl_chat = (RelativeLayout) convertView.findViewById(R.id.rl_chat);//聊天布局 //接收的消息 hodler.fromIcon = (CircleImageView) convertView.findViewById(R.id.chatfrom_icon);//他人头像 hodler.toIcon = (CircleImageView) convertView.findViewById(R.id.chatto_icon);//自己头像 hodler.fromContainer = (LinearLayout) convertView.findViewById(R.id.chart_from_container); hodler.fromText = (TextView) convertView.findViewById(R.id.chatfrom_content);//文本 hodler.fromImg = (ImageView) convertView.findViewById(R.id.chatfrom_img);//图片 hodler.fromLocation = (ImageView) convertView.findViewById(R.id.chatfrom_location);//位置 hodler.ll_music = (LinearLayout) convertView.findViewById(R.id.ll_music);//音乐 hodler.iv_music= (ImageView) convertView.findViewById(R.id.iv_music); hodler.pb_music=(ProgressBar)convertView.findViewById(R.id.pb_music); hodler.tv_song_name = (TextView) convertView.findViewById(R.id.tv_song_name);//音乐名 hodler.tv_song_author = (TextView) convertView.findViewById(R.id.tv_song_author);//音乐作者 hodler.progress_load = (ProgressBar) convertView.findViewById(R.id.progress_load);//ProgressBar //发送的消息 hodler.toContainer = (RelativeLayout) convertView.findViewById(R.id.chart_to_container); hodler.toText = (TextView) convertView.findViewById(R.id.chatto_content);//文本 hodler.toImg = (ImageView) convertView.findViewById(R.id.chatto_img);//图片 hodler.toLocation = (ImageView) convertView.findViewById(R.id.chatto_location);//位置 //时间 hodler.time = (TextView) convertView.findViewById(R.id.chat_time); convertView.setTag(hodler); } else { hodler = (ViewHodler) convertView.getTag(); } final Msg msg = list.get(position); if (msg.getIsComing() == 0) {// 收到消息 from显示 hodler.toContainer.setVisibility(View.GONE);//隐藏右侧布局 hodler.fromContainer.setVisibility(View.VISIBLE); hodler.time.setText(msg.getDate()); if (msg.getType().equals(Const.MSG_TYPE_TEXT)) {//文本类型 hodler.fromText.setVisibility(View.VISIBLE);//文本 hodler.fromImg.setVisibility(View.GONE);//图片 hodler.fromLocation.setVisibility(View.GONE);//位置 hodler.ll_music.setVisibility(View.GONE);//音乐 hodler.progress_load.setVisibility(View.GONE); SpannableStringBuilder sb = ExpressionUtil.prase(mContext, hodler.fromText, msg.getContent());// 对内容做处理 hodler.fromText.setText(sb); Linkify.addLinks(hodler.fromText, Linkify.ALL);//增加文本链接类型 } else if (msg.getType().equals(Const.MSG_TYPE_IMG)) {//图片类型 hodler.fromText.setVisibility(View.GONE);//文本 hodler.fromImg.setVisibility(View.VISIBLE);//图片 hodler.fromLocation.setVisibility(View.GONE);//位置 hodler.ll_music.setVisibility(View.GONE);//音乐 hodler.progress_load.setVisibility(View.GONE); finalImageLoader.display(hodler.fromImg, msg.getContent());//加载图片 } else if (msg.getType().equals(Const.MSG_TYPE_LOCATION)) {//位置类型 hodler.fromText.setVisibility(View.GONE);//文本 hodler.fromImg.setVisibility(View.GONE);//图片 hodler.fromLocation.setVisibility(View.VISIBLE);//位置 hodler.ll_music.setVisibility(View.GONE);//音乐 hodler.progress_load.setVisibility(View.GONE); finalImageLoader.display(hodler.fromLocation, msg.getContent());//加载网络图片 } else if (msg.getType().equals(Const.MSG_TYPE_MUSIC)) {//音乐类型 hodler.fromText.setVisibility(View.GONE);//文本 hodler.fromImg.setVisibility(View.GONE);//图片 hodler.fromLocation.setVisibility(View.GONE);//位置 hodler.ll_music.setVisibility(View.VISIBLE);//音乐 hodler.progress_load.setVisibility(View.GONE); if(!TextUtils.isEmpty(msg.getBak1())&&msg.getBak1().equals("1")){ hodler.pb_music.setVisibility(View.VISIBLE); hodler.iv_music.setVisibility(View.GONE); }else{ hodler.pb_music.setVisibility(View.GONE); hodler.iv_music.setVisibility(View.VISIBLE); } String[] musicinfo = msg.getContent().split(","); if (musicinfo.length==3) {//音乐链接,歌曲名,作者 hodler.tv_song_name.setText(musicinfo[1]); hodler.tv_song_author.setText(musicinfo[2]); } } } else {// 发送消息 to显示(目前发送消息只能发送文本类型,后期将会增加其它类型) hodler.toContainer.setVisibility(View.VISIBLE); hodler.fromContainer.setVisibility(View.GONE); hodler.time.setText(msg.getDate()); if (msg.getType().equals(Const.MSG_TYPE_TEXT)) {//文本类型 hodler.toText.setVisibility(View.VISIBLE);//文本 hodler.toImg.setVisibility(View.GONE);//图片 hodler.toLocation.setVisibility(View.GONE);//位置 SpannableStringBuilder sb = ExpressionUtil.prase(mContext, hodler.toText, msg.getContent());// 对内容做处理 hodler.toText.setText(sb); Linkify.addLinks(hodler.toText, Linkify.ALL); } else if (msg.getType().equals(Const.MSG_TYPE_IMG)) {//图片类型 hodler.toText.setVisibility(View.GONE);//文本 hodler.toImg.setVisibility(View.VISIBLE);//图片 hodler.toLocation.setVisibility(View.GONE);//位置 finalImageLoader.display(hodler.toImg, msg.getContent());//加载图片 } else if (msg.getType().equals(Const.MSG_TYPE_LOCATION)) {//位置类型 hodler.toText.setVisibility(View.GONE);//文本 hodler.toImg.setVisibility(View.GONE);//图片 hodler.toLocation.setVisibility(View.VISIBLE);//位置 finalImageLoader.display(hodler.toLocation, msg.getContent());//加载网络图片 } } // 文本点击 hodler.fromText.setOnClickListener(new onClick(position)); hodler.fromText.setOnLongClickListener(new onLongCilck(position)); hodler.toText.setOnClickListener(new onClick(position)); hodler.toText.setOnLongClickListener(new onLongCilck(position)); //图片点击 hodler.fromImg.setOnClickListener(new onClick(position)); hodler.fromImg.setOnLongClickListener(new onLongCilck(position)); hodler.toImg.setOnClickListener(new onClick(position)); hodler.toImg.setOnLongClickListener(new onLongCilck(position)); //位置 hodler.fromLocation.setOnClickListener(new onClick(position)); hodler.fromLocation.setOnLongClickListener(new onLongCilck(position)); hodler.toLocation.setOnClickListener(new onClick(position)); hodler.toLocation.setOnLongClickListener(new onLongCilck(position)); //音乐 hodler.ll_music.setOnClickListener(new onClick(position)); hodler.ll_music.setOnLongClickListener(new onLongCilck(position)); return convertView; } class ViewHodler { RelativeLayout rl_chat; CircleImageView fromIcon, toIcon; ImageView fromImg, fromLocation, toImg, toLocation; TextView fromText, toText, time; LinearLayout fromContainer; RelativeLayout toContainer; ProgressBar progress_load; //音乐 LinearLayout ll_music; ImageView iv_music; ProgressBar pb_music; TextView tv_song_name, tv_song_author; }
1.4版本:
final Msg msg = list.get(position); if (convertView == null) { convertView = createViewByType(msg, position); } CircleImageView head_view = ViewHolder.get(convertView, R.id.head_view);//头像 TextView chat_time = ViewHolder.get(convertView, R.id.chat_time);//时间 TextView tv_text = ViewHolder.get(convertView, R.id.tv_text);//文本 ImageView iv_image = ViewHolder.get(convertView, R.id.iv_image);//图片 ImageView iv_location = ViewHolder.get(convertView, R.id.iv_location);//位置 LinearLayout layout_voice = ViewHolder.get(convertView, R.id.layout_voice);//语音 语音播放按钮父控件 ImageView iv_voice = ViewHolder.get(convertView, R.id.iv_voice);//动画 ImageView iv_fy = ViewHolder.get(convertView, R.id.iv_fy);//翻译按钮 final TextView tv_fy = ViewHolder.get(convertView, R.id.tv_fy);//翻译内容 LinearLayout ll_music = (LinearLayout) convertView.findViewById(R.id.ll_music);//音乐 ImageView iv_music = (ImageView) convertView.findViewById(R.id.iv_music); ProgressBar pb_music = (ProgressBar) convertView.findViewById(R.id.pb_music); TextView tv_song_name = (TextView) convertView.findViewById(R.id.tv_song_name);//音乐名 TextView tv_song_author = (TextView) convertView.findViewById(R.id.tv_song_author);//音乐作者 chat_time.setText(msg.getDate());//时间 switch (msg.getType()) { case Const.MSG_TYPE_TEXT://文本 tv_text.setText(msg.getContent()); tv_text.setOnClickListener(new onClick(position)); tv_text.setOnLongClickListener(new onLongCilck(position)); break; case Const.MSG_TYPE_IMG://图片 finalImageLoader.display(iv_image, msg.getContent()); iv_image.setOnClickListener(new onClick(position)); iv_image.setOnLongClickListener(new onLongCilck(position)); break; case Const.MSG_TYPE_LOCATION://位置 finalImageLoader.display(iv_location, msg.getContent()); iv_location.setOnClickListener(new onClick(position)); iv_location.setOnLongClickListener(new onLongCilck(position)); break; case Const.MSG_TYPE_VOICE://语音 final String[] _content = msg.getContent().split(Const.SPILT); tv_fy.setText(_content[1]); tv_fy.setVisibility(View.GONE); layout_voice.setOnClickListener(new RecordPlayClickListener(mContext, iv_voice, _content[0])); iv_fy.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (tv_fy.getVisibility() == View.GONE) { tv_fy.setVisibility(View.VISIBLE); }else{ tv_fy.setVisibility(View.GONE); } } }); layout_voice.setOnLongClickListener(new onLongCilck(position)); break; case Const.MSG_TYPE_MUSIC://音乐 if (!TextUtils.isEmpty(msg.getBak1()) && msg.getBak1().equals("1")) { pb_music.setVisibility(View.VISIBLE); iv_music.setVisibility(View.GONE); } else { pb_music.setVisibility(View.GONE); iv_music.setVisibility(View.VISIBLE); } String[] musicinfo = msg.getContent().split(Const.SPILT); if (musicinfo.length == 3) {//音乐链接,歌曲名,作者 tv_song_name.setText(musicinfo[1]); tv_song_author.setText(musicinfo[2]); } ll_music.setOnClickListener(new onClick(position)); ll_music.setOnLongClickListener(new onLongCilck(position)); break; } return convertView;
就拿代码行数来说就非常直观,而且1.4版本中还增加了语音消息类型!代码简洁,逻辑更加清晰,扩展也更加容易,这也算的上IM应用的标准写法啦!
好了,接下来看看1.4版本中增加了哪些功能:
1.增加语音聊天功能及语音翻译功能:
1.4之前是录音完毕后转为文字并放进输入框,手动发送,而1.4版本中录音完毕后,可以转为语音形式自动发送,可点击播放,也可点击翻译按钮翻译成文字形式,类似QQ,看效果图:
看完你肯定会想问我是如何实现的,是直接识别音频文件并将音频文件转为文字吗?这么高大上?——哈哈,非也,其实我是取巧!在使用讯飞语音(录音)的参数设置代码中,看到如下代码:
mIat.setParameter(SpeechConstant.ASR_AUDIO_PATH, Const.FILE_VOICE_CACHE + "iat.wav");
这个文件就是每次说话时,自动生成的音频文件,那么你刚说完的话,直接取这个音频文件播放不就可以了吗?!当然,你需要复制这个文件或者说移动这个文件,并修改文件名,否则你原封不动的话,下次录音不久吧上次录音的文件覆盖掉了吗?
/** * 移动文件 * @param oldPath * @param newPath * @return */ public static boolean copyFile(String oldPath, String newPath) { File oldFile = new File(oldPath); if (!oldFile.exists()) { return false; } if(oldFile.renameTo(new File(newPath))){ return true; }else{ return false; } }
音频文件路径有了,而语音识别后的文本也是讯飞直接识别后生成的,现在音频文件路径和对应的语音识别文本都有了,将其存储起来,那么所谓的语音聊天,语音翻译实现也就顺理成章了!(哎,还以为是多么高大上呢,原来是投机取巧啊^^)
2.增加录音发送形式和回复自动朗读设置:
录音以语音形式发送,即录音完毕,直接以语音形式发送;
录音以文字形式发送,即录音完毕,转为文字形式手动发送;
回复内容直接朗读,即文本形式的回复直接朗读出来!
GitHub:https://github.com/baiyuliang/QRobot
相关文章推荐
- Linux下安装PCRE
- nginx rewrite 指令
- 开源项目——小Q聊天机器人V1.4
- nginx port_in_redirect
- java并发编程实战 ThreadLocal
- 自定义类的实例化对象转JSON--结合Runtime
- 职场潜规则你能忍受到第几条?
- UNIX网络编程:消息队列
- laypage前端分页插件实现ajax异步分页
- 卷积神经网络(CNN)在句子建模上的应用
- 【Groovy基础系列】 Groovy运算符
- 好老师(模拟+搜索)
- 24.UIViewController
- 异步编程几种模式
- [Java IO]03_字符流
- 较为完善的限定字数评论框效果
- 将很长的String截取为多个小段字符串
- struts2 上传和下载
- DB2中有关排序内存的三个参数:SORTHEAP, SHEAPTHRES_SHR和SHEAPTHRES
- perftracker performance tool checking list