手把手教你做Android聊天机器人

我相信大家应该知道有款应用叫小黄鸡吧!

如果不知道,那你见过那种可以秒回复的聊天应用么?

如果仍然没看到!那你总见过可以迅速回复你的微信公共账吧!

如果仍然....亲出门左拐

好,不多说。

首先大家都应该了解程序,程序就是由人为的设定搭建起来的一套系统,

这里的机器人也是,简单的原理就是当你输入关键字后,通过一套算法,

在数据库中找到与之最为匹配的内容在返回给你。这个已经有人实现,我们这节教程就用别人

已经实现好的东西去做一??个应用来玩耍~~

(当然如果你非要想知道如何去做,给我留言。看情况我会出篇教程去交大家如何去做这个后端的机器人)

首先我们需要设计程序。

需要用到的类

-------ChatMessage.java(自己创建的类,目的是为了在接受与发送的时候把信息封装对象化)

------- Result.java(接受信息时候需要用到的返回信息类)

直到

------- AiaiUntil.java(自己创建的类型,用来发送信息与得到返回信息的工具)

------- ------- ------- ------- ------- ------- ------- ------- ------- ------- ------- ------- ------- ------- ------- ------- ------- ------- ------- -------

CharMessageAdapter.java (因为是聊天形式的应用,所以布局需要时动态的,这里引用的布局Adapter需要继承BaseAdapter )

MainActivity.java(程序入口,程序的总展示层)

以上就是用到的所有类,很少吧。

为什么这么少,是因为我们借用的是别人写好的机器人后台- 图灵机器人

大家可以点开连接,简单看看里面的API是如何用的。

请求方式

API地址:  http://www.tuling123.com/openapi/api

请求方式:HTTP GET

数据格式:JSON

返回的数据都是JSON。还有不论是否返回成功都会返回一个代码,用来判断是否返回成功

下面我们就进行代码的编写,首先是封装信息的对象。

ChatMessage。java的

包装com.www.xiaoaiai.com.bean;

进口java.util.Date的;

公共类ChatMessage {

		私人字符串名称;
		私人弦乐味精;
		私人类型类型;
		私人时间日期;
		公共ChatMessage(){

		}
		公共ChatMessage(弦乐味精,类型类型,日期为准){
			this.msg =味精;
			this.type =类型;
			this.date =日期;
		}

		//定义枚举定义类型
		//枚举是用来区分数据类型
		公共枚举类型
		{
			来料,OUTCOMING
		}
		公共字符串的getName(){
			返回的名称;
		}
		公共无效的setName(字符串名称){
			this.name =名称;
		}
		公共字符串的getMsg(){
			返回味精;
		}
		公共无效setMsg(弦乐味精){
			this.msg =味精;
		}
		公共类型的getType(){
			返回类型;
		}
		公共无效的setType(类型类型){
			this.type =类型;
		}
		公开日期GETDATE(){
			返回日期;
		}
		公共无效的setDate(日期为准){
			this.date =日期;
		}

}

下面是信息结果类

包装com.www.xiaoaiai.com.bean;
/ **
 *
 * @author Srain_zhou
 *为了发送一个对话对象到服务器所需要的映射对象
 * /
公共类结果{

	//此处注意开头字母组好小写,因为返回的结果键都是小谢的
	私人诠释代码;
	私人字符串文本;
	公众诠释引用代码(){
		返回代码;
	}
	公共无效setCode(INT代码){
		this.code =代码;
	}
	公共字符串的getText(){
		返回文本;
	}
	公共无效的setText(字符串文本){
		this.text =文本;
	}

}

下面是核心交换类,可以理解为DAO

AiaiUntil.java

包com.www.xiaoaiai.com.until;

进口java.io.ByteArrayOutputStream中;
进口java.io.IOException的;
进口的java.io.InputStream;
进口java.io.UnsupportedEncodingException;
进口java.net.HttpURLConnection中;
进口java.net.MalformedURLException;
进口java.net.URLEncoder中;
进口java.util.Date的;

进口com.google.gson.Gson;
进口com.www.xiaoaiai.com.bean.ChatMessage;
进口com.www.xiaoaiai.com.bean.ChatMessage.Type;
进口com.www.xiaoaiai.com.bean.Result;

