昨天写了一个简单的聊天机器人,只是完成了文字类的对话,关于查询的还么有做,今天整理了一下发上来,我不是一个大牛,只是希望给学习者一点小小的能量。
1.以下是机器人部分的布局,我用了RelativeLayout布局,开始写的是LinearLayOut,由于编译器的问题出现了错位,我费了好大劲去看我的代码没有错,人不能吊死在一棵树上,我换种方式就OK了。用户部分的布局与这个基本类似,我就不发了。
<span style="font-size:14px;"><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<TextView
android:id="@+id/date"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_marginBottom="3dp"
android:background="#ccc"
android:text="2015-09-17 12:23:12" />
<RelativeLayout
android:id="@+id/relayout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/date">
<ImageView
android:id="@+id/egg"
android:layout_width="50dp"
android:layout_height="50dp"
android:src="@drawable/head3"/>
<TextView
android:id="@+id/eggname"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="17sp"
android:layout_below="@+id/egg"
android:text="小友子"/>
</RelativeLayout>
<TextView
android:id="@+id/eggtalk"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toRightOf="@+id/relayout"
android:layout_below="@+id/date"
android:background="@drawable/chatfrom_bg_normal"
android:text="您好,小友为您服务!!!" />
</RelativeLayout>
</span>
2.MainActivity的布局,也很简单,主要就是一个ListView 和输入框和发送按钮
<span style="font-size:14px;"><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/ic_03"
tools:context=".MainActivity" >
<TextView
android:id="@+id/title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="小友"
android:gravity="center_horizontal"
android:textSize="25sp"
android:textColor="#FFFFFF"
android:background="@drawable/title_bar" />
<ListView
android:id="@+id/chat_content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_above="@+id/bottom"
android:layout_below="@+id/title"
>
</ListView>
<LinearLayout
android:id="@+id/bottom"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:background="@drawable/bottom_bar"
android:orientation="horizontal"
android:padding="10dp" >
<EditText
android:id="@+id/input_et"
android:layout_width="230dp"
android:layout_height="match_parent"
android:background="@drawable/send_btn_normal"
android:text="你好"
android:textSize="15sp" />
<Button
android:id="@+id/send"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="发送"
android:layout_marginLeft="5dp"
android:textSize="20sp" />
</LinearLayout>
</RelativeLayout></span>
3.下面是一个聊天信息类,包含谁说的话,说话内容,时间。注意枚举类型的定义和date类型的转换。
<span style="font-size:14px;">public class ChatMessage {
private String message;
private String name;
private Date date;
private String datestr;
public String getDatestr() {
return datestr;
}
public void setDatestr(String datestr) {
this.datestr = datestr;
}
public enum Type{ //定义一个枚举,判断是谁说的话
OUTCOMING,INCOMING //OUTCOMING代表我,INCOMING代表机器人
}
private Type type; //type只有以上两种取值
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) { //date.setDate(New Data())可以放入输入时间的固定格式字符串
this.date = date;
DateFormat dFormat=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
this.datestr=dFormat.format(date);
}
public Type getType() {
return type;
}
public void setType(Type type) {
this.type = type;
}
public ChatMessage(){
}
public ChatMessage(Type type,String msg){ //构造函数
super();
this.type=type;
this.message=msg;
setDate(new Date());
}
}
</span>
4.Result类主要是机器人返回参数code和text,这是图灵机器人规定的格式,是文字类必有有的,当然如果要添加别的内容,参数也要增加。
<span style="font-size:14px;">/*
* 机器人返回的内容
* 文字类的返回参数(Json格式)是状态码code和 文字内容 text
*/
public class Result {
private int 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;
}
}
</span>
5.连接网络的代码
<span style="font-size:14px;">public class HttpUtils {
private static String API_KEY="6726dcae3e70bad48df7834dd722c200";
private static String URL="http://www.tuling123.com/openapi/api";
/*
* 得到机器人返回的消息
*/
public static ChatMessage sendMsg(String msg){
ChatMessage message = new ChatMessage();
String url=setParams(msg);
String res =doGet(url);
Gson gson=new Gson();
Result result = gson.fromJson(res,Result.class); //gson解析
if (result.getCode()!=100000||result.getText()==null||result.getText().trim().equals("")){
message.setMessage("哎。。我的功能也是有限的啊");
}else {
message.setMessage(result.getText());
}
message.setType(Type.INCOMING);
message.setDate(new Date());
return message;
}
/*
* 拼接URL
*/
private static String setParams(String msg){
try {
msg=URLEncoder.encode(msg,"UTF-8"); //用此方法对String类型的msg进行转码成utf—8
} catch (UnsupportedEncodingException e) {
e.printStackTrace();<pre name="code" class="java">}
return URL+"?key="+API_KEY+"&info="+msg; //URL格式
}
/*
* get请求,获得返回数据
*/
private static String doGet(String urlStr){
String result = "";
URL url2;
InputStream is;
InputStreamReader isr;
BufferedReader br;
try {
url2 = new URL(urlStr);
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();
System.out.println("网络异常");
} catch (IOException e) {
e.printStackTrace();
}
return result;
}
}
</pre><span style="font-size:14px"><br />6.自定义一个Adapter类<br /></span><p></p><pre>
<span style="font-family: Arial, Helvetica, sans-serif;"> //LayoutInflater是用来找layout下的xml布局文件,并且实例化;</span>
//对于一个没有被载入或者想要动态载入的界面,都需要使用LayoutInflater.inflate()来载入;
private LayoutInflater mInflater;
private Context context;
private List<ChatMessage> datas;
public MessageAdapter(Context context,List<ChatMessage> datas){
this.context=context;
this.datas=datas;
mInflater=LayoutInflater.from(context);
}
@Override
public int getCount() {
// TODO Auto-generated method stub
return datas.size();
}
@Override
public Object getItem(int arg0) {
// TODO Auto-generated method stub
return datas.get(arg0);
}
@Override
public long getItemId(int arg0) {
// TODO Auto-generated method stub
return arg0;
}
@Override
public int getItemViewType(int position) {
ChatMessage msg=datas.get(position);
return msg.getType()==Type.INCOMING?1:0; //机器人输出的type为1,人输出的为0
}
//协定ListView中有几种类型的item
@Override
public int getViewTypeCount() {
return 2;
}
@Override
public View getView(int position, View converView, ViewGroup parent) {
ChatMessage message = datas.get(position);
ViewHolder vh = null;
if (converView==null) {
if (message.getType()==Type.OUTCOMING) {
converView = mInflater.inflate(R.layout.me_talk,null);
vh=new ViewHolder();
vh.date=(TextView)converView.findViewById(R.id.date);
vh.content=(TextView)converView.findViewById(R.id.metalk);
converView.setTag(vh);
}else if (message.getType()==Type.INCOMING) {
converView=mInflater.inflate(R.layout.agg_talk, null);
vh=new ViewHolder();
vh.date=(TextView)converView.findViewById(R.id.date);
vh.content=(TextView)converView.findViewById(R.id.eggtalk);
converView.setTag(vh);
}
}else {
vh=(ViewHolder)converView.getTag();
}
vh.content.setText(message.getMessage());
vh.date.setText(message.getDatestr());
return converView;
}
class ViewHolder{
TextView date;
TextView content;
}
}
</span>
7.Mainactivity
<span style="font-size:14px;">public class MainActivity extends Activity {
private ListView message;
private EditText input_message;
private Button send;
private String msg;
private List<ChatMessage> datas=new ArrayList<ChatMessage>(); //存储聊天信息
private MessageAdapter adapter;
private MyTask task;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
requestWindowFeature(Window.FEATURE_NO_TITLE); //隐藏窗体标题栏,全屏显示
message = (ListView)findViewById(R.id.chat_content);
input_message=(EditText)findViewById(R.id.input_et);
send=(Button)findViewById(R.id.send);
datas.add(new ChatMessage(Type.INCOMING,"祝小友子生日快乐")); //设置机器人输出的第一句话
send.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
msg=input_message.getText().toString(); //获取输入内容
if (TextUtils.isEmpty(msg)) { //TextUtils类对字符串进行处理,此处判断输入是否为空
Toast.makeText(MainActivity.this, "你还没输入信息", Toast.LENGTH_LONG).show();
return;
}
ChatMessage to=new ChatMessage(Type.OUTCOMING,msg);
to.setDate(new Date());
datas.add(to);
adapter.notifyDataSetChanged(); //更新数据
message.setSelection(datas.size()-1); //将列表移动到指定的Position处。
input_message.setText("");
task=new MyTask();
task.execute(msg);
}
});
adapter=new MessageAdapter(MainActivity.this, datas);
message.setAdapter(adapter);
}
//返回一个CharMessage对象
class MyTask extends AsyncTask<String, Void, ChatMessage>{
@Override
protected ChatMessage doInBackground(String... arg0) {
ChatMessage from = null;
try {
from=HttpUtils.sendMsg(arg0[0]);
} catch (Exception e) {
from=new ChatMessage(Type.INCOMING,"哎呀,我的服务器挂啦!");
}
return from;
}
@Override
protected void onPostExecute(ChatMessage result) {
super.onPostExecute(result);
datas.add(result);
adapter.notifyDataSetChanged();
message.setSelection(datas.size()-1);
}
}
}
</span>
8.最后,不要忘了连网操作!