Android案例练习(一)——智能机器人
案例来自慕课网 http://www.imooc.com/,采用Eclipse编写。
一、本案例使用的知识:
1.第三方API图灵机器人的API。
2.ListView多种Item布局时的处理,实现聊天对话的界面
二、目录结构
三、编写过程:
1.编写一个工具类,实现消息的发送与接收
建立包com.example.util,在包下建立HttpUtils.java类,代码如下。
1 package com.example.util; 2 /* 3 * 发送一个消息,得到一个返回的消息 4 */ 5 import java.io.ByteArrayOutputStream; 6 import java.io.IOException; 7 import java.io.InputStream; 8 import java.io.UnsupportedEncodingException; 9 import java.net.HttpURLConnection; 10 import java.net.MalformedURLException; 11 import java.net.URLEncoder; 12 import java.util.Date; 13 14 import com.example.bean.ChatMessage; 15 import com.example.bean.ChatMessage.Type; 16 import com.example.bean.Result; 17 import com.google.gson.Gson; 18 19 public class HttpUtils { 20 private static final String URL="http://www.tuling123.com/openapi/api"; 21 //固定的uri,指定往哪里发送请求 22 private static final String API_KEY="ba5637dd0b34bab9322c7c61317cee5a"; 23 public static String doGet(String msg){ 24 String result=""; 25 String url=setParams(msg);//为URL设置参数 26 InputStream is=null; 27 ByteArrayOutputStream baos=null; 28 29 try { 30 java.net.URL urlNet=new java.net.URL(url); 31 HttpURLConnection conn=(HttpURLConnection) urlNet.openConnection(); 32 conn.setReadTimeout(5*1000); 33 conn.setConnectTimeout(5*1000); 34 conn.setRequestMethod("GET");//conn参数设置 35 36 is=conn.getInputStream(); 37 int len=-1; 38 byte[] buf=new byte[128];//设置128字节缓冲区 39 baos=new ByteArrayOutputStream(); 40 41 while((len=is.read(buf)) !=-1){ 42 baos.write(buf,0,len); 43 } 44 baos.flush(); 45 46 result=new String(baos.toByteArray()); 47 } catch (MalformedURLException e) { 48 // TODo 自动生成的 catch 块 49 e.printStackTrace(); 50 } catch (IOException e) { 51 // TODO 自动生成的 catch 块 52 e.printStackTrace(); 53 }finally 54 { 55 if(baos!=null){ 56 try { 57 baos.close(); 58 } catch (IOException e) { 59 // TODO 自动生成的 catch 块 60 e.printStackTrace(); 61 } 62 } 63 if(is!=null){ 64 try { 65 is.close(); 66 } catch (IOException e) { 67 // TODO 自动生成的 catch 块 68 e.printStackTrace(); 69 } 70 } 71 72 } 73 return result; 74 } 75 private static String setParams(String msg) { 76 // TODO 自动生成的方法存根 77 String url=""; 78 try { 79 url = URL+"?key="+API_KEY+"&info="+URLEncoder.encode(msg,"UTF-8"); 80 } catch (UnsupportedEncodingException e) { 81 // TODO 自动生成的 catch 块 82 e.printStackTrace(); 83 } 84 return url; 85 } 86 public static ChatMessage sendMessage(String msg){ 87 ChatMessage chatMessage=new ChatMessage(); 88 String jsonRes=doGet(msg); 89 Gson gson=new Gson(); 90 Result result=null; 91 try { 92 result = gson.fromJson(jsonRes, Result.class); 93 chatMessage.setMsg(result.getText()); 94 } catch (Exception e) { 95 // TODO: handle exception 96 chatMessage.setMsg("服务器繁忙,请稍后重试"); 97 } 98 chatMessage.setDate(new Date()); 99 chatMessage.setType(Type.INCOMING); 100 return chatMessage; 101 } 102 103 }
2.搭建操作环境,对工具类进行测试
建立包com.example.test,在此包下建立类TestHttpUtils.java。代码如下:
1 package com.example.test; 2 3 import com.example.util.HttpUtils; 4 5 import android.test.AndroidTestCase; 6 import android.util.Log; 7 8 9 public class TestHttpUtils extends AndroidTestCase { 10 public void testSendInfo(){ 11 String res=HttpUtils.doGet("给我讲个笑话"); 12 Log.e("TAG",res); 13 String res1=HttpUtils.doGet("给我讲个鬼故事"); 14 Log.e("TAG",res1); 15 String res2=HttpUtils.doGet("你好"); 16 Log.e("TAG",res2); 17 String res3=HttpUtils.doGet("你真美"); 18 Log.e("TAG",res3); 19 } 20 }
3.编写聊天界面
在drawable-hdpi文件下加入所需的图片,res/layout下建立activity_main.xml,item_from_msg.xml,item_to_msg.xml三个布局文件,代码如下:
1 <RelativeLayout 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 <RelativeLayout 6 android:id="@+id/id_ly_top" 7 android:layout_width="fill_parent" 8 android:layout_height="45dp" 9 android:layout_alignParentTop="true" 10 android:background="@drawable/title_bar">" 11 <TextView 12 android:layout_width="wrap_content" 13 android:layout_height="wrap_content" 14 android:layout_centerInParent="true" 15 android:textColor="#ffffff" 16 android:textSize="22sp" 17 android:text="小慕" 18 />" 19 </RelativeLayout> 20 21 22 <RelativeLayout 23 android:id="@+id/id_ly_bottom" 24 android:layout_width="fill_parent" 25 android:layout_height="55dp" 26 android:layout_alignParentBottom="true" 27 android:background="@drawable/bottom_bar"> 28 <Button 29 android:id="@+id/id_send_msg" 30 android:layout_width="60dp" 31 android:layout_height="40dp" 32 android:layout_centerInParent="true" 33 android:layout_alignParentRight="true" 34 android:background="@drawable/send_btn_bg" 35 android:text="发送" 36 37 /> 38 <EditText 39 android:id="@+id/id_input_msg" 40 android:layout_width="fill_parent" 41 android:layout_height="40dp" 42 android:background="@drawable/login_edit_normal" 43 android:layout_marginLeft="10dp" 44 android:layout_marginRight="10dp" 45 android:layout_centerVertical="true" 46 android:textSize="18sp" 47 android:layout_toLeftOf="@id/id_send_msg"/> " 48 </RelativeLayout> 49 <ListView 50 android:id="@+id/id_listview_msgs" 51 android:layout_width="fill_parent" 52 android:layout_height="fill_parent" 53 android:layout_above="@+id/id_ly_bottom" 54 android:layout_below="@+id/id_ly_top" 55 android:divider="@null" 56 android:dividerHeight="5dp"> 57 </ListView> 58 </RelativeLayout>
1 <?xml version="1.0" encoding="utf-8"?> 2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 3 android:layout_width="match_parent" 4 android:layout_height="wrap_content" 5 android:orientation="vertical" > 6 7 <TextView 8 android:id="@+id/id_from_msg_date" 9 android:layout_width="wrap_content" 10 android:layout_height="wrap_content" 11 android:layout_gravity="center" 12 android:background="#bebebe" 13 android:textColor="#f5f5f5" 14 android:textSize="12sp" 15 android:text="2012-12-12 12:12:12" /> 16 <LinearLayout 17 android:layout_width="wrap_content" 18 android:layout_height="wrap_content" 19 android:orientation="horizontal" 20 > 21 <LinearLayout 22 android:layout_width="fill_parent" 23 android:layout_height="wrap_content" 24 android:orientation="vertical"> 25 <ImageView 26 android:layout_width="49dp" 27 android:layout_height="49dp" 28 android:src="@drawable/icon"/> 29 <TextView 30 android:layout_width="wrap_content" 31 android:layout_height="wrap_content" 32 android:textSize="18sp" 33 android:layout_gravity="center" 34 android:text="小慕" 35 />" 36 37 </LinearLayout> 38 <TextView 39 android:id="@+id/id_from_msg_info" 40 android:layout_width="wrap_content" 41 android:layout_height="wrap_content" 42 android:text="你好!" 43 android:textSize="16sp" 44 android:gravity="center_vertical" 45 android:background="@drawable/chatfrom_bg_normal"/><!-- 垂直居中 -->" 46 47 </LinearLayout>" 48 49 50 </LinearLayout>
1 <?xml version="1.0" encoding="utf-8"?> 2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 3 android:layout_width="match_parent" 4 android:layout_height="wrap_content" 5 android:gravity="right" 6 android:orientation="vertical" > 7 8 <TextView 9 android:id="@+id/id_to_msg_date" 10 android:layout_width="wrap_content" 11 android:layout_height="wrap_content" 12 android:layout_gravity="center" 13 android:background="#bebebe" 14 android:textColor="#f5f5f5" 15 android:textSize="12sp" 16 android:text="2012-12-12 12:12:12" /> 17 <LinearLayout 18 android:layout_width="wrap_content" 19 android:layout_height="wrap_content" 20 android:orientation="horizontal" 21 > 22 <TextView 23 android:id="@+id/id_to_msg_info" 24 android:layout_width="wrap_content" 25 android:layout_height="wrap_content" 26 android:text="你好!" 27 android:textSize="16sp" 28 android:gravity="center_vertical" 29 android:background="@drawable/chatto_bg_normal"/><!-- 垂直居中 --> 30 <LinearLayout 31 android:layout_width="fill_parent" 32 android:layout_height="wrap_content" 33 android:orientation="vertical"> 34 <ImageView 35 android:layout_width="49dp" 36 android:layout_height="49dp" 37 android:src="@drawable/me"/> 38 <TextView 39 android:layout_width="wrap_content" 40 android:layout_height="wrap_content" 41 android:textSize="18sp" 42 android:layout_gravity="center" 43 android:text="Saraad" 44 />" 45 46 </LinearLayout> 47 48 49 </LinearLayout> 50 51 52 </LinearLayout>
为了更好的实现发送按钮的效果,需要在res下建立drawable文件夹,建立send_btn_bg.xml文件。代码如下:
1 <?xml version="1.0" encoding="utf-8"?> 2 <selector xmlns:android="http://schemas.android.com/apk/res/android"> 3 <item android:state_pressed="true" 4 android:drawable="@drawable/send_btn_pressed"></item> 5 <item android:drawable="@drawable/send_btn_normal"></item>" 6 </selector>
4.添加数据
建立com.example.bean包,建立ChatMessage.java,Result.java文件,代码如下:
1 package com.example.bean; 2 3 import java.util.Date; 4 5 public class ChatMessage { 6 private String name; 7 private String msg; 8 private Type type; 9 private Date date; 10 public ChatMessage() { 11 12 } 13 14 15 public ChatMessage(String msg, Type type, Date date) { 16 super(); 17 this.msg = msg; 18 this.type = type; 19 this.date = date; 20 } 21 22 23 public enum Type{ 24 INCOMING,OUTCOMING 25 } 26 27 public String getName() { 28 return name; 29 } 30 31 public void setName(String name) { 32 this.name = name; 33 } 34 35 public String getMsg() { 36 return msg; 37 } 38 39 public void setMsg(String msg) { 40 this.msg = msg; 41 } 42 43 public Type getType() { 44 return type; 45 } 46 47 public void setType(Type type) { 48 this.type = type; 49 } 50 51 public Date getDate() { 52 return date; 53 } 54 55 public void setDate(Date date) { 56 this.date = date; 57 } 58 }
1 package com.example.bean; 2 3 public class Result { 4 private int code; 5 private String text; 6 public int getCode() { 7 return code; 8 } 9 public void setCode(int code) { 10 this.code = code; 11 } 12 public String getText() { 13 return text; 14 } 15 public void setText(String text) { 16 this.text = text; 17 } 18 }
5.实现对话
在原有的包下建立ChatMessageAdapter.java文件,MainActivity.java是原有的。代码如下:
1 package com.example.imook_mook; 2 3 import java.text.SimpleDateFormat; 4 import java.util.List; 5 6 import com.example.bean.ChatMessage; 7 import com.example.bean.ChatMessage.Type; 8 9 import android.content.Context; 10 import android.view.LayoutInflater; 11 import android.view.View; 12 import android.view.ViewGroup; 13 import android.widget.BaseAdapter; 14 import android.widget.TextView; 15 16 public class ChatMessageAdapter extends BaseAdapter { 17 private LayoutInflater myInflater; 18 private List<ChatMessage> mDatas; 19 20 public ChatMessageAdapter(Context context,List<ChatMessage> mDatas){ 21 myInflater=LayoutInflater.from(context); 22 this.mDatas=mDatas; 23 } 24 25 @Override 26 public int getCount() { 27 // TODO 自动生成的方法存根 28 return mDatas.size(); 29 } 30 31 @Override 32 public Object getItem(int position) { 33 // TODO 自动生成的方法存根 34 return mDatas.get(position); 35 } 36 37 @Override 38 public long getItemId(int position) { 39 // TODO 自动生成的方法存根 40 return position; 41 } 42 43 @Override 44 public int getItemViewType(int position) { 45 // TODO 自动生成的方法存根 46 ChatMessage chatMessage=mDatas.get(position); 47 if(chatMessage.getType()==Type.INCOMING){ 48 return 0; 49 } 50 return 1; 51 }//接受消息为0,发送消息为1; 52 53 @Override 54 public int getViewTypeCount() { 55 // TODO 自动生成的方法存根 56 return 2; 57 } 58 59 @Override 60 public View getView(int position, View convertView, ViewGroup parent) { 61 // TODO 自动生成的方法存根 62 ChatMessage chatMessage=mDatas.get(position); 63 ViewHolder viewHolder=null; 64 if(convertView==null){ 65 //通过ItemType设置不同的布局 66 if(getItemViewType(position)==0) 67 { 68 convertView=myInflater.inflate(R.layout.item_from_msg, 69 parent,false); 70 viewHolder=new ViewHolder(); 71 viewHolder.mDate=(TextView) convertView 72 .findViewById(R.id.id_from_msg_date); 73 viewHolder.mMsgs=(TextView) convertView 74 .findViewById(R.id.id_from_msg_info); 75 }else{ 76 convertView=myInflater.inflate(R.layout.item_to_msg,parent, 77 false); 78 viewHolder=new ViewHolder(); 79 viewHolder.mDate=(TextView) convertView 80 .findViewById(R.id.id_to_msg_date); 81 viewHolder.mMsgs=(TextView) convertView 82 .findViewById(R.id.id_to_msg_info); 83 } 84 convertView.setTag(viewHolder); 85 }else{ 86 viewHolder=(ViewHolder) convertView.getTag(); 87 } 88 //设置数据 89 SimpleDateFormat df=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); 90 viewHolder.mDate.setText(df.format(chatMessage.getDate())); 91 viewHolder.mMsgs.setText(chatMessage.getMsg()); 92 return convertView; 93 } 94 private final class ViewHolder{ 95 TextView mDate; 96 TextView mMsgs; 97 }//提升效率 98 99 }
1 package com.example.imook_mook; 2 3 import java.util.ArrayList; 4 import java.util.Date; 5 import java.util.List; 6 7 import com.example.bean.ChatMessage; 8 import com.example.bean.ChatMessage.Type; 9 import com.example.util.HttpUtils; 10 11 import android.os.Bundle; 12 import android.os.Handler; 13 import android.os.Message; 14 import android.app.Activity; 15 import android.text.TextUtils; 16 import android.view.Menu; 17 import android.view.View; 18 import android.view.View.OnClickListener; 19 import android.view.Window; 20 import android.widget.Button; 21 import android.widget.EditText; 22 import android.widget.ListView; 23 import android.widget.Toast; 24 25 public class MainActivity extends Activity { 26 private ListView mMsgs; 27 private ChatMessageAdapter mAdapter; 28 private List<ChatMessage> mDatas;//数据源 29 30 private EditText mInputMsg; 31 private Button mSendMsg; 32 33 private Handler mHandler=new Handler() 34 { 35 public void handleMessage(android.os.Message msg){ 36 //等待接受子线程数据的返回 37 ChatMessage fromMessage=(ChatMessage) msg.obj; 38 mDatas.add(fromMessage); 39 mAdapter.notifyDataSetChanged(); 40 } 41 }; 42 @Override 43 protected void onCreate(Bundle savedInstanceState) { 44 super.onCreate(savedInstanceState); 45 requestWindowFeature(Window.FEATURE_NO_TITLE); 46 setContentView(R.layout.activity_main); 47 48 initView(); 49 initDatas(); 50 //初始化事假 51 initListener(); 52 } 53 private void initListener() { 54 // TODO 自动生成的方法存根 55 mSendMsg.setOnClickListener(new OnClickListener(){ 56 57 @Override 58 public void onClick(View v) { 59 // TODO 自动生成的方法存根 60 final String toMsg =mInputMsg.getText().toString(); 61 if(TextUtils.isEmpty(toMsg)) 62 { 63 Toast.makeText(MainActivity.this,"发送消息不能为空",Toast.LENGTH_SHORT).show(); 64 return ; 65 } 66 67 ChatMessage toMessage=new ChatMessage(); 68 toMessage.setDate(new Date()); 69 toMessage.setMsg(toMsg); 70 toMessage.setType(Type.OUTCOMING); 71 mDatas.add(toMessage); 72 mAdapter.notifyDataSetChanged();//通知更新 73 74 mInputMsg.setText(""); 75 new Thread(){ 76 public void run(){ 77 ChatMessage fromMessage=HttpUtils.sendMessage(toMsg); 78 Message m=Message.obtain(); 79 m.obj=fromMessage; 80 mHandler.sendMessage(m); 81 } 82 }.start(); 83 84 } 85 86 }); 87 } 88 private void initDatas() { 89 // TODO 自动生成的方法存根 90 mDatas=new ArrayList<ChatMessage>(); 91 mDatas.add(new ChatMessage("你好,小慕为您服务",Type.INCOMING,new Date())); 92 //mDatas.add(new ChatMessage("你好",Type.OUTCOMING,new Date())); 93 mAdapter=new ChatMessageAdapter(this,mDatas); 94 mMsgs.setAdapter(mAdapter); 95 } 96 97 private void initView() { 98 // TODO 自动生成的方法存根 99 mMsgs=(ListView) findViewById(R.id.id_listview_msgs); 100 mInputMsg=(EditText) findViewById(R.id.id_input_msg); 101 mSendMsg= (Button) findViewById(R.id.id_send_msg); 102 103 } 104 105 106 }
最后在AndroidManifest.xml文件中添加权限:
1 <?xml version="1.0" encoding="utf-8"?> 2 <manifest xmlns:android="http://schemas.android.com/apk/res/android" 3 package="com.example.imook_mook" 4 android:versionCode="1" 5 android:versionName="1.0" > 6 <uses-permission android:name="android.permission.INTERNET"/>" 7 <uses-sdk 8 android:minSdkVersion="8" 9 android:targetSdkVersion="18" /> 10 11 <application 12 android:allowBackup="true" 13 android:icon="@drawable/ic_launcher" 14 android:label="@string/app_name" 15 android:theme="@style/AppTheme" > 16 <uses-library android:name="android.test.runner"/> 17 <activity 18 android:name="com.example.imook_mook.MainActivity" 19 android:label="@string/app_name" > 20 <intent-filter> 21 <action android:name="android.intent.action.MAIN" /> 22 23 <category android:name="android.intent.category.LAUNCHER" /> 24 </intent-filter> 25 </activity> 26 </application> 27 <instrumentation android:targetPackage="com.example.imook_mook" 28 android:label="this is a test" 29 android:name="android.test.InstrumentationTestRunner"> 30 </instrumentation> 31 </manifest>
四、总结
项目截图:
抛出异常快捷键shift+alt+z。
引用图灵机器人的API官网 http://www.tuling123.com/。
2016-03-1720:57:38