公共类AiaiUntil {
	//连接图灵机器人的接口
	私有静态最后字符串URL =“htt??p://www.tuling123.com/openapi/api”;
	//自己的apikey
	私有静态最后弦乐API_KEY =“自己去申请的一个APP_KEY体验下开发的快感吧!”;

	//发送一个消息,得到返回的消息
	公共静态ChatMessage的sendMessage(弦乐味精){
		//创建一个封装信息对象
		ChatMessage chatmessage =新ChatMessage();
		//此处请看的doGet方法
		字符串jsonRes =的doGet(MSG);
		// GSON是谷歌提供的一个JAR包主要用途为序列化的Java对象为JSON字符串,或反序列化JSON字符串成的Java对象。
		//序列化是为了网路传输
		GSON GSON =新GSON();
		结果结果= NULL;
		尝试{
			//为了获得返回字符串
			结果= gson.fromJson(jsonRes,Result.class);
			chatmessage.setMsg(result.getText());
		}赶上(例外五){
			chatmessage.setMsg(“服务器繁忙”);
		}

		chatmessage.setDate(新日期());
		chatmessage.setType(Type.INCOMING);
		返回chatmessage;
	}

	公共静态字符串的doGet(弦乐味精){
		字符串结果=“”;
		//拼接网址此处需要详细了解图灵机器人的请求方式
		字符串URL = setRarams(MSG);
		//输入流
		InputStream的是= NULL;
		// ByteArrayOutputStream此类实现了一个输出流,其中的数据被写入一个字节数组。
		ByteArrayOutputStream BAOS = NULL;
		//构建发送请求的对象
		尝试{
			的java.net.URL url_net =新的java.net.URL(URL);
			HttpURLConnection的CONN =(HttpURLConnection类)url_net.openConnection();
			//设置从主机读取数据超时
			conn.setReadTimeout(5 * 1000);
			//设置连接主机超时
			conn.setConnectTimeout(5 * 1000);
			//设置连接方式
			conn.setRequestMethod(“GET”);
			//获取写入流
			是= conn.getInputStream();
			//设置缓冲区
			整型长度= -1;
			//设置缓冲区128字节
			byte []的BUF =新的字节[128];
			//吧流转换成字符串的类
			BAOS =新ByteArrayOutputStream();
			//判断是否读完
			而((长度= is.??read(BUF))!=  -  1){
				baos.write(BUF,0,长度);
			}
			//清除缓冲区
			baos.flush();
			//把流转换为字符串
			结果=新的String(baos.toByteArray());

		}赶上(MalformedURLException的E){
			// TODO自动生成的catch块
			e.printStackTrace();
		}赶上(IOException异常E){
			// TODO自动生成的catch块
			e.printStackTrace();
		}最后{
			//释放资源
			尝试{
				如果(BAOS!= NULL){
					baos.close();
				}
			}赶上(IOException异常E){
				// TODO自动生成的catch块
				e.printStackTrace();
			}
			尝试{
				如果(是!= NULL){
					is.close();
				}
			}赶上(IOException异常E){
				// TODO自动生成的catch块
				e.printStackTrace();
			}
		}

		返回结果;
	}

	//构建请求路径的方法
	公共静态字符串setRarams(弦乐味精){
		字符串URL_value = NULL;
		尝试{
			URL_value =网址+ + + API_KEY“与信息=”+ URLEncoder.encode(MSG,“UTF-8”)“键=?”;
		}赶上(UnsupportedEncodingException E){
			// TODO自动生成的catch块
			e.printStackTrace();
		}
		返回URL_value;
	}
}

CharMessageAdapter.java内容提供者,里面关于对话的布局文件你可以按照自己的喜欢自己去设计

简单解释下。其中对话框是一个listView 里面分别是两组不同的ListView(红色与蓝色),请结合下面

代码去模拟定义自己的对话布局,我就觉得我的布局丑,所以就不贴代码了。自己DIY吧~~

包com.www.xiaoaiai.com;

进口java.text.SimpleDateFormat的;
进口的java.util.List;

进口com.www.xiaoaiai.com.bean.ChatMessage;
进口com.www.xiaoaiai.com.bean.ChatMessage.Type;

进口android.content.Context;
进口android.view.LayoutInflater;
进口android.view.View;
进口android.view.ViewGroup;
进口android.widget.BaseAdapter;
进口android.widget.TextView;

