今天我们来分享一个有趣的应用:Android版的智能聊天机器人
开发工具:Eclipse
开发时间:2015/07/07
所用技术:图灵机器人API 网络通信之异步请求 接口回调 自定义Adapter
下面我将详细叙述开发的步骤:
第一步:申请图灵机器人的API KEY
方法很简单,只需要在图灵机器人API官网注册一个账号,注册成功之后,会显示一个API KEY
图灵机器人API 账号注册网址:图灵机器人
注册成功后,点击平台接入,认真看一下API接入的流程
第二步:开始创建工程进行编码,首先,新建一个class,用作异步请求图灵机器人API,获取返回信息
以下是我的HttpData 的源码:
1 package com.oysd.tuling; 2 3 import java.io.BufferedReader; 4 import java.io.InputStream; 5 import java.io.InputStreamReader; 6 7 import org.apache.http.HttpEntity; 8 import org.apache.http.HttpResponse; 9 import org.apache.http.client.methods.HttpGet; 10 import org.apache.http.impl.client.DefaultHttpClient; 11 12 import android.os.AsyncTask; 13 14 public class HttpData extends AsyncTask<String, Void, String> { 15 16 private DefaultHttpClient mHttpClient; 17 private HttpGet mHttpGet; 18 private String url; 19 private HttpResponse mHttpResponse;//获取Http请求的返回 20 private HttpEntity mHttpEntity;//创建Http实体 21 private InputStream in;//将获取的数据转换成流文件来处理 22 private HttpGetDataListener listener; 23 24 public HttpData(String url,HttpGetDataListener listener){ 25 this.url = url; 26 this.listener = listener; 27 } 28 29 @Override 30 protected String doInBackground(String... arg0) { 31 // TODO Auto-generated method stub 32 try{ 33 mHttpClient = new DefaultHttpClient(); 34 mHttpGet = new HttpGet(url); 35 mHttpResponse = mHttpClient.execute(mHttpGet);//通过客户端来进行发送 36 mHttpEntity = mHttpResponse.getEntity();//通过Response对象获取数据 37 in = mHttpEntity.getContent();//通过Http的实体来获取具体的内容 38 //通过缓存区进行读取 39 BufferedReader br = new BufferedReader(new InputStreamReader(in)); 40 String line = null; 41 StringBuffer sb = new StringBuffer(); 42 while((line = br.readLine()) != null){ 43 sb.append(line); 44 } 45 return sb.toString(); 46 47 }catch(Exception e){ 48 e.printStackTrace(); 49 50 } 51 52 53 return null; 54 } 55 56 @Override 57 protected void onPostExecute(String result) { 58 listener.getDataUrl(result); 59 super.onPostExecute(result); 60 } 61 62 63 }
其中,我添加了一个接口类,为了让主类能够获取到这个异步申请返回的result
以下是我的接口类(里面就一个方法,只是学习一下这种逻辑,勿喷……):
1 package com.oysd.tuling; 2 3 public interface HttpGetDataListener { 4 void getDataUrl(String data); 5 }
当我们自己发的消息以及我们自己的开发API KEY 都获取之后发给图灵机器人API,就可以获取到json数据了,
在主类中MainActivity实现了json数据的解析(此json的格式非常简单,通过JSonObject直接就能解析)
以下是MainActivity的代码:
1 package com.oysd.tuling; 2 3 import java.text.SimpleDateFormat; 4 import java.util.ArrayList; 5 import java.util.Date; 6 import java.util.List; 7 8 import org.json.JSONException; 9 import org.json.JSONObject; 10 11 import android.app.Activity; 12 import android.os.Bundle; 13 import android.util.Log; 14 import android.view.Menu; 15 import android.view.MenuItem; 16 import android.view.View; 17 import android.view.View.OnClickListener; 18 import android.widget.Button; 19 import android.widget.EditText; 20 import android.widget.ListView; 21 22 public class MainActivity extends Activity implements HttpGetDataListener, OnClickListener{ 23 24 private static final String URL = "http://www.tuling123.com/openapi/api?"; 25 private static final String KEY = "ae3ecf47d74a8904cc7e527eece961e6"; 26 private static final String TAG = "TuLingMain"; 27 //String info = "深圳今天天气"; 28 private HttpData httpData; 29 private List<ListData> lists; 30 private ListView lv; 31 private EditText sendText; 32 private Button btnSend; 33 private TextAdapter adapter; 34 private String [] welcome_array; 35 private String content_str; 36 private double currentTime,oldTime = 0; 37 38 39 @Override 40 protected void onCreate(Bundle savedInstanceState) { 41 super.onCreate(savedInstanceState); 42 setContentView(R.layout.activity_main); 43 initView(); 44 //String url = getUrl(info); 45 } 46 47 private void initView(){ 48 //Log.d(TAG,getTime()); 49 lv = (ListView) findViewById(R.id.lv); 50 sendText = (EditText) findViewById(R.id.sendText); 51 btnSend = (Button) findViewById(R.id.btnSend); 52 lists = new ArrayList<ListData>(); 53 btnSend.setOnClickListener(this); 54 adapter = new TextAdapter(lists, this);//承接上下文 55 lv.setAdapter(adapter); 56 ListData listData; 57 listData = new ListData(getRondomWelcomeTips(), ListData.REVEIVER,getTime()); 58 lists.add(listData); 59 } 60 61 private String getUrl(String msg){ 62 String str = URL + "key=" + KEY + "&info=" + msg; 63 return str; 64 } 65 66 private String getRondomWelcomeTips(){ 67 String welcome_tip = null; 68 welcome_array = this.getResources().getStringArray(R.array.welcome_tips); 69 int index = (int) (Math.random()*(welcome_array.length - 1)); 70 welcome_tip = welcome_array[index]; 71 return welcome_tip; 72 } 73 @Override 74 public void getDataUrl(String data) { 75 // TODO Auto-generated method stub 76 parseText(data); 77 } 78 79 private void parseText(String str){ 80 81 try { 82 JSONObject jb = new JSONObject(str); 83 ListData listData; 84 listData = new ListData(jb.getString("text"),ListData.REVEIVER,getTime()); 85 lists.add(listData); 86 adapter.notifyDataSetChanged();//重新适配 87 88 } catch (JSONException e) { 89 // TODO Auto-generated catch block 90 e.printStackTrace(); 91 } 92 93 } 94 95 @Override 96 public void onClick(View arg0) { 97 //getTime(); 98 content_str = sendText.getText().toString(); 99 sendText.setText("");//发送之后,将输入框清空 100 //点击的时候需要添加重新适配的代码 101 String doTrim = content_str.replace(" ", "");//处理空格的问题 102 String doEnter = doTrim.replace("\n", "");//处理回车的问题 103 ListData listData; 104 listData = new ListData(content_str, ListData.SEND,getTime()); 105 lists.add(listData); 106 if(lists.size() > 30){ 107 for(int i = 0 ;i < lists.size() -20 ; i++){ 108 lists.remove(i); 109 } 110 } 111 adapter.notifyDataSetChanged( );//不要忘记刷新 112 113 httpData = (HttpData) new HttpData(getUrl(content_str), this).execute(); 114 115 } 116 117 private String getTime(){ 118 currentTime = System.currentTimeMillis(); 119 SimpleDateFormat format = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss"); 120 Date curDate = new Date(); 121 String str = format.format(curDate); 122 int sjc = (int) (currentTime - oldTime); 123 Log.d(TAG, "" + sjc); 124 125 if((currentTime - oldTime) >= 5*1000*60){ 126 oldTime = currentTime; 127 return str; 128 }else{ 129 return ""; 130 } 131 } 132 }
其中有很多ListView,我们需要自己定义个Adapter,
新建一个TextAdapter 扩展至BaseAdapter:
1 package com.oysd.tuling; 2 3 import java.util.List; 4 5 import android.content.Context; 6 import android.view.LayoutInflater; 7 import android.view.View; 8 import android.view.ViewGroup; 9 import android.widget.BaseAdapter; 10 import android.widget.RelativeLayout; 11 import android.widget.TextView; 12 13 public class TextAdapter extends BaseAdapter { 14 15 private List<ListData> lists; 16 private Context mContext; 17 private RelativeLayout layout; 18 public TextAdapter(List<ListData> lists,Context context){ 19 this.lists = lists; 20 this.mContext = context; 21 } 22 @Override 23 public int getCount() { 24 return lists.size(); 25 } 26 27 @Override 28 public Object getItem(int position) { 29 return lists.get(position); 30 } 31 32 @Override 33 public long getItemId(int position) { 34 return position; 35 } 36 37 @Override 38 public View getView(int position, View convertView, ViewGroup parent) { 39 40 LayoutInflater inflater = LayoutInflater.from(mContext); 41 42 if(lists.get(position).getFlag() == ListData.REVEIVER){ 43 layout = (RelativeLayout) inflater.inflate(R.layout.leftitem, null); 44 45 } 46 47 if(lists.get(position).getFlag() == ListData.SEND){ 48 layout = (RelativeLayout) inflater.inflate(R.layout.rightitem, null); 49 } 50 TextView tv = (TextView) layout.findViewById(R.id.tv); 51 tv.setText(lists.get(position).getContent()); 52 TextView time = (TextView) layout.findViewById(R.id.time); 53 time.setText(lists.get(position).getTime()); 54 return layout; 55 } 56 57 }
其中需要涉及到数据的封装,以下是我的封装类:
1 package com.oysd.tuling; 2 3 public class ListData { 4 5 public static final int SEND = 1; 6 public static final int REVEIVER = 2; 7 private String content; 8 private String time; 9 private int flag; 10 11 public ListData(String content,int flag,String time){ 12 setContent(content); 13 setFlag(flag); 14 setTime(time); 15 } 16 17 public String getContent() { 18 return content; 19 } 20 21 public void setContent(String content) { 22 this.content = content; 23 } 24 25 public int getFlag() { 26 return flag; 27 } 28 29 public void setFlag(int flag) { 30 this.flag = flag; 31 } 32 33 public String getTime() { 34 return time; 35 } 36 37 public void setTime(String time) { 38 this.time = time; 39 } 40 41 42 }
功能比较简单,以上涉及到的布局文件如下:
首先是主界面的布局文件:
1 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 2 xmlns:tools="http://schemas.android.com/tools" 3 android:layout_width="match_parent" 4 android:layout_height="match_parent" 5 android:orientation="vertical" 6 > 7 8 <ListView 9 android:layout_width="fill_parent" 10 android:layout_height="0dp" 11 android:layout_weight="1" 12 android:transcriptMode="alwaysScroll" 13 android:id="@+id/lv" 14 android:divider="@null" 15 android:listSelector="@android:color/transparent"> 16 </ListView> 17 18 <LinearLayout 19 android:layout_width="fill_parent" 20 android:layout_height="wrap_content" 21 android:orientation="horizontal" 22 android:focusable="true" 23 android:focusableInTouchMode="true"> 24 25 <EditText 26 android:id="@+id/sendText" 27 android:layout_width="0dp" 28 android:layout_weight="1" 29 android:layout_height="wrap_content"/> 30 31 <Button 32 android:id="@+id/btnSend" 33 android:layout_width="wrap_content" 34 android:layout_height="wrap_content" 35 android:text="@string/send" 36 /> 37 </LinearLayout> 38 39 </LinearLayout>
然后是每一个单独的ListView的布局,就是图灵机器人发送时的显示,以及我们自己发送时的显示,分左右两边
以下是leftitem布局:
1 <?xml version="1.0" encoding="utf-8"?> 2 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 3 android:layout_width="match_parent" 4 android:layout_height="match_parent" > 5 6 7 <TextView 8 android:id="@+id/time" 9 android:layout_width="fill_parent" 10 android:layout_height="wrap_content" 11 android:gravity="center_horizontal" 12 /> 13 <ImageView 14 android:layout_below="@id/time" 15 android:id="@+id/iv" 16 android:layout_width="70dp" 17 android:layout_height="70dp" 18 android:padding="10dp" 19 android:src="@drawable/rabot2"/> 20 21 <TextView 22 android:layout_below="@id/time" 23 android:id="@+id/tv" 24 android:layout_marginRight="60dp" 25 android:layout_width="wrap_content" 26 android:layout_height="wrap_content" 27 android:layout_alignBottom="@+id/iv" 28 android:layout_toRightOf="@+id/iv" 29 android:background="@drawable/chatfrom_bg_normal" 30 android:gravity="left" /> 31 32 </RelativeLayout>
然后是rightitem布局:
1 <?xml version="1.0" encoding="utf-8"?> 2 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 3 android:layout_width="match_parent" 4 android:layout_height="match_parent" > 5 6 7 <TextView 8 android:id="@+id/time" 9 android:layout_width="fill_parent" 10 android:layout_height="wrap_content" 11 android:gravity="center_horizontal" 12 /> 13 14 <ImageView 15 android:layout_below="@id/time" 16 android:layout_alignParentRight="true" 17 android:id="@+id/iv" 18 android:layout_width="70dp" 19 android:layout_height="70dp" 20 android:padding="10dp" 21 android:src="@drawable/rabot1"/> 22 23 <TextView 24 android:layout_below="@id/time" 25 android:id="@+id/tv" 26 android:layout_marginLeft="60dp" 27 android:layout_width="wrap_content" 28 android:layout_height="wrap_content" 29 android:layout_alignBottom="@+id/iv" 30 android:layout_toLeftOf="@+id/iv" 31 android:background="@drawable/chatto_bg_normal" 32 android:gravity="left" /> 33 34 </RelativeLayout>
到这里,智能聊天机器人的小应用开发完成,如果需要下载整个项目的,请点这里
时间: 2024-10-10 06:19:07