Android聊天机器人
16lz
2021-01-26
今天做了一个小项目,就是Android自动聊天机器人的开发。主要的难点有:.图灵机器人API的解读和ListView多种item的实现
思考:
1.在ListView的每一项item中要放的数据是什么?
2.怎么把用于返回数据解析类的对象放在item的显示对象中。
3.提醒adapter有新数据了。
以下就是具体的代码实现:简单介绍一下各个函数的作用:
①MainActivity:在主线程中要实现发送按钮的监听事件,另外要创建一个异步任务实现网络数据的解析
②ChatMessageAdapter:继承于适配器BaseAdapter的类,用于向ListView中填充数据
③ChatMessage:定义ListView中要填充的内容
④Result类:因为该解析数据中没有第一级标题,所以就自定义Result类,其变量于Json解析出的变量保持一致,即是code和text
⑤HttpUtils:工具类,用于网络数据的解析
一、MainActivity
package org.mobiletrain.robot;import java.util.ArrayList;import java.util.Date;import java.util.List;import org.mobiletrain.robot.bean.ChatMessage;import org.mobiletrain.robot.bean.ChatMessage.Type;import org.mobiletrain.robot.http.HttpUtils;import android.app.Activity;import android.text.TextUtils;import android.view.View;import android.os.AsyncTask;import android.os.Bundle;import android.view.Window;import android.widget.Button;import android.widget.EditText;import android.widget.ListView;import android.widget.Toast;public class MainActivity extends Activity implements View.OnClickListener{private ListView listView;private EditText mInputText;private Button mSendButton;private ChatMessageAdapter adapter;private List<ChatMessage>mDatas;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);requestWindowFeature(Window.FEATURE_NO_TITLE);setContentView(R.layout.activity_main);listView = (ListView)this.findViewById(R.id.id_listview_msgs);mInputText = (EditText)this.findViewById(R.id.id_input_msg);mSendButton = (Button)this.findViewById(R.id.id_send_msg);initDate();mSendButton.setOnClickListener(this);}/** * 初始化ListView的第一行 */private void initDate() {mDatas = new ArrayList<ChatMessage>();ChatMessage chat = new ChatMessage("您好,我是蛋蛋,很高兴为您服务!!",new Date(),Type.INCOMING);mDatas.add(chat);adapter = new ChatMessageAdapter(this, mDatas);listView.setAdapter(adapter);}/** * 设置按钮点击事件 *@Override */public void onClick(View v) {//1.点击之后获取edittext的值,判读一下是否为空,如果是空的,就提示用户。String msg = mInputText.getText().toString();if (TextUtils.isEmpty(msg)) {Toast.makeText(MainActivity.this, "输入数据不能为空", Toast.LENGTH_SHORT).show();}ChatMessage toMessage = new ChatMessage();toMessage.setDate(new Date());toMessage.setMessage(msg);toMessage.setType(Type.OUTCOMING);mDatas.add(toMessage);//提醒适配器更新数据adapter.notifyDataSetChanged();mInputText.setText("");new ChatMessageTask().execute(msg);}/** * 这是解析出来的数据格式 * { * code : 123 * text : 好开心呀,有吃成长快乐了。。。 * } * 定义异步任务实现数据的解析 * */class ChatMessageTask extends AsyncTask<String, Void, ChatMessage>{@Overrideprotected ChatMessage doInBackground(String... params) {ChatMessage chat = HttpUtils.sendMessage(params[0]);return chat;}@Overrideprotected void onPostExecute(ChatMessage result) {super.onPostExecute(result);mDatas.add(result);//提醒适配器更新数据adapter.notifyDataSetChanged();}}}二、ChatMessageAdapter适配器
package org.mobiletrain.robot;import java.text.SimpleDateFormat;import java.util.List;import org.mobiletrain.robot.bean.ChatMessage;import org.mobiletrain.robot.bean.ChatMessage.Type;import android.content.Context;import android.view.LayoutInflater;import android.view.View;import android.view.ViewGroup;import android.widget.BaseAdapter;import android.widget.TextView;/** * 定义ChatMessageAdapter适配器继承BaseAdapter * @author Administrator * */public class ChatMessageAdapter extends BaseAdapter{private List<ChatMessage>mDatas;private LayoutInflater mInflater;public ChatMessageAdapter(Context context,List<ChatMessage>mDatas){this.mInflater = LayoutInflater.from(context);this.mDatas = mDatas;}@Overridepublic int getCount() {return mDatas.size();}@Overridepublic Object getItem(int position) {return mDatas.get(position);}@Overridepublic long getItemId(int position) {return position;}/** * 协定listview中有几种类型的item *@Override */public int getViewTypeCount() {return 2;}/** * 判断枚举Type的类型然后确定填充数据的布局 * @Override */public int getItemViewType(int position) {ChatMessage chatMessage = mDatas.get(position);if (chatMessage.getType() == Type.OUTCOMING) {return 0;}return 1;}@Overridepublic View getView(int position, View convertView, ViewGroup parent) {ViewHolder vh;//如果converView为空,就去找到布局文件并填充内容if (convertView==null) {//判断Type的类型,如果为0代表用户输入,则convertView填充的数据界面为ListView的右边if (getItemViewType(position)==0) {convertView = mInflater.inflate(R.layout.item_to_msg, null);vh = new ViewHolder();vh.tv_date = (TextView)convertView.findViewById(R.id.id_to_msg_date);vh.tv_message=(TextView)convertView.findViewById(R.id.id_to_msg_info);}else {convertView = mInflater.inflate(R.layout.item_from_msg, null);vh = new ViewHolder();vh.tv_date = (TextView)convertView.findViewById(R.id.id_form_msg_date);vh.tv_message=(TextView)convertView.findViewById(R.id.id_from_msg_info);}convertView.setTag(vh);}else{vh = (ViewHolder)convertView.getTag();}//向ListView中填充数据ChatMessage data = mDatas.get(position);SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");vh.tv_date.setText(df.format(data.getDate()));vh.tv_message.setText(data.getMessage());return convertView;}/** *定义ViewHolder实现ListView的优化 * @author Administrator * */class ViewHolder{TextView tv_date;TextView tv_message;}}三、ChatMessage类
package org.mobiletrain.robot.bean;import java.util.Date;/** * 定义获取输入的内容的类 * @author Administrator * */public class ChatMessage {private String message;private String name;private Date date;private Type type;public void setType(Type type) {this.type = type;}public Type getType() {return type;}//枚举:是一种新型的变量,他可以控制设定的内容public enum Type{OUTCOMING,INCOMING}public String getMessage() {return message;}public void setMessage(String message) {this.message = message;}public String getName() {return name;}public void setName(String name) {this.name = name;}public Date getDate() {return date;}public void setDate(Date date) {this.date = date;}public ChatMessage(String message, Date date, Type type) {super();this.message = message;this.date = date;this.type = type;}public ChatMessage() {// TODO Auto-generated constructor stub}}
四、与解析内容相匹配的自定义Result类
package org.mobiletrain.robot.bean;/** * 解析结果的格式 * @author Administrator * */public class Result {private String code;private String text;public String getCode() {return code;}public String getText() {return text;}public void setCode(String code) {this.code = code;}public void setText(String text) {this.text = text;}}
五、解析工具类:HttpUtils
package org.mobiletrain.robot.http;import java.io.BufferedInputStream;import java.io.BufferedReader;import java.io.ByteArrayOutputStream;import java.io.IOException;import java.io.InputStream;import java.io.InputStreamReader;import java.io.UnsupportedEncodingException;import java.net.HttpURLConnection;import java.net.MalformedURLException;import java.net.URL;import java.net.URLEncoder;import java.util.Date;import org.apache.http.HttpResponse;import org.apache.http.client.ClientProtocolException;import org.apache.http.client.HttpClient;import org.apache.http.client.methods.HttpGet;import org.apache.http.impl.client.DefaultHttpClient;import org.apache.http.util.EntityUtils;import org.mobiletrain.robot.bean.ChatMessage;import org.mobiletrain.robot.bean.ChatMessage.Type;import org.mobiletrain.robot.bean.Result;import com.google.gson.Gson;import com.google.gson.JsonSyntaxException;import android.R.string;/** * 联网工具类,用于连接网络,取得数据 * */public class HttpUtils {// 图灵机器人使用api的公网地址public static final String URL = "http://www.tuling123.com/openapi/api";// 申请的apiKeypublic static final String API_KEY = "be12dd3c0bac3654e78aa69e4b36a6dd";/** * 通过HttpURLConnection解析Json数据,返回结果是一个字符串 * @param url * @return */public static String getJsonContent(String url) {String result = "";URL url2;InputStream is;InputStreamReader isr;BufferedReader br;try {url2 = new URL(url);HttpURLConnection connection = (HttpURLConnection) url2.openConnection();is = connection.getInputStream();isr = new InputStreamReader(is, "utf-8");String line = "";br = new BufferedReader(isr);while ((line = br.readLine()) != null) {result += line;}try {br.close();} catch (IOException e) {e.printStackTrace();}} catch (MalformedURLException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}return result;}/** * 通过HttpClient解析Json数据,返回结果是一个字符串 * @param url * @return */public static String getJsonContent2(String url) {String result = "";HttpClient httpClient = new DefaultHttpClient();HttpGet httpGet = new HttpGet(url);HttpResponse response = null;try {response = httpClient.execute(httpGet);if (response.getStatusLine().getStatusCode() == 200) {result = EntityUtils.toString(response.getEntity(), "utf-8");}} catch (ClientProtocolException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}return result;}/** * 解析Json数据,返回结果是一个byte[]数组,一般用于解析网络图片 * @param url * @return */public static byte[] getByteContent2(String url) {byte[] data = null;HttpClient httpClient = new DefaultHttpClient();HttpGet httpGet = new HttpGet(url);HttpResponse response = null;try {response = httpClient.execute(httpGet);if (response.getStatusLine().getStatusCode() == 200) {data = EntityUtils.toByteArray(response.getEntity());}return data;} catch (ClientProtocolException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}return data;}/** * 通过HttpURLConnection解析Json数据,返回结果也是一个byte[]类型的数组 * @param url * @return */public static byte[] getByteContent(String url) {try {URL url2 = new URL(url);HttpURLConnection httpConn = (HttpURLConnection) url2.openConnection();httpConn.setDoInput(true); // 允许输入内容httpConn.setDoOutput(false);httpConn.connect();ByteArrayOutputStream baos = new ByteArrayOutputStream();if (httpConn.getResponseCode() == 200) {BufferedInputStream bis = new BufferedInputStream(httpConn.getInputStream());byte[] buffer = new byte[8 * 1024];int c = 0;while ((c = bis.read(buffer)) != -1) {baos.write(buffer, 0, c);baos.flush();}byte[] data = baos.toByteArray();return data;}} catch (Exception e) {e.printStackTrace();}return null;}/** * 拼接接口,其中参数为用户输入传来的内容 */public static String setParams(String msg){String url = "";try { url = URL +"?key="+API_KEY+"&info="+URLEncoder.encode(msg, "UTF-8");} catch (UnsupportedEncodingException e) {e.printStackTrace();}return url;}/** * 解析Json数据,返回类型是一个ChatMessage对象 * @param msg * @return */public static ChatMessage sendMessage(String msg){ChatMessage chatMessage = new ChatMessage();String jsonRes = getJsonContent(setParams(msg));Gson gson = new Gson();Result result = null;try {result = gson.fromJson(jsonRes, Result.class);chatMessage.setMessage(result.getText());} catch (JsonSyntaxException e) {chatMessage.setMessage("服务器繁忙,请稍后再试");}chatMessage.setDate(new Date());chatMessage.setType(Type.INCOMING);return chatMessage;}}下面就是实现的效果图:
初始界面:
聊天界面:
更多相关文章
- Android(安卓)ApiDemos示例解析(134):Views->Layouts->Baseline-
- Android(安卓)Okhttp断点续传面试深入解析
- Android(安卓)消息推送:第三方消息推送平台 详细解析
- Unity调用Android(安卓)jar包方法——(三、使用UnitySendMessage
- [置顶] 解析android 流量监测的实现原理
- android Adapter体系
- Android之EasyPermissions源码解析
- ArcGIS for Android(安卓)离线数据图例加载
- Android数据类型之间相互转换系统介绍