我一直坚信着,即使一个最简单的APP,也有他的难点,如果一个复杂的APP你无法做出来,那肯定是你基础不扎实,我身边的人总是问我,安卓为什么学了有忘记了,总是学不好,有些东西记不住,其实这不能怪你,如果别人开发了那么久的东西,你一下子就学会了,你让谷歌怎么活。

篇幅有限,如果读者看不懂的话,可以复习下基础,我尽量将代码简单化了。  先看效果图

如果你是初学安卓,这个APP你可能要半小时

如果你是有经验的开发者,OK,你可能看一遍就能将自己的开发类带入,10分钟不到就搞定。

开发步骤:

1. 先去图灵机器人注册KEY

http://www.tuling123.com/

2.准备好联网操作,将联网工具类放入

PS:这里是我自己的联网工具类,如果喜欢可以收藏

3.准备json解析

json解析并不复杂,所以只是用了自带json解析了

4.UI准备

5.业务逻辑准备

第一步 你先去 图灵机器人的官网申请key 这个不复杂,因为可以QQ登录 如果不想申请 那就用我的呗

key = 349baa5d2bd5d2d7612e4f2c1fcd973d

第二步  联网获取json

其实这个请求数据,没什么区别的,看看他的请求示例

private String url="http://www.tuling123.com/openapi/api?key=349baa5d2bd5d2d7612e4f2c1fcd973d&info=";

后面加入你的输入的信息 即可

联网:1.Httpclient  2. Httpconnection 3.Xutils 4.各种工具类。

一个开发者,随着开发的东西越来越来多,积累的工具也越来越多,在这个小Demo 里 你可以使用自己的工具类

我的联网工具类,是自己封装的  你可以在自带加入线程,用的是Httpconnection联网,然后根据IO操作 转成String  通过接口放回String类型。