公共类CharMessageAdapter扩展了BaseAdapter {
  / **
	*对于一个没有被载入或者想要动态载入的界面,都需要使用充气来载入。
	*的Andr??oid里面想要创建一个画面的时候,初学一般都是新建一个类,继承活动基类,
	*然后在的onCreate里面使用的setContentView方法来载入一个在XML里定义好的界面。
 	*其实在活动里面就使用了LayoutInflater来载入界面,
 	*通过getSystemService(Context.LAYOUT_INFLATER_SERVICE)方法可以获得一个LayoutInflater,
 	*也可以通过LayoutInflater吹气= getLayoutInflater();
 	*来获得。然后使用充气方法来载入布局的XML,
 	*在实际开发种LayoutInflater这个类还是非常有用的,它的作用类似于findViewById()
	*不同点是LayoutInflater是用来找布局下的xml布局文件,
	*并且实例化!而findViewById()是找具体的xml下的具体窗口小部件控件。
	* /
	//用来重载布局的对象,是机器人已经帮我们做好的类
	私人LayoutInflater mInflater;
	//聊天信息数据集合
	私人名单<ChatMessage> mDatas;
	公共CharMessageAdapter(上下文语境,名单<ChatMessage> mDatas){
		mInflater = LayoutInflater.from(上下文);
		this.mDatas = mDatas;
	}
	//继承BaseAdapter需要重写的方法,获取数据的长度
	@覆盖
	公众诠释getCount将(){
		// TODO自动生成方法存根
		返回mDatas.size();
	}
	//继承BaseAdapter需要重写的方法,获取数据所处的项目
	@覆盖
	公共对象的getItem(INT位置){
		// TODO自动生成方法存根
		返回mDatas.get(位置);
	}
	//继承BaseAdapter需要重写的方法,获取ITEMID
	@覆盖
	众长getItemId(整数位){
		// TODO自动生成方法存根
		回到位置;
	}
	/ **
	 *因为本次需要布局两次不同位置所以需要多写两个方法
	 * /
	// getItemViewType方法告诉ListView中每行该显示哪种项目
	@覆盖
	公众诠释getItemViewType(整数位){
		ChatMessage chatMessage = mDatas.get(位置);

		如果(chatMessage.getType()== Type.INCOMING){
			返回0;
		}
		返回1;
	}
	// getViewTypeCount这个方法告诉ListView控件我共有多少种项目
	@覆盖
	公众诠释getViewTypeCount(){
		// TODO自动生成方法存根
		返回2;
	}
	/ **
	 *就是一个持有者的类,他里面一般没有方法,
	 *只有属性,作用就是一个临时的储存器,
	 *把你getView方法中每次返回的视图存起来,可以下次再用。
	 *这样做的好处就是不必每次都到布局文件中去拿到你的视图,提高了效率。
	 * /
	 私人final类ViewHolder {
		 TextView的mDate;
		 TextView的MMSG;
	 }
	//如下这个就是如何动态布局的代码
	@覆盖
	公共查看getView(INT位置,查看convertView,父母的ViewGroup){
		ChatMessage chatMessage = mDatas.get(位置);
		//上文中说出用处,提高页面效率
		ViewHolder viewholder = NULL;
		如果(convertView == NULL){
			//通过的ItemType设置不同的布局
			如果(getItemViewType(位置)== 0){
			convertView = mInflater.inflate(R.layout.item_from_msg,父母,假);
			viewholder =新ViewHolder();
			viewholder.mDate =(TextView的)convertView.findViewById(R.id.from_msg_date);
			viewholder.mMsg =(TextView的)convertView.findViewById(R.id.from_msg);
			}
			其他{
				convertView = mInflater.inflate(R.layout.item_to_msg,父母,假);
				viewholder =新ViewHolder();
				viewholder.mDate =(TextView的)convertView.findViewById(R.id.to_msg_date);
				viewholder.mMsg =(TextView的)convertView.findViewById(R.id.to_msg);
			}
			//在使用LayoutInflater对象进行查看扩充的标签的使用
			//用来标记convertView,如果viewholder对象有就不在重新生成对象,为了效率!
			convertView.setTag(viewholder);
		}其他{
			viewholder =(ViewHolder)convertView.getTag();
		}
		//下面这段代码慢慢看,很简单
		SimpleDateFormat的DF =新的SimpleDateFormat(“YYYY-MM-DD HH:MM:SS”);
		viewholder.mDate.setText(df.format(chatMessage.getDate()));
		viewholder.mMsg.setText(chatMessage.getMsg());

		返回convertView;
	}

}

下面就是最主要的主MainActivity了~~

package com.www.xiaoaiai.com;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import com.www.xiaoaiai.com.bean.ChatMessage;
import com.www.xiaoaiai.com.bean.ChatMessage.Type;
import com.www.xiaoaiai.com.until.AiaiUntil;

import android.support.v7.app.ActionBarActivity;
import android.text.TextUtils;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.Window;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.Toast;

