聊天接口是网上找的,我用的是图灵机器人,注册后拿到key值,然后,就可以动手下代码。
个人认为,聊天机器人最大的难点有三个
1、布局,要实现微信那样的聊天布局确实要花费一些功夫。
2、解析数据,楼主用的是谷歌的Gson解析,解析出数据以后,重要的是判断该数据是属于文字对话,新闻,菜谱,抑或是列车。
3、布局之间的转换,由于涉及到自己和机器人,所以listview里面至少要有三个布局(一个是自己,另一个是机器人,另一个当然是聊天界面啦),重写BaseAdapter方法,让布局在两个布局之间进行转换。
楼主的布局
主界面XML代码
<?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:layout_width="match_parent" android:layout_height="20pt" android:background="@drawable/title_bar" android:gravity="center" android:text="图灵机器人" android:textColor="#FFFFFF" android:textSize="10pt" /> <ListView android:id="@+id/listView" android:layout_width="match_parent" android:layout_height="0pt" android:layout_weight="1" android:divider="#00000000" android:fastScrollEnabled="true" android:listSelector="@android:color/transparent" android:scrollbarStyle="insideInset" android:transcriptMode="normal" > </ListView> <LinearLayout android:layout_width="match_parent" android:layout_height="25pt" android:background="@drawable/bottom_bar" android:gravity="center" android:orientation="horizontal" > <EditText android:id="@+id/editText" android:layout_width="fill_parent" android:layout_height="17pt" android:layout_marginLeft="3pt" android:layout_weight="1" android:background="@drawable/editext" android:paddingLeft="1pt" android:paddingRight="1pt" /> <Button android:id="@+id/button" android:layout_width="32pt" android:layout_height="20pt" android:layout_marginLeft="3pt" android:layout_marginRight="2pt" android:background="@drawable/button" android:text="确认" /> </LinearLayout> </LinearLayout>
聊天对话框代码
<?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:orientation="vertical" > <LinearLayout android:id="@+id/ly01" android:layout_width="match_parent" android:layout_height="10pt" android:gravity="center" > <TextView android:id="@+id/time" android:layout_width="wrap_content" android:layout_height="match_parent" android:layout_gravity="center" android:text="2015-9-18 21:07:56" /> </LinearLayout> <ImageButton android:id="@+id/immi" android:layout_width="25pt" android:layout_height="25pt" android:layout_alignParentRight="true" android:layout_below="@+id/ly01" android:background="@drawable/ic_launcher" /> <TextView android:id="@+id/text" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_toLeftOf="@+id/immi" android:layout_alignTop="@+id/immi" android:layout_marginTop="5pt" android:textSize="17sp" android:maxEms="10" android:singleLine="false" android:background="@drawable/chatto_bg_normal" android:text="窗前明月光,疑是地上霜。" /> </RelativeLayout>
效果图:
解析数据:
HttpURLConnection连接
package http; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.URL; public class HttpUtils { 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; } br.close(); } catch (MalformedURLException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } if (result == "") {//进行判空操作,如果没联网,会给<span style="font-family: Arial, Helvetica, sans-serif;">result重新赋值而不至于是空。</span> result = "{\"code\":100000,\"text\":\"亲!服务器到月球了!\"}"; } return result; } }
解析数据
楼主是直接在解析类里面定义了解析函数。
Talk是定义的数据存储类。
public static Talk getTalk(String json) { Gson gson = new Gson(); Talk talk = gson.fromJson(json, Talk.class); return talk; }
package com.rebot; import java.util.List; import com.google.gson.Gson; public class Talk { private int type = 0; // 0为机器人,1为自己 private int code; // 返回类型。 人默认为0 private String text; // 返回文字 private String time;// 发送时间 List<More> list; // 返回的list public Talk(int type, int code, String text, String time) { this.code = code; this.type = type; this.text = text; this.time = time; } public int getType() { return type; } public void setType(int type) { this.type = type; } 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; } public String getTime() { return time; } public void setTime(String time) { this.time = time; } public List<More> getList() { return list; } public void setList(List<More> list) { this.list = list; } public String toString() { return "type=" + type + ", code=" + code + ", text=" + text + "\n"; } public static Talk getTalk(String json) { Gson gson = new Gson(); Talk talk = gson.fromJson(json, Talk.class); return talk; } }
代码如下
package com.rebot; public class More { // -------------列车------------------ private String trainnum; // 车次 private String start; // 起始站 private String terminal; // 到达站 private String starttime; // 开车时间 private String endtime; // 到达时间 // --------公用------- private String detailurl; // 详情地址 private String icon; // 图标地址 // ------------------- public String getTrainnum() { return trainnum; } public void setTrainnum(String trainnum) { this.trainnum = trainnum; } public String getStart() { return start; } public void setStart(String start) { this.start = start; } public String getTerminal() { return terminal; } public void setTerminal(String terminal) { this.terminal = terminal; } public String getStarttime() { return starttime; } public void setStarttime(String starttime) { this.starttime = starttime; } public String getEndtime() { return endtime; } public void setEndtime(String endtime) { this.endtime = endtime; } public String getDetailurl() { return detailurl; } public void setDetailurl(String detailurl) { this.detailurl = detailurl; } public String getIcon() { return icon; } public void setIcon(String icon) { this.icon = icon; } public String getTrain() { return "车次:" + trainnum + "\n起始站:" + start + "\n到达站:" + terminal + "\n开车时间:" + starttime + "\n到达时间:" + endtime + "\n详情地址:" + detailurl + "\n图标地址:" + icon; } // --------------------------------------- // ------------------新闻-------------------- private String article; private String source; public String getArticle() { return article; } public void setArticle(String article) { this.article = article; } public String getSource() { return source; } public void setSource(String source) { this.source = source; } public String getNews() { return "标题:" + article + "\n来源" + source + "\n详情地址" + detailurl + "\n图标地址" + icon; } // ------------------菜谱---------------------- private String name; // 名称 private String info; // 详情 public String getName() { return name; } public void setName(String name) { this.name = name; } public String getInfo() { return info; } public void setInfo(String info) { this.info = info; } public String getMenu() { return "名称:" + name + "\n详情" + info + "\n详情地址" + detailurl + "\n图标地址" + icon; } }
主界面代码
package com.example.n.rebot02; import java.io.UnsupportedEncodingException; import java.net.URLEncoder; import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; import java.util.List; import http.HttpUtils; import com.rebot.Talk; import android.os.AsyncTask; import android.os.Bundle; import android.annotation.SuppressLint; import android.app.Activity; 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; public class MainActivity extends Activity { private ListView listView; private EditText editText; private Button button; private List<Talk> talks; private MyAsyncTask task; private MyAdapter adapter; @SuppressWarnings("serial") protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); requestWindowFeature(Window.FEATURE_NO_TITLE); setContentView(R.layout.main_layout); listView = (ListView) findViewById(R.id.listView); editText = (EditText) findViewById(R.id.editText); button = (Button) findViewById(R.id.button); talks = new ArrayList<Talk>() { { add(new Talk(0, 100000, "阿尼哈希哟!", printDate())); } }; adapter = new MyAdapter(MainActivity.this, talks); listView.setAdapter(adapter); // listView.setSelection(adapter.getCount()); // adapter.notifyDataSetChanged(); button.setOnClickListener(new OnClickListener() { public void onClick(View v) { String mi = editText.getText().toString(); // -----------添加自己-------------- Talk talk = new Talk(1, 100000, mi, printDate()); talks.add(talk); // ------------输入框设置为空--------------- editText.setText(""); System.out.println("==============talk:" + talk); // -----------启动AsyncTask--------- String APIKEY = "d0c05c50d03d541fc1571908b453452f"; String INFO = null; try { INFO = URLEncoder.encode(mi, "utf-8"); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } String getURL = "http://www.tuling123.com/openapi/api?key=" + APIKEY + "&info=" + INFO; // ------------------------------- adapter.notifyDataSetChanged(); listView.smoothScrollToPosition(listView.getCount() - 1); // ------------------------------- task = new MyAsyncTask(); task.execute(getURL); } }); } class MyAsyncTask extends AsyncTask<String, Void, List<Talk>> { @Override protected List<Talk> doInBackground(String... params) { // ---------------解析数据------------------ String json = HttpUtils.getJsonContent(params[0]); Talk talk = Talk.getTalk(json); // ----------------添加机器人---------------- System.out.println("------------talk" + talk); talk.setType(0); talk.setTime(printDate()); talks.add(talk); return talks; } protected void onPostExecute(List<Talk> result) { super.onPostExecute(result); adapter.notifyDataSetChanged(); listView.smoothScrollToPosition(listView.getCount() - 1); } } @SuppressLint("SimpleDateFormat") public static String printDate() { DateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); return format.format(new Date()); } }<strong> </strong>
package com.example.n.rebot02; import java.util.List; import com.rebot.Talk; import android.content.Context; import android.text.method.LinkMovementMethod; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.View.OnClickListener; import android.view.ViewGroup; import android.widget.BaseAdapter; import android.widget.ImageButton; import android.widget.TextView; import android.widget.Toast; public class MyAdapter extends BaseAdapter { private Context context; private List<Talk> talk; public MyAdapter(Context context, List<Talk> talk) { this.context = context; this.talk = talk; } public int getCount() { return talk.size(); } public Object getItem(int position) { return talk.get(position); } public long getItemId(int position) { return position; } public View getView(int position, View convertView, ViewGroup parent) { Talk talk1 = talk.get(position); View view = null; if (talk1.getType() == 1) { view = LayoutInflater.from(context).inflate(R.layout.mi_item, null); } else { view = LayoutInflater.from(context).inflate(R.layout.reboot_item, null); } TextView textView = (TextView) view.findViewById(R.id.text); TextView textView2 = (TextView) view.findViewById(R.id.time); switch (talk1.getCode()) { case 100000:<span style="white-space:pre"> </span>//判断返回类型,<span style="font-family: Arial, Helvetica, sans-serif;">100000为文字类聊天,</span><span style="font-family: Arial, Helvetica, sans-serif;">305000为列车</span><span style="font-family: Arial, Helvetica, sans-serif;"> </span> textView.setText(talk1.getText()); break; case 40002: textView.setText(talk1.getText()); break; case 305000: textView.setText(talk1.getText() + "\n" + talk1.getList().get(0).getTrain()); break; case 302000: textView.setText(talk1.getText() + "\n" + talk1.getList().get(0).getNews()); textView.setMovementMethod(LinkMovementMethod.getInstance()); break; case 308000: textView.setText(talk1.getText() + "\n" + talk1.getList().get(0).getMenu()); Log.i("main", talk1.getText() + "\n" + talk1.getList().get(0).getMenu()); break; default: break; } textView2.setText(talk1.getTime()); return view; } }<strong> </strong>
心得:
别忘了开网络权限!
别忘了开网络权限!
别忘了开网络权限!
(重要的事情说三遍)
ListView显示最后一行:
listView.smoothScrollToPosition(listView.getCount() - 1);
实时刷新ListView
adapter.notifyDataSetChanged();
去掉丑陋的标题头
requestWindowFeature(Window.FEATURE_NO_TITLE);
(这句话一定要写在super.onCreate(savedInstanceState);的下一行!)
第一次写博客,不足之处尚多,以后慢慢改进。
http://download.csdn.net/detail/jiaoyaning1210/9123123