package com.example.AiComputer;import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.nio.ByteOrder;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Handler;/*** 封装的 网络 + 线程*/
public class HttpUtils {// 使用线程池来下载图片,同一时刻,最多有3个线程在运行private static ExecutorService execuotrs = Executors.newFixedThreadPool(3);interface OnBitmapNetWorkResponse {public void ok(Bitmap bitmap);public void error(String error);}public static void RequestBitmapNetWork(final String path,final OnBitmapNetWorkResponse response) {final Handler handler = new Handler();execuotrs.execute(new Runnable() {@Overridepublic void run() {boolean isNetWorkOK = false;try {URL url = new URL(path);HttpURLConnection openConnection = (HttpURLConnection) url.openConnection();openConnection.setConnectTimeout(5000);openConnection.connect();if (openConnection.getResponseCode() == 200) {InputStream inputStream = openConnection.getInputStream();final Bitmap bitmap = BitmapFactory.decodeStream(inputStream);handler.post(new Runnable() {@Overridepublic void run() {response.ok(bitmap);}});inputStream.close();isNetWorkOK = true;}} catch (MalformedURLException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();} finally {if (!isNetWorkOK) {handler.post(new Runnable() {@Overridepublic void run() {response.error("服务器不在服务区内!");}});}}}});}public interface OnNetWorkResponse {public void ok(String response);public void error(String error);}public static void RequestNetWork(final String path,final OnNetWorkResponse response) {//实例化handler final Handler hanlder = new Handler();new Thread() {public void run() {//标志位boolean isWorkOK = false;InputStream inputStream = null;ByteArrayOutputStream outStream = null;try {URL url = new URL(path);System.out.println("=======path========="+path);HttpURLConnection connection = (HttpURLConnection) url.openConnection();connection.setConnectTimeout(5000);connection.setDoInput(true);connection.connect();if (connection.getResponseCode() == 200) {inputStream = connection.getInputStream();outStream = new ByteArrayOutputStream();byte[] b = new byte[1024];int len = 0;while ((len = inputStream.read(b)) != -1) {outStream.write(b, 0, len);}outStream.flush();final String result = new String(outStream.toByteArray());hanlder.post(new Runnable() {@Overridepublic void run() {response.ok(result);}});isWorkOK = true;}} catch (MalformedURLException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();} finally {// 网络操作出问题if (!isWorkOK) {response.error("服务器走神拉!");}if (inputStream != null) {try {inputStream.close();} catch (IOException e) {e.printStackTrace();}}if (outStream != null) {try {outStream.close();} catch (IOException e) {e.printStackTrace();}}}};}.start();}}

如果对于这一节,不懂的可以看下 我写的 网络编程系列

从java网络编程学起(2)

第三步,就是json 解析

我们在url后面加入 深圳的天气   返回的是

{"code":100000,"text":"今天多云 24~19°C明天阴 26~21°C后天阴 22~17°C"}

最外层是一个大括号,so 直接用JsonObject,解析即可

JSONObject jb = new JSONObject(response);

4.UI准备

其实对于ui  并不复杂,  最外层是一个 线性布局,里面是 两个线性布局,第一个装着listview ----->显示聊天信息  第二个 装着 一个button 发送消息 一个Edittext 输入信息

布局文件:activity_main.xml

<LinearLayout 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:orientation="vertical" ><ListViewandroid:id="@+id/lv"android:layout_width="fill_parent"android:layout_height="0dp"android:layout_weight="1"android:divider="@null"android:listSelector="@android:color/transparent"android:transcriptMode="alwaysScroll" ></ListView><LinearLayoutandroid:layout_width="fill_parent"android:layout_height="wrap_content"android:orientation="horizontal" ><EditTextandroid:id="@+id/sendText"android:layout_width="0dp"android:layout_height="wrap_content"android:layout_weight="1" /><Button android:id="@+id/send_btn"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="发送"/></LinearLayout></LinearLayout>

既然说道了listview  就知道我们的聊天信息,要在上面显示,我们要在适配器中 判断是那个发送的消息,进行判断是哪个发送过来的 显示那部分布局 ,左边的是机器人的消息布局  右边是 我们发送消息的布局

也不复杂, 一个相对布局中有一个textview  显示发送时间,一个Imageview显示机器人的头像  一个textview 显示消息内容

机器人消息的布局

<?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" ><TextViewandroid:id="@+id/time"android:layout_width="fill_parent"android:layout_height="wrap_content"android:gravity="center_horizontal" /><ImageViewandroid:id="@+id/iv"android:layout_width="70dp"android:layout_height="70dp"android:layout_below="@id/time"android:padding="10dp"android:src="@drawable/robot" /><TextViewandroid:id="@+id/tv"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_below="@id/time"android:layout_marginRight="50dp"android:layout_toRightOf="@id/iv"android:background="@drawable/aio_friend_bg_nor_11"android:gravity="center" /></RelativeLayout>

我们发送消息的内容

<?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" ><TextViewandroid:id="@+id/time"android:layout_width="fill_parent"android:layout_height="wrap_content"android:gravity="center_horizontal" /><ImageViewandroid:id="@+id/iv"android:layout_width="70dp"android:layout_height="70dp"android:layout_alignParentRight="true"android:layout_below="@id/time"android:padding="10dp"android:src="@drawable/xiaoxin" /><TextViewandroid:id="@+id/tv"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_below="@id/time"android:layout_marginLeft="50dp"android:layout_toLeftOf="@id/iv"android:background="@drawable/aio_user_bg_nor_11"android:gravity="center" /></RelativeLayout>

不知不觉,就走到了最后一步,相信 你一定会觉得,好简单呀,是的很简单,因为最难的在后面

业务逻辑 :

1.Edittext 和listview 和button的实例化

2.button点击事件的处理

获取 Edittext输入的内容,进行处理————>去掉空格和回车的信息,替代成空 。  然后将数据封装到实体类中去。 当大于30条的时候清空一次 然后刷新一下适配器

将处理好的信息 发送到服务器 获取 回复的信息 然后也封装进行实体类,刷新一下适配器

3. 设置欢迎语言,每一次进来,为了提高用户体验,我们进行欢迎语出现, 先建立一个数组  用来装 欢迎语

来到res/values/Strings 加入数组

   <string-array name="welcome_tips"><item>主人,奴婢在此等候多时了</item><item>主人,近来一切可好</item><item>亲爱的,我想死你了</item><item>欢迎归来,我亲爱的主人</item><item>我是小新机器人,很高兴为您服务</item></string-array>

然后再 java 代码中如一个方法

 private String getRandomWelcomeTips() {String welcome_tip = null;welcome_array = this.getResources().getStringArray(R.array.welcome_tips);int index = (int) (Math.random() * (welcome_array.length - 1));welcome_tip = welcome_array[index];return welcome_tip;}

应该不难看懂 通过随机 得到数组内容

其中聊天嘛,应该把时间也加入