public class MainActivity extends ActionBarActivity {
	//最外边的对话布局
	private ListView mMsg;
	//内容提供对象
	private CharMessageAdapter mAdapter;
	//数据集合
	private List<ChatMessage> mDatas;
	//VIEW
	private EditText mInputMsg;
	private Button mSendMsg;
	//因为要更新界面所以要用 Handler mHandler
	private Handler mHandler =new Handler(){
		public void handleMessage(android.os.Message msg) {
			//等待ijieshou子线程
			ChatMessage cm=(ChatMessage)msg.obj;
			mDatas.add(cm);
			mAdapter.notifyDataSetChanged();
			mMsg.setSelection(mDatas.size()-1);
		};};
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		requestWindowFeature(Window.FEATURE_NO_TITLE);
		setContentView(R.layout.activity_main);
		//初始化视图
		initView();
		//初始化数据
		initDatas();
		//初始化监听
		initListener();
	}

	private void initListener() {
		mSendMsg.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				final String toMsg = mInputMsg.getText().toString();

			if(TextUtils.isEmpty(toMsg)){
				Toast.makeText(MainActivity.this, "发送消息不可以为空", Toast.LENGTH_SHORT).show();
					return;
				}
			//为了做聊天的效果
			ChatMessage toMessage = new ChatMessage();
			toMessage.setDate(new Date());
			toMessage.setMsg(toMsg);
			toMessage.setType(Type.OUTCOMING);
			mDatas.add(toMessage);
			mAdapter.notifyDataSetChanged();
			mMsg.setSelection(mDatas.size()-1);
			mInputMsg.setText("");
			new Thread(
					new Runnable() {
						public void run() {
							//网络访问不能用在主线程中应该在子线程中
							ChatMessage fromMessage =AiaiUntil.sendMessage(toMsg);
							Message m =Message.obtain();
							m.obj=fromMessage;
							//发送后 会在handler中的handleMessage中接受到
							mHandler.sendMessage(m);
						}
					}).start();

			}
		});

	}
	private void initDatas() {
		mDatas =new ArrayList<ChatMessage>();
		mDatas.add(new ChatMessage("你好,我是小艾艾",Type.INCOMING,new Date()));
		mAdapter = new CharMessageAdapter(this,mDatas);
		mMsg.setAdapter(mAdapter);
	}
	private void initView() {
		mMsg=(ListView)findViewById(R.id.id_list_view_01);
		mInputMsg=(EditText)findViewById(R.id.input_msg);
		mSendMsg=(Button)findViewById(R.id.id_send_msg);
	}

}

希望对大家的学习有帮助~~~

提示!~~~

1如果你编译不出现R文件,也就是说R. 不出来 说明你的XML文件绝对有错误

2在这个APP中,千万别忘记加网络访问权限~

AndroidManifest.xml 文件中

加入如下代码

<uses-permission android:name="android.permission.INTERNET"/> 加载application  标签外面

				
时间: 2024-10-08 20:51:02

手把手教你做Android聊天机器人的相关文章

手把手教你做蓝牙聊天应用(一)-设计方案

前言 通过"计算器"和"视频播放器"我们已经能够开始开发一些比较像样的应用了. 今天,我们将开始制作一个"蓝牙聊天"应用.这个应用其实很简单,没有炫酷的界面,就是一对一.通过蓝牙连接两台设备,让两个人互相发送信息. 可别觉得它太无聊.没有什么实用性,其实我们正是想通过它让你开始接触网络编程(蓝牙和wifi都是无线连接技术,它们的程序设计方法和思路非常的相似). 另外,学会了使用蓝牙,就为大家打开了技术开发的另一扇大门-物联网,现在很多物联网硬件都

手把手教你做蓝牙聊天应用(二)-设计方案

第2节 设计方案 功能确定后,就要开始围绕功能进行功能的验证.界面设计的规划.以及程序结构的规划了. 2.1 技术验证 选定了现阶段要完成的核心功能后,我们首先需要对它们做技术上的验证,看看用什么样的方法能实现它们.在进行技术验证的同时,也能让我们发现很多我们在头脑风暴阶段没有意识到的现实问题. 现在的手机和移动设备已经把蓝牙作为了标准配置,它常常用到与周边小设备的数据连接上,例如蓝牙自拍杆,蓝牙音箱,蓝牙键盘,运动手环等等,可以看出这都是一些不需要太大数据量传输而需要保持长时间数据通信的设备.

