背景:其实,关于实现机器人聊天,是偶然的情况下的,公司需要做一个ios版的机器人,用于自动购买东西,然后ios就研发了一个,我觉得这种机器人挺好玩的,想明白到底怎么实现,于是就上了百度,这东西是神器,果断需要好好利用利用。
一:老规矩,先上效果图
二:原理分析
1.接入图灵机器人api
2.根据api完成网络请求消息的发送和接收
3.完成布局界面
4.实现和小家伙的对话
三:实例切割(源码展示)
1.图灵机器人是一个非常强大,方便使用的平台,我们在实现智能机器人聊天的时候,便是依靠其强大的api,实现我们在聊天的功能,可以为我们聊天,解闷,打豆豆,呵呵。
图灵机器人接入api地址:http://www.tuling123.com/openapi/cloud/access_api.jsp
从图灵机器的网站,我们可以看出,他的一个请求方式,就一个get,一个组装url,然后就返回gson格式的数据,真简单,方便,照着它说的做,就ok了
2.api请求消息的接收和发送(工具类)
(1)配置类
package com.robot.tools; /** * 配置类 * * @author zengtao 2015年5月5日 下午7:59:42 */ public class Config { public static final String URL_KEY = "http://www.tuling123.com/openapi/api"; public static final String APP_KEY = "817259da4b7b4f105d1ca8d3072ed7ab"; }
(2)日期工具
package com.robot.tools; import android.annotation.SuppressLint; import java.text.SimpleDateFormat; import java.util.Date; /** * 时间格式化工具 * * @author zengtao 2015年5月6日 下午3:27:14 */ 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); } }
(3)http请求工具类
package com.robot.tools; 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; import com.google.gson.Gson; import com.robot.bean.ChatMessage; import com.robot.bean.ChatMessage.Type; import com.robot.bean.Result; /** * http工具类 * * @author zengtao 2015年5月5日 下午7:59:15 */ 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(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; } }
3.实体类的编写
(1)图灵机器人的返回结果
package com.robot.bean; /** * 映射服务器返回的结果 * * @author zengtao 2015年5月6日 上午9:50:52 */ 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; } }
(2)聊天信息的实体类
package com.robot.bean; import java.util.Date; /** * 聊天信息实体类 * * @author zengtao 2015年5月6日 上午9:47:01 */ 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 } }
4.布局的实现
(1)左面布局的实现
<?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" > <TextView android: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" /> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" > <LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="vertical" > <ImageView android:id="@+id/chat_left_image" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/icon" /> <TextView android: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> <TextView android:background="@drawable/chatfrom_bg_focused" android:gravity="center" android:textSize="16sp" android:layout_gravity="center_vertical" android:id="@+id/chat_left_message" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="您好。" /> </LinearLayout> </LinearLayout>
(2)聊天右边的布局
<?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" > <TextView android: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" /> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="right" android:orientation="horizontal" > <TextView android:id="@+id/chat_right_message" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_vertical" android:background="@drawable/chatto_bg_normal" android:gravity="center" android:text="can i help me ?" android:textSize="16sp" /> <LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="vertical" > <ImageView android:id="@+id/chat_right_image" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/me" /> <TextView android: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>
(3)主界面(聊天界面)布局
<?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/chat_bg_default" android:orientation="vertical" > <!-- 头部 --> <RelativeLayout android:id="@+id/chat_top" android:layout_width="match_parent" android:layout_height="50dp" android:background="@drawable/title_bar" > <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerInParent="true" android:text="小乖" android:textColor="#ffffff" android:textSize="18sp" /> </RelativeLayout> <!-- 底部 --> <RelativeLayout android:id="@+id/chat_bottom" android:layout_width="match_parent" android:layout_height="55dp" android:layout_alignParentBottom="true" android:background="@drawable/bottom_bar" > <EditText android:id="@+id/chat_input_message" android:layout_width="240dp" android:layout_height="wrap_content" android:layout_centerVertical="true" android:layout_marginLeft="5dp" android:background="@drawable/login_edit_normal" android:gravity="center" /> <Button 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:background="@drawable/chat_send_button" android:text="发送" android:textColor="#FFFFFF" android:textSize="18sp" /> </RelativeLayout> <!-- 中间 --> <ListView android: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>
5.聊天信息的适配器
package com.robot.adapter; import java.util.List; 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 com.robot.bean.ChatMessage; import com.robot.bean.ChatMessage.Type; import com.robot.tools.DateUtils; import com.robot.ui.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; } @Override public int getCount() { return list.isEmpty() ? 0 : list.size(); } @Override public Object getItem(int position) { return list.get(position); } @Override public long getItemId(int position) { return position; } @Override public int getItemViewType(int position) { ChatMessage chatMessage = list.get(position); // 如果是接收消息:0,发送消息:1 if (chatMessage.getType() == Type.INCOUNT) { return 0; } return 1; } @Override public int getViewTypeCount() { return 2; } @SuppressLint("InflateParams") @Override public 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.list_chat_left_item, 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.list_chat_right_item, 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; } }
6.主界面调用
package com.robot.ui; import java.util.ArrayList; import java.util.Date; import java.util.List; 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 com.robot.adapter.ChatMessageAdapter; import com.robot.bean.ChatMessage; import com.robot.bean.ChatMessage.Type; import com.robot.tools.HttpUtils; public class MainActivity 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; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); requestWindowFeature(Window.FEATURE_NO_TITLE); setContentView(R.layout.main_activity); 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("您好,小乖为您服务!", 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(MainActivity.this, "对不起,您还未发送任何消息", Toast.LENGTH_SHORT).show(); return; } // 2.自己输入的内容也是一条记录,记录刷新 ChatMessage sendChatMessage = new ChatMessage(); sendChatMessage.setMessage(send_message); sendChatMessage.setData(new Date()); sendChatMessage.setType(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() { @Override public void onClick(View v) { switch (v.getId()) { case R.id.chat_send: chat(); break; } } }; }
7.当然记得AndroidManifest.xml里面的权限问题
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.robot.ui" android:versionCode="1" android:versionName="1.0" > <uses-sdk android:minSdkVersion="8" android:targetSdkVersion="21" /> <uses-permission android:name="android.permission.INTERNET" /> <!-- 网络权限 --> <application android:allowBackup="true" android:icon="@drawable/icon" android:label="@string/app_name" android:theme="@style/AppTheme" > <uses-library android:name="android.test.runner" /> <!-- 测试环境 --> <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> <!-- 测试环境 --> <instrumentation android:name="android.test.InstrumentationTestRunner" android:label="this is a test " android:targetPackage="com.robot.ui" > </instrumentation> </manifest>
四:总结
以上呢,变KO了这个所谓的智能机器人,我们的小乖乖也就完成了,现在你就可以开始逗她玩了,想怎么玩就怎么玩,不过千万不要玩坏了,冒烟了就不好了,当然我们的小乖还可以增加很多功能,你可以选择增加语言功能功什么的,如果有实现的,跪求分享,我也好学习学习,每天撸一撸代码,一天一撸,十撸成神。
Demo下载地址:http://download.csdn.net/detail/u011546655/8725771