Android实现智能聊天机器人
最近在做项目中,突然来了灵感,要做一个聊天机器人.聊天机器人在很多大型App上都有使用,比如QQ群里的QQ小冰,淘宝京东等App上在没有人工客服之前会有机器人跟你聊天,根据你发的问题关键词,向你推荐一些答案,可以省下很多人工的时间以及减小服务器的压力
文章最后会给出下载地址,跟这个代码不同,不过也可以参考,可以实现功能
此功能主要原理
1.接入图灵机器人api,拼接上你输入框的消息;
2.根据api完成网络请求消息的接收与发送
3.完成布局页面
4.实现和你小蜜的对话
废话不多说,直接上图和代码
一:老规矩,先上效果图
二:注册图灵机器人,获取api
1.进入图灵机器人官网注册,已有账号的可直接登录
2.点击创建机器人
3.在创建机器人时,根据自己的需求,选择即可
4.创建好机器人之后会得到一个Api地址和一个ApiKey(如图所示)
5.下面就要拼接Api地址了(拼接方法如图所示)
拼接方法:
http://www.tuling123.com/openapi/api?key=你自己的apikey&info=你要发送的话&userid=你自己的唯一标示
三.下面就是具体实现的代码了
6.配置类,配置自己的图灵机器人(Config)
/*** author:Created by ZhangPengFei.* data: 2017/12/28* 配置类*/
public class Config {public static final String URL_KEY = "http://www.tuling123.com/openapi/api";public static final String APP_KEY = "38026ee35d614607b29c4ef3a56474a7";//此处是你申请的Apikey
}
7.格式化日期时间的工具类,用于显示时间(DateUtils)
import android.annotation.SuppressLint;
import java.text.SimpleDateFormat;
import java.util.Date;/*** author:Created by ZhangPengFei.* data: 2017/12/28* 时间格式化工具类*/public class DateUtils {@SuppressLint("SimpleDateFormat")public static String dateToString(Date date) {SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");return df.format(date);}
}
8.HttpUtils网络请求类(HttpUtils)
import com.google.gson.Gson;import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.util.Date;/*** author:Created by ZhangPengFei.* data: 2017/12/28* http工具类*/
public class HttpUtils {/*** 发送消息到服务器** @param message :发送的消息* @return:消息对象*/public static ChatMessage sendMessage(String message) {ChatMessage chatMessage = new ChatMessage();String gsonResult = doGet(message);Gson gson = new Gson();Result result = null;if (gsonResult != null) {try {result = gson.fromJson(gsonResult, Result.class);chatMessage.setMessage(result.getText());} catch (Exception e) {chatMessage.setMessage("服务器繁忙,请稍候再试...");}}chatMessage.setData(new Date());chatMessage.setType(ChatMessage.Type.INCOUNT);return chatMessage;}/*** get请求** @param message :发送的话* @return:数据*/public static String doGet(String message) {String result = "";String url = setParmat(message);System.out.println("------------url = " + url);InputStream is = null;ByteArrayOutputStream baos = null;try {URL urls = new URL(url);HttpURLConnection connection = (HttpURLConnection) urls.openConnection();connection.setReadTimeout(5 * 1000);connection.setConnectTimeout(5 * 1000);connection.setRequestMethod("GET");is = connection.getInputStream();baos = new ByteArrayOutputStream();int len = -1;byte[] buff = new byte[1024];while ((len = is.read(buff)) != -1) {baos.write(buff, 0, len);}baos.flush();result = new String(baos.toByteArray());} catch (Exception e) {e.printStackTrace();} finally {if (is != null) {try {is.close();} catch (IOException e) {e.printStackTrace();}}if (baos != null) {try {baos.close();} catch (IOException e) {e.printStackTrace();}}}return result;}/*** 设置参数** @param message : 信息* @return : url*/private static String setParmat(String message) {String url = "";try {url = Config.URL_KEY + "?" + "key=" + Config.APP_KEY + "&info="+ URLEncoder.encode(message, "UTF-8");} catch (UnsupportedEncodingException e) {e.printStackTrace();}return url;}
}
9.请求api地址返回的数据(Result)
/*** author:Created by ZhangPengFei.* data: 2017/12/28* 映射服务器返回的结果*/
public class Result {private int code; // code码private String text; // 信息public int getCode() {return code;}public void setCode(int code) {this.code = code;}public String getText() {return text;}public void setText(String text) {this.text = text;}}
10.聊天消息的实体类(ChatMessage)
import java.util.Date;/*** author:Created by ZhangPengFei.* data: 2017/12/28* 聊天消息的实体类*/
public class ChatMessage {private String name;// 姓名private String message;// 消息private Type type;// 类型:0.发送者 1.接受者private Date data;// 时间public ChatMessage() {}public ChatMessage(String message, Type type, Date data) {super();this.message = message;this.type = type;this.data = data;}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getMessage() {return message;}public void setMessage(String message) {this.message = message;}public Type getType() {return type;}public void setType(Type type) {this.type = type;}public Date getData() {return data;}public void setData(Date data) {this.data = data;}public enum Type {INCOUNT, OUTCOUNT}
}
11.服务器发送与接收消息,左边布局的实现(layout_left)
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical" ><TextViewandroid:background="#f5f5f5"android:id="@+id/chat_left_time"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_gravity="center"android:paddingTop="5dp"android:textSize="14sp"android:text="2015/5/6 12:10:13" /><LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="horizontal" ><LinearLayoutandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:orientation="vertical" ><ImageViewandroid:id="@+id/chat_left_image"android:layout_width="100dp"android:layout_height="100dp"android:src="@drawable/ser" /><TextViewandroid:id="@+id/chat_left_name"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginLeft="25dp"android:text="小蜜"android:textSize="16sp" /></LinearLayout><TextViewandroid:layout_marginLeft="10dp"android:background="@drawable/kefuborder"android:gravity="center"android:textSize="16sp"android:layout_gravity="center_vertical"android:id="@+id/chat_left_message"android:layout_width="220dp"android:layout_height="wrap_content"android:text="您好。" /></LinearLayout></LinearLayout>
12.客户端发送与接收消息,右边布局的实现(layout_right)
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical" ><TextViewandroid:id="@+id/chat_right_time"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_gravity="center"android:background="#f5f5f5"android:paddingTop="5dp"android:text="2015/5/6 12:10:13"android:textSize="14sp" /><LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:gravity="right"android:orientation="horizontal" ><TextViewandroid:id="@+id/chat_right_message"android:layout_width="220dp"android:layout_height="wrap_content"android:layout_gravity="center_vertical"android:layout_marginRight="10dp"android:background="@drawable/myborder"android:gravity="center"android:text="can i help me ?"android:textSize="16sp" /><LinearLayoutandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:orientation="vertical" ><ImageViewandroid:id="@+id/chat_right_image"android:layout_width="100dp"android:layout_height="100dp"android:src="@drawable/m" /><TextViewandroid:id="@+id/chat_right_name"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginLeft="25dp"android:layout_marginTop="5dp"android:text="zengtao"android:textSize="16sp" /></LinearLayout></LinearLayout></LinearLayout>
13.主界面聊天页面布局的实现(activity_chat)
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:background="@drawable/bac"android:orientation="vertical" ><!-- 头部 --><RelativeLayoutandroid:id="@+id/chat_top"android:layout_width="match_parent"android:layout_height="50dp"android:background="#3A4449" ><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_centerInParent="true"android:text="小蜜"android:textColor="#ffffff"android:textSize="18sp" /></RelativeLayout><!-- 底部 --><RelativeLayoutandroid:id="@+id/chat_bottom"android:layout_width="match_parent"android:layout_height="55dp"android:layout_alignParentBottom="true"android:background="#3A4449" ><EditTextandroid:id="@+id/chat_input_message"android:layout_width="240dp"android:background="@drawable/shuruborder"android:layout_height="wrap_content"android:layout_centerVertical="true"android:layout_marginLeft="5dp"android:gravity="center" /><Buttonandroid:background="@drawable/btnborder"android:id="@+id/chat_send"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_alignParentRight="true"android:layout_centerVertical="true"android:layout_toRightOf="@id/chat_input_message"android:text="发送"android:textColor="#FFFFFF"android:textSize="18sp" /></RelativeLayout><!-- 中间 --><ListViewandroid:id="@+id/chat_listview"android:layout_width="match_parent"android:layout_height="match_parent"android:layout_above="@id/chat_bottom"android:layout_below="@id/chat_top"android:divider="@null"android:dividerHeight="3dp" ></ListView></RelativeLayout>
14.聊天消息的适配器(ChatMessageAdapter)
/*** author:Created by ZhangPengFei.* data: 2017/12/28*/import android.annotation.SuppressLint;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;import java.util.List;import weektest.project.R;/*** 聊天信息适配器** @author zengtao 2015年5月6日 下午2:25:10*/
public class ChatMessageAdapter extends BaseAdapter {private List<ChatMessage> list;public ChatMessageAdapter(List<ChatMessage> list) {this.list = list;}@Overridepublic int getCount() {return list.isEmpty() ? 0 : list.size();}@Overridepublic Object getItem(int position) {return list.get(position);}@Overridepublic long getItemId(int position) {return position;}@Overridepublic int getItemViewType(int position) {ChatMessage chatMessage = list.get(position);// 如果是接收消息:0,发送消息:1if (chatMessage.getType() == ChatMessage.Type.INCOUNT) {return 0;}return 1;}@Overridepublic int getViewTypeCount() {return 2;}@SuppressLint("InflateParams")@Overridepublic View getView(int position, View convertView, ViewGroup parent) {ChatMessage chatMessage = list.get(position);if (convertView == null) {ViewHolder viewHolder = null;// 通过ItemType加载不同的布局if (getItemViewType(position) == 0) {convertView = LayoutInflater.from(parent.getContext()).inflate(R.layout.layout_left, null);viewHolder = new ViewHolder();viewHolder.chat_time = (TextView) convertView.findViewById(R.id.chat_left_time);viewHolder.chat_message = (TextView) convertView.findViewById(R.id.chat_left_message);} else {convertView = LayoutInflater.from(parent.getContext()).inflate(R.layout.layout_right, null);viewHolder = new ViewHolder();viewHolder.chat_time = (TextView) convertView.findViewById(R.id.chat_right_time);viewHolder.chat_message = (TextView) convertView.findViewById(R.id.chat_right_message);}convertView.setTag(viewHolder);}// 设置数据ViewHolder vh = (ViewHolder) convertView.getTag();vh.chat_time.setText(DateUtils.dateToString(chatMessage.getData()));vh.chat_message.setText(chatMessage.getMessage());return convertView;}/*** 内部类:只寻找一次控件** @author zengtao 2015年5月6日 下午2:27:57*/private class ViewHolder {private TextView chat_time, chat_message;}
}
15.主java的实现(ChatActivity)
import android.annotation.SuppressLint;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.text.TextUtils;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.Window;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.Toast;import java.util.ArrayList;
import java.util.Date;
import java.util.List;import weektest.project.R;public class ChatActivity extends Activity {private List<ChatMessage> list;private ListView chat_listview;private EditText chat_input;private Button chat_send;private ChatMessageAdapter chatAdapter;private ChatMessage chatMessage = null;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);requestWindowFeature(Window.FEATURE_NO_TITLE);setContentView(R.layout.activity_chat);initView();initListener();initData();}// 1.初始试图private void initView() {// 1.初始化chat_listview = (ListView) findViewById(R.id.chat_listview);chat_input = (EditText) findViewById(R.id.chat_input_message);chat_send = (Button) findViewById(R.id.chat_send);}// 2.设置监听事件private void initListener() {chat_send.setOnClickListener(onClickListener);}// 3.初始化数据private void initData() {list = new ArrayList<ChatMessage>();list.add(new ChatMessage("您好,小乖为您服务!", ChatMessage.Type.INCOUNT, new Date()));chatAdapter = new ChatMessageAdapter(list);chat_listview.setAdapter(chatAdapter);chatAdapter.notifyDataSetChanged();}// 4.发送消息聊天private void chat() {// 1.判断是否输入内容final String send_message = chat_input.getText().toString().trim();if (TextUtils.isEmpty(send_message)) {Toast.makeText(ChatActivity.this, "对不起,您还未发送任何消息",Toast.LENGTH_SHORT).show();return;}// 2.自己输入的内容也是一条记录,记录刷新ChatMessage sendChatMessage = new ChatMessage();sendChatMessage.setMessage(send_message);sendChatMessage.setData(new Date());sendChatMessage.setType(ChatMessage.Type.OUTCOUNT);list.add(sendChatMessage);chatAdapter.notifyDataSetChanged();chat_input.setText("");// 3.发送你的消息,去服务器端,返回数据new Thread() {public void run() {ChatMessage chat = HttpUtils.sendMessage(send_message);Message message = new Message();message.what = 0x1;message.obj = chat;handler.sendMessage(message);};}.start();}@SuppressLint("HandlerLeak")private Handler handler = new Handler() {public void handleMessage(android.os.Message msg) {if (msg.what == 0x1) {if (msg.obj != null) {chatMessage = (ChatMessage) msg.obj;}// 添加数据到list中,更新数据list.add(chatMessage);chatAdapter.notifyDataSetChanged();}};};// 点击事件监听OnClickListener onClickListener = new OnClickListener() {@Overridepublic void onClick(View v) {switch (v.getId()) {case R.id.chat_send:chat();break;}}};
}
17.当然别忘记了权限与依赖问题
<uses-permission android:name="android.permission.INTERNET" /> <!-- 网络权限 -->
compile 'com.google.code.gson:gson:2.2.4'//Gson解析依赖
18.写了这么多,就把图片和绘制的形状一块给你们吧,
①.输入框的样式(shuruborder)
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"><strokeandroid:width="1dp"android:color="#FFF" /><solid android:color="#FFF" /><corners android:radius="5dip" /></shape>
②.小蜜聊天框的样式(kefuborder)
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"><strokeandroid:width="1dp"android:color="#5188DE" /><solid android:color="#A5D932" /><corners android:radius="8dip" /></shape>
③.自己聊天框的样式(myborder)
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"><strokeandroid:width="1dp"android:color="#787878" /><solid android:color="#FFFFFF" /><corners android:radius="8dip" /></shape>
④.发送按钮的样式(btnborder)
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"><solid android:color="#CCCCCC"/><corners android:radius="5dip"/></shape>
⑤.用到的图片
背景图(bac.png)
小蜜头像(ser.png)
自己的头像(m.png)
19.现在的话我们的造人计划已经基本完成了,现在就可以跟你造好的聊天玩耍,
自己造的,玩的时候小心一点,玩坏就不好了.
下载地址