手把手教你做蓝牙聊天应用(五)-界面使用ConnectionManager

第5节 界面使用ConnectionManager ConnectionManager已经设计完成了,它的价值需要在ChatActivity中体现出来. 5.1 监听ConnectionManager 实现对ConnectionManager各个状态的监听,当ConnectionManager的状态有变化.收到发送的数据时,需要让ChatActivity知道,它才能将各种变化反应到用户界面上. 5.1.1 创建监听器 ConnectionManager定义了ConnectionListener接

手把手教你做蓝牙聊天应用(六)-界面优化

第6节 应用的美化与完善 现在,我们还可以为聊天应用加上多国语言的支持和关于界面,把使用到的颜色和尺寸定义到资源文件当中,这样一来,安豆的蓝牙聊天应用就算是比较完整的完成了. 这两部分在以前"计算器"章节中,已经介绍过了,大家就自己动手吧. 这一节,我们将重点介绍聊天文字的背景图片是如何制作的. 6.1 9Patch图片的原理 观察一下安卓系统中需要经常用到的图片,可以发现: 很多要使用透明效果的地方在转角处: 很多图片不同的地方只在靠近边缘的地方,内部区域几乎都是一样的: 为此安卓系

手把手教你做蓝牙聊天应用(三)-获取要连接的设备

第3节 获取要连接的设备 这一节我们开始设计蓝牙聊天应用的界面.根据之前的规划,连接管理将放在单独的ConnectionManager模块当中,所以每当要使用连接功能的时候,我们就暂时把它空着,等到ConnectionManager开发完成之后再加进来. 这里我们将完成下面的界面设计, 3.1 主界面 主界面是一个独立的Activity-ChatActivity,它要实现三个主要功能, 当蓝牙没有开启或者设备不能被发现的时候,请求用户打开对应的功能: 下方有输入框输入要发送的文字内容,点击按钮后

手把手教你做蓝牙聊天应用(四)-蓝牙连接模块

第4节 蓝牙连接模块 蓝牙连接的管理模块需要为ChatActivity提供于连接相关的所有功能,要设计的方便使用,并尽量隐藏连接的细节. 4.1 对外接口 我们首先来看看ConnectionManager需要向Chat Activity提供哪些接口. 监听.当应用运行起来后,聊天应用需要启动对其它蓝牙设备的监听,迎接随时可能到来的连接请求.所以ConnectionManager需要提供启动监听-startListen()和停止监听-stopListen()的两个接口: 主动连接.应用搜索到可连接

微信测试工程师手把手教你做弱网络模拟测试

微信测试工程师手把手教你做弱网络模拟测试 Posted by 腾讯优测 | 3,152 views 小优有话说: app研发不同于实验室里做研究,哪里有"理想环境". 理想里,用户用着性能卓越的手机,连着畅通无阻的wifi网络. "哇塞!这个app好用到飞起!" 现实是,他们可能正用着你闻所未闻的机型,穿梭于地铁.公交.火车.乡间.大山-.. 信号"若隐若现,扑朔迷离" "我去!又crash了!" "唉,怎么又连不上

手把手教你做关键词匹配项目(搜索引擎)---- 第三天

第三天 小王(运营总监)看到小丁丁整天都在淘宝.百度.魔方.拍拍上面淘关键词,每天花费的时间好长,工作效率又低,拿着这个借口来找到我. 说到:小帅帅,你看小丁丁每天都在淘宝.百度.魔方.拍拍上面淘关键词花费的时间好长,你能不能帮帮忙,看看能不能让系统自己做啦,这样可以节省好多人力,带来的效益多高.(0 其实就是为了掩饰他们懒惰 0) 小帅帅一听到可以带来的效益好高,王总还求着我呢 ,马上 两眼冒着星光,是该好好体现, 解决这个问题就可以体现出我的价值. 小帅帅拍着胸膛保证到:王总,这个小KS啦,

UWP Jenkins + NuGet + MSBuild 手把手教你做自动UWP Build 和 App store包

背景 项目上需要做UWP的自动安装包,在以前的公司接触的是TFS来做自动build. 公司要求用Jenkins来做,别笑话我,之前还真不晓得这个东西. 会的同学请看一下支持错误,不会的同学请先自行脑补,我们一步一步的来. 首先我们准备2个安装包,Jenkins,NuGet 都下载最新的好了. 1. 安装Jenkins,下一步下一步.安装好了会自动浏览器跳转到http://localhost:8080/ 如下图 按照提示去C:\Program Files (x86)\Jenkins\secrets