 private String getTime() {currentTime = System.currentTimeMillis();SimpleDateFormat format = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");Date curDate = new Date();String str = format.format(curDate);if (currentTime - oldTime >= 500) {oldTime = currentTime;return str;} else {return "";}}

也就是获取了下 系统时间,然后格式化了下

Java代码 MainActivity

package com.example.AiComputer;import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;import org.json.JSONException;
import org.json.JSONObject;import com.example.AiComputer.HttpUtils.OnNetWorkResponse;import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ListView;public class MainActivity extends Activity implements OnClickListener{//输入框private EditText sendtext;private Button send_btn;private ListView listView;private String content_str;private String[] welcome_array;private String url="http://www.tuling123.com/openapi/api?key=349baa5d2bd5d2d7612e4f2c1fcd973d&info=";private double currentTime=0, oldTime = 0;private List<ListData> lists;private ListData listData;private MyAdapter adapter;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);initView();}private void initView() {listView = (ListView) findViewById(R.id.lv);sendtext = (EditText) findViewById(R.id.sendText);send_btn = (Button) findViewById(R.id.send_btn);lists = new ArrayList<ListData>();//发送的点击事件send_btn.setOnClickListener(this);adapter = new MyAdapter(lists, this);listView.setAdapter(adapter);listData = new ListData(getRandomWelcomeTips(), ListData.RECEIVER,getTime());lists.add(listData);}private String getRandomWelcomeTips() {String welcome_tip = null;welcome_array = this.getResources().getStringArray(R.array.welcome_tips);int index = (int) (Math.random() * (welcome_array.length - 1));welcome_tip = welcome_array[index];return welcome_tip;}
/*1.获取 Edittext输入的内容,进行处理————>去掉空格和回车的信息,替代成空 。* 2.然后将数据封装到实体类中去。 当大于30条的时候清空一次 然后刷新一下适配器* */@Overridepublic void onClick(View v) {getTime();content_str = sendtext.getText().toString();sendtext.setText("");String dropk = content_str.replace(" ", "");String droph = dropk.replace("\n", "");listData = new ListData(content_str, ListData.SEND, getTime());lists.add(listData);if (lists.size() > 30) {for (int i = 0; i < lists.size(); i++) {lists.remove(i);}}adapter.notifyDataSetChanged();HttpUtils.RequestNetWork(url+droph, new OnNetWorkResponse() {@Overridepublic void ok(String response) {try {JSONObject jb = new JSONObject(response);// System.out.println(jb.getString("code"));// System.out.println(jb.getString("text"));ListData listData;listData = new ListData(jb.getString("text"), ListData.RECEIVER,getTime());lists.add(listData);adapter.notifyDataSetChanged();} catch (JSONException e) {// TODO Auto-generated catch blocke.printStackTrace();}}@Overridepublic void error(String error) {// TODO Auto-generated method stub}});}private String getTime() {currentTime = System.currentTimeMillis();SimpleDateFormat format = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");Date curDate = new Date();String str = format.format(curDate);if (currentTime - oldTime >= 500) {oldTime = currentTime;return str;} else {return "";}}
}

其实在没有点击的时候,欢迎语 已经通过适配器 显示到listview上面去了 所以我们可以放在adapter实例化下面  ,实体类,主要起的作用就是将 发送的时间和内容 封装好,在适配器中判断 进行展示

其实最重要的是 适配器的内容,应该怎么处理 发送过来的消息:

我们向适配器 传了两个值集合,装满了实体类数据的集合 一个上下文

我们先建立一个相对布局,用来填充条目的内容  我们要想一个list装着实体类,实体类,有很多数据 ,我们需要通过标识符来判断显示那部分内容。

package com.example.AiComputer;import java.util.List;import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.RelativeLayout;
import android.widget.TextView;public class MyAdapter extends BaseAdapter{private List<ListData> lists;private Context mContext;private RelativeLayout layout;public MyAdapter(List<ListData> lists,Context mContext) {this.lists = lists;this.mContext = mContext;}@Overridepublic int getCount() {return lists.size();}@Overridepublic Object getItem(int position) {return lists.get(position);}@Overridepublic long getItemId(int position) {return position;}@Overridepublic View getView(int position, View convertView, ViewGroup parent) {LayoutInflater inflater = LayoutInflater.from(mContext);if(lists.get(position).getFlag() == ListData.RECEIVER){layout = (RelativeLayout) inflater.inflate(R.layout.leftitem, null);}if (lists.get(position).getFlag() == ListData.SEND) {layout = (RelativeLayout) inflater.inflate(R.layout.rightitem, null);}TextView tv = (TextView) layout.findViewById(R.id.tv);TextView time = (TextView) layout.findViewById(R.id.time);tv.setText(lists.get(position).getContent());time.setText(lists.get(position).getTime());return layout;}}

如有问题,可以在我博客上面留言

练手小项目(1)——智能聊天机器人相关推荐

  1. Golang练手小项目系列

    Golang练手小项目系列 本系列整理了10个工作量和难度适中的Golang小项目,适合已经掌握Go语法的工程师进一步熟练语法和常用库的用法. golang练手小项目系列(1)-位向量 golang练 ...

  2. ssm练手小项目_20 个 JavaScript+Html+CSS 练手的小项目

    前言: 最近在 GitHub 上发现了一个 vanillawebprojects[1] 开源仓库,里面收集了 20 个 JavaScript+Html+CSS的练手项目,没有使用任何框架,可以让你从基 ...

  3. 台式小风扇(HTML+CSS+JS练手小项目)

    台式小风扇(HTML+CSS+JS练手小项目) 功能介绍 外观展示 HTML代码 CSS代码 JS代码 总结 功能介绍 前段时间看到这样的风扇特效,感觉还挺好玩,就自己也写一个练练手. 风扇有四个档位 ...

  4. 爬虫练手小项目:豆瓣高分图书TOP100

    爬虫练手小项目:豆瓣高分图书TOP100 import requests import re from requests.exceptions import RequestException impo ...

  5. 数据结构练手小项目(AVL树、哈希表、循环链表、MySQL数据库)

    文章目录 前言 正文(无删减) 我的想法(删减修改版) 数据导入与数据存储 功能实现 数据结构 用户结构 SIM卡结构 AVL树数据结构 哈希表结构 数据表 用户表 SIM卡表 时间安排 前言 本月主 ...

  6. html+css+js之20个练手小项目(一)

    html+css+js之20个练手小项目(一)--Hangman 前言 一.HTML 二.CSS 三.JS 前言 前端新手练习,记录不迷失. 主要练习html和CSS布局以及JS. 来源github, ...

  7. 练手小项目,爬取3DM图片

    博客原文:https://weweweha.com 1. 概述 ​ 爬取3DM指定网页的游戏壁纸,并且通过多线程来加速爬取图片的速度. 2.使用库 ​ request库用来1解析指定网页,re库用来搜 ...

  8. c语言模拟器怎么打程序,C语言初学者练手小项目——万花模拟器

    原标题:C语言初学者练手小项目--万花模拟器 还记得小时候玩的万花尺么?好好玩,各种不同的点距能画出各种各样形状图形. C语言程序万花尺模拟 函数功能:每隔5秒随机生成万花图形 并自动保存作图参数以及 ...

  9. 练手小项目(2)-生活小助手--星座运势查询

    上一篇内容 练手小项目(2)-生活小助手 今天星期一.趁着中午的歇息时间把 第二个写出来 星座运势,近期看看极客学院 用聚合数据做了天气预报的视频教程,不好评价他.看他在后面的代码变更那么大,我就知道 ...

最新文章

  1. 运动检测(前景检测)之——ViBe
  2. php数组操作之合并相同键名的值,排序,排重,去空值等
  3. 从自我学习到深层网络
  4. 九九乘法表_JAVA
  5. 【Vegas原创】Mysql绿色版安装方法
  6. Matlab求欧式距离
  7. Spring MVC表单验证
  8. linux inputuevent使用
  9. node mysql商城开发_GitHub - Ssipon/nideshop: NideShop:基于Node.js+MySQL开发的开源免费商城(api服务器端)...
  10. 神州数码 每日总结DCWS
  11. NOD32企业版授权文件过期后的应急处理(病毒病义更新)
  12. 分享几款狂拽炫酷屌炸天的大屏监控场景案例
  13. 中小企业财务管理的重要性
  14. ie8打不来ftp文件服务器,在IE8、IE9中访问FTP无法直接显示文件夹视图解决办法
  15. 计算机管理员无法关闭防火墙,Win10关闭防火墙提示:出于安全原因 某些设置由系统管理员管理的解决方法...
  16. 回顾维乐VELO创始人余彩云漫漫创新路
  17. 网络安全——缓冲区溢出攻击
  18. Mac OSX常用软件
  19. 位图BitMap图像的读取与存储
  20. 将.C文件编译成最小的PE可执行文件

热门文章

  1. 各国海关单证有哪些要求?
  2. 如何对“诱惑”说不?
  3. BPM流程建模开发详解
  4. Frenet坐标系及其与笛卡尔坐标的转换(2)——原理
  5. 移动开发者大会第一日观感
  6. 11.elasticsearch认证考试总结
  7. 无法用ip连接mysql数据库_MYSQL数据库无法使用IP访问的方法
  8. 应用程序日志管理工具
  9. 漫画版python_不能错过的Python漫画
  10. 网线直连,Synergy低延迟顺滑共享鼠标键盘