一步步教你为网站开发Android客户端

news/2024/5/13 15:38:45/文章来源:https://blog.csdn.net/good_night_honey/article/details/24312607
http://www.eoeandroid.com/thread-182400-1-1.html
本文面向Android初级开发者,有一定的Java和Android知识即可。

文章覆盖知识点:HttpWatch抓包,HttpClient模拟POST请求,Jsoup解析HTML代码,动态更新ListView

背景介绍:客户端(Client)或称为用户端,是指与服务器相对应,为客户提供本地服务的程序。而android系统上的90%客户端软件都有一个共性,就是为了改善网页在android系统上体验不佳而生,最具有影响力的软件有:新浪微博、人人网、淘宝等,这类软件最突出的特点就是,先有网站再有软件。由于网络技术发展的多样性,手机浏览器往往无法跟随它的步伐,为改善用户体验,网站客户端软件印运而生。

开发Android网站客户端通常有两种方法:第一种,通过服务端的开放平台,调用提供的API接口来开发,比如说open sina;第二种,服务端没有提供任何接口,你也没有服务端任何数据库访问权限,就是一个纯纯粹粹的网站,要你做客户端。今天,我要和大家分享的正是第二种情况。



这是一个简单的示意图,告诉我们,数据是由网页从数据库中取出,我们要为这个系统做客户端,我们就应该这样去改造它。




通过这样间接的方法来访问数据库,只要网页能看到的内容,我们的客户端都能获取到,而UI是由你自行制作,就可以使使用体验上一个台阶。
既然网页是我们的数据枢纽,我们就从网页分析着手。

该教程来自本人项目-掌上民大-真实经验,所以用项目中的”掌上图书馆”板块来示范。

该项目任务为中南民族大学图书馆图书查询功能制作客户端。

首先打开该网址http://www.lib.scuec.edu.cn/,我们会看到主界面




正中间就是查询入口,我们输入”android”进行查询




得到结果的网页,但我们能发现,这个页面是ILAS图书管理系统,所以真正的入口并不是上面红圈的地方。
所以我继续找,经过短暂的观察,发现入口在这里




我们点击进入




果然就是这货,我们点击书目查询





就是它了。真正的入口就在这里,这时我们打开HttpWatch软件,点”Record”,在搜索框里输入”android”,点击查询,抓取以”android”为关键字搜索时浏览器的所有包。待结果界面载入完成后,HttpWatch上就会出现如下信息



我们先看Summary选项卡,我们可以初步了解,这是一个POST请求(Http请求中的一种,另一种是GET),POST到的网址是http://coin.lib.scuec.edu.cn/cgi-bin/IlaswebBib。
这样我们的思路就清晰了,我们的客户端需要模拟浏览器,向上述地址POST一个包,那个地址肯定会返回一个Content给我们,不出意外的话,Content里面就是我们要的书目信息。那么,浏览器POST上去的内容是什么呢?我们点击这条POST请求,看详细信息,




由于是POST请求,我们先看POST DATA,里面是以键值对的形式存储的,这里显示了我们浏览器在我们搜索”android”时,POST的所有数据。那这些键值对又代表了什么呢,我们打开这个网页的源码来一探究竟。



从这段可以看出v_index是表示查找途径的它有TITLE,AUTHOR,SUBJECT,CLASSNO,ISBN,CALLNO六种值



FLD_DAT_BEG和FLD_DAT_END分别是开始和结束年份



v_value表示用户在搜索框中输入的内容



v_paggnum表示每页显示的书目条数,有10 15 20三种



v_seldatabases是检索库  有0 1 2三种值v_LogicSrch是检索方式   有0 1两种值



Submit是查询或重填,有 查 询 和 重 填 两种值

至此,我们弄清楚了POST Data里所有内容的含义和取值可能。但我们模拟POST请求为什么,其实就是为了得到搜索的书目信息,所以我们看一下返回的Content是不是我们要的东西




果然,就是我们搜到的书目信息,就以String的形式放在Content里面。最后我们查看一下Stream,截图,以防等下我们需要这里面的东西



好了,这个页面的工作原理我们已经弄清楚了:用户在网页中输入搜索内容后,点击查询,浏览器会POST一个Data到目标网址,该网址的返回信息就是搜到的书目。 
我们开始编写代码,模拟这个过程,先打开eclipse建立一个Java项目(注意是Java项目,因为Java项目可以完美移植到Android项目中且调试方便,并且模拟Http请求这一过程没有用到任何Android功能)。
导入HttpClient的4个包commons-codec、commons-httpclient、commons-logging、log4j。

代码片段,双击复制
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
//实例化HttpClient
HttpClient client = newHttpClient();
//Stream页面里面有Host地址 端口是80
client.getHostConfiguration().setHost("http://coin.lib.scuec.edu.cn",80);
//用目标地址 实例一个POST方法
PostMethod post = newPostMethod("http://coin.lib.scuec.edu.cn/cgi-bin/IlaswebBib");
//将需要的键值对写出来
NameValuePair beg = newNameValuePair("FLD_DAT_BEG", “”);
NameValuePair end = newNameValuePair("FLD_DAT_END", “”);
NameValuePair submit = newNameValuePair("submit","查 询"));
NameValuePair vIndex = newNameValuePair("v_index", “TITLE”);
NameValuePair vLogicSrch = newNameValuePair("v_LogicSrch","0");
NameValuePair vPagenum = newNameValuePair("v_pagenum","10");
NameValuePair vSeldatabase = newNameValuePair("v_seldatabase","0");
NameValuePair vValue = newNameValuePair("v_value",”android”);
//给POST方法加入上述键值对
post.setRequestBody(newNameValuePair[] {beg , end , submit , vIndex , vLogicSrch , vPagenum , vSeldatabase , vValue});
//执行POST方法
client.executeMethod(post);
//将POST返回的数据以流的形式读入,再把输入流流至一个buff缓冲字节数组
//StreamTool类是我自己写的一个工具类,其内容将在下文附出
byte[] buff = StreamTool.readInputStream(post.getResponseBodyAsStream());
//将返回的内容格式化为String存在html中
String html = newString(buff);
//任务完成了,释放连接
post.releaseConnection();

代码片段,双击复制
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
//StreamTool类如下
publicclassStreamTool {
/**
* 从输入流中获取数据
* @param inputStream 输入流
* <a href="\"http://www.eoeandroid.com/home.php?mod=space&uid=7300\"" target="\"_blank\"">@return</a> 字节数组
* @throws Exception
*/
publicstaticbyte[] readInputStream(InputStream inputStream) throwsException
{
//实例化一个输出流
ByteArrayOutputStream outputStream = newByteArrayOutputStream();
//一个1024字节的缓冲字节数组
byte[] buffer = newbyte[1024];
intlen = 0;
//读流的基本知识
while((len=inputStream.read(buffer)) != -1) {
outputStream.write(buffer,0, len);
}
//用完要关,大家都懂的
inputStream.close();
returnoutputStream.toByteArray();
}
}


现在,我们得到了POST方法返回的String,我们输出到控制台看看是什么 
代码片段,双击复制
01
System.out.println(html);



没错,就是我们上文看到的HttpWatch 抓到的返回Content,也就是一段HTML代码,这说明,我们模拟浏览器POST请求成功了!
我们再试试别的搜索内容,来一个”Android开发”(即将v_value键值对的值改成”android开发”),这时运行后,我们却从控制台得到了这样的结果:


                                                                                                   

经过几次试验后,发现一个规律,只要搜索内容中包括中文,就搜不到。
所以可以判定是中文编码的问题,我们修改上面的代码,将代表搜索内容的v_value对应的值编码为”ISO-8859-1”

就将上段代码中的
代码片段,双击复制
01
NameValuePair vValue = newNameValuePair("v_value",”android”);

改为 
代码片段,双击复制
01
NameValuePair vValue = newNameValuePair("v_value",newString(“android开发”.getBytes(),"ISO-8859-1"));

这时再运行,控制台成功输出以” android开发”为关键字的Content。

至此,我们POST请求才真正完成。 观察控制台的HTML后发现,我们需要的书目信息就在里面,只不过被一些HTML标签包裹住了,下一步我们就要解放这些信息,存储到容器里。
这里我们要用到Jsoup,一个Java开源HTML解析器(来自org.jsoup包)。
我们直接上代码,逐行解释(大家最好对应上面的HTML代码来理解)
首先我们建一个容器来装这些解析到的数据,由于我的项目是将这些数据以ListView呈现给用户,而ListView的数据是由Adapter提供,Adapter需要传一个特殊容器-包含HashMap的ArrayList(Android基础知识)
代码片段,双击复制
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
//所以有
List<Map<String,Object>> list = newArrayList<Map<String,Object>>();
//开始使用Jsoup
//Jsoup支援一个Document类 将刚才的html转化成Document
Document document = Jsoup.parse(html);
//一个Document又由elements组成 我们选择”tr”开头的标签,存入 trs元素群中
Elements trs = document.select("tr");
//得到整个HTML中包含tr的标签的个数
inttotalTrs = trs.size();
//我们可以观察上面没有搜索结果的那个HTML。发现,如果totalTrs<=3就表示没结果。
//只要有书目结果totalTrs必定大于3,于是
if(totalTrs > 3)
for(inti = 0;i < totalTrs - 3;i++)
{
//观察HTML,从第i+2个tr开始,包含的才是我们要的书目信息
//我们从每个tr中选出td标签元素群
Elements tds = trs.get(i + 2).select("td");
//得到每个tr中td的个数
inttotalTds = tds.size();
//一个临时的HashMap,里面是String-Object键值对
Map<String,Object> map = newHashMap<String,Object>();
//j是一个标识数
for(intj =0;j < totalTds ;j++)
{
switch(j) {
//0表示第一个,即书名
//put方法即向map加入一条键值对
//html()方法就得到标签括起来的内容
case0:
map.put("book_title", tds.get(j).html().toString());
break;
case1:
//1表示第二个,即作者
map.put("book_author", tds.get(j).html().toString());
break;
case2:
//2表示第三个,即出版信息
map.put("book_press", tds.get(j).html().toString());
break;
case3:
//3表示第四个,即页数
map.put("book_page", tds.get(j).html().toString());
break;
case4:
//4表示第五个,即价格
map.put("book_price", tds.get(j).html().toString());
break;
case5:
//5表示第六个,即索取号
map.put("book_noFor", tds.get(j).html().toString());
break;
case6:
//6表示第七个,即那段网址
//那段网址td中又包含一个a标签,a标签的href属性的值就是网址
//attr(“href”)可以返回href属性的值
map.put("book_detail", tds.get(j).select("a").attr("href").toString());
break;
default:
break;
}
}
list.add(map);
}

list就是我们需要的ArrayList啦

上面所有代码调通后,我们只需一些简单的复制粘贴,就可以放在我们的Android工程中,加上一段简单的代码就可以让ListView显示这个ArrayList。(由于没有任何技术含量,以及该项目暂未上线,此段代码不予以展示,敬请谅解) 

接下来,我们一个页面最多只包含10个书目信息,而我们校图书馆,光以”Java”为关键字的书就超过1000本,怎么来显示完全呢,一次显示所有的书肯定不现实。首先数据量太大,手机无法承受;消耗流量过大,用户体验极差。所以,我们就需要ListView能够动态加载数据,即一开始显示十项,如果用户此时拉动ListView显示完十项之后,自动联网,再加载十项(如果还有十项的话),这样的用户体验会非常顺畅。
这个功能的核心是,我们的ListView需要实现OnScrollListener接口。
如果你的ListView所在的Activity继承的是ListActivity的话,只需在extends ListActivity后面加上implements OnScrollListener,这时你需要复写onScroll和onScrollStateChanged。如果你的ListView是从XMLgetView 得到的,你只需为它setOnScrollListener,也会需要你复写onScroll和onScrollStateChanged。

不管你用哪种方法,我们只用修改onScroll方法
代码片段,双击复制
01
02
03
04
05
06
07
08
09
@Override
publicvoidonScroll(AbsListView view, intfirstVisibleItem,
intvisibleItemCount,inttotalItemCount) {
// TODO Auto-generated method stub
//关键的判断代码,这句话表示用户将ListView拉至最底部
if(firstVisibleItem + visibleItemCount == totalItemCount)
//你只需要把继续得到下面十项的代码写在这里,就可以实现上述功能了。
//同样再使用一次POST方法,不再赘述
//代码由于同样原因不予以展示,敬请谅解

至此,文章开头的几个知识点已经全部讲解完毕,时间仓促,事物繁忙,可能会影响文章质量,还请大家多多包涵。 如果有问题,可以直接回帖、发论坛信息或通过Email:anliupeinye@gmail.com联系我。

项目成品展示:
 


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.luyixian.cn/news_show_766094.aspx

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

nginx配置https后,网站出现无法访问情况

证书来自阿里云。 Nginx配置如下 server {listen 443;server_name package.oeynet.com;root /server/wwwroot/package_v1/Public;ssl on;ssl_certificate /server/certs/package.oeynet.com/214082784100471.pem;ssl_certificate_key /server/certs/package.oeynet.com/21…

网站二级域名用.net 2.0实现方案

本人所了解有两种方案&#xff0c;可能还有其的方式&#xff0c;希望大家多多讨论&#xff01; 基本思路&#xff1a; 1. 域名支持泛解析&#xff0c;即是指&#xff1a;把A记录 *.域名.com 解析到服务器IP&#xff0c;服务器IIS中做绑定&#xff0c;绑定时主机头为空; 2. 为了…

网站日志实时分析之Flink处理实时热门和PVUV统计

点击上方蓝色字体&#xff0c;选择“设为星标”回复”资源“获取更多资源大数据技术与架构点击右侧关注&#xff0c;大数据开发领域最强公众号&#xff01;暴走大数据点击右侧关注&#xff0c;暴走大数据&#xff01;实时热门统计操作步骤&#xff1a;先从Kafka读取消费数据使用…

nodejs爬虫-通过抓取搜狗微信网站获取微信文章信息

展示地址 : http://39.108.162.233/wxlist github地址 : https://github.com/zzwwjjdj319/wechat_crawler 一 总量统计 二 按日期搜索 三 文章列表 四 微信文章链接

将ASP.NET网站部署到服务器IIS上

ASP.NET编写的网站程序&#xff0c;在网站编写完成所有流程都测试通过后&#xff0c;需要将网站发布到IIS的Web服务器上&#xff0c;此文将介绍发布的流程以及IIS相关设置过程&#xff0c;帮助读者了解网站发布的流程。 一、首先在Visual Studio中选择网站项目&#xff0c;然后…

WEB服务器之一:创建一个网站

一、实验准备网站的名字为&#xff1a;www.itat.com这里我们要用两台虚拟机&#xff1a;1、 Nanjing&#xff08;DNS服务器、WEB服务器&#xff09; IP&#xff1a;192.168.11.732、 shanghai&#xff08;做测试&#xff09;IP&#xff1a;192.168.11.72 DNS&#xff1a;192.1…

Asp.net MVC 2 网站轻松实现多语言支持

本文短地址&#xff1a;http://zdd.me/aspnetmultilingual 现在的网站大多数都支持多语言&#xff0c;为不同语言的用户访问网站提供方便。我在前几天用asp.net mvc 2 做了一个网站同时提供了中文和英文的支持&#xff0c;在这里将我的网站的多语言的实现方式与各位网友分享一下…

怪异而美丽的网站

怪异而美丽的网站 记录跳闸 记录跳闸是一个漂亮的贝尔兄弟的实验品。 邀请您来解决刮伤用鼠标的滚动轮记录的一系列难题。 聪明的游戏和一个可爱的界面&#xff0c;使这个有趣的在线Flash游戏&#xff0c;因为它是怪异。 声汉堡 这里是最有创造力的和非常规的闪光&#xff0c;我…

Windows安装node环境,部署静态网站

1、进入官网&#xff0c;下载nodejs https://nodejs.org/zh-cn/ 2、安装nodejs win10怎么安装nodejs和npm https://jingyan.baidu.com/article/d169e1860e6d8c436611d89a.html 3、查看版本信息 C:\Users\admin>node -v v12.2.0 4、部署静态网页 在当前页面打开命令行&#x…

创建自定义主机头的网站集

当我们在一个SharePoint Web应用程序中创建新网站集时&#xff0c;虽然我们可以指定网站集的路径&#xff0c;但是网站集的主机头&#xff0c;似乎必须使用Web应用程序所定义的主机头。比如&#xff0c;当在“http://sp2010”这个Web应用程序中创建一个新网站集时&#xff0c;网…

使用django建站系列之登录页面(一)

先秀一下我的登录页&#xff1a; 废话没有&#xff0c;直接上操作步骤。 1&#xff09;建立工程 #django-admin.py startproject MyWeb 2)建立应用 #cd MyWeb/ #django-admin.py startapp app51cto 3)修改settings.py添加app vim MyWeb/settings.py INSTALLED_APPS ( django.c…

WordPress网站制作静态化插件:Cos-Html-Cache介绍

现在很多做网站的新手朋友、甚至网站建设公司都会采用现成的网站管理系统来建站&#xff0c;国内的PageAdmin、Discuz、Ecshop等网站管理系统都已经很成熟&#xff0c;大量的被用于网站建设中&#xff0c;之前小熊优化的小编分别介绍了这些网站管理系统&#xff0c;并且几乎都默…

网站经验谈:网站被降权怎么办 如何恢复权重

虽然百度一再强调百度本身并没有权重一说&#xff0c;但是对于各位站长朋友来说&#xff0c;权重还是衡量一个网站的重要指标之一。一个网站的权重高&#xff0c;代表流量高&#xff0c;收录好&#xff0c;关键词排名也相对较好。那么&#xff0c;这么重要的指标&#xff0c;一…

如何判断一个网站是否被墙

http://www.cnblogs.com/wangkangluo1/archive/2012/04/15/2447921.html 大家都知道GFW 平日作恶多端&#xff0c;一旦有网站不能访问&#xff0c;很多人都把矛头直指它了…. 虽然一般都是它干的&#xff0c;但实际上也不排除一些人别有用心…. 那么下面就来简单判断一下吧… 方…

学用MVC4做网站五:5.2我的文章

文章管理这一块&#xff0c;按照左侧导航这一块向下写 到了“我的文章”这一块。 先还是打开【ArticleController】&#xff0c;添加public ActionResult UserOwn(int id 0, int page 1) 这里的id是指栏目id&#xff0c;可以显示自己发布的指定栏目的文章&#xff0c;默认为0…

企业网站优化切忌心浮气躁

为什么80%的码农都做不了架构师&#xff1f;>>> 互联网时代&#xff0c;大部分的企业都有自己的网站&#xff0c;随着网站管理员的更新换代&#xff0c;企业网站的优化成了遗留问题。很多企业网站域名年龄都有几年以上了&#xff0c;但是从seo的角度来说还是那么烂…

网站用户分析知识总结

本文是《数据蛙三个月强化课》的第七篇总结教程&#xff0c;如果想要了解数据蛙社群&#xff0c;可以阅读给DataFrog社群同学的学习建议。温馨提示&#xff1a;如果您已经熟悉网站用户分析知识,大可不必再看这篇文章&#xff0c;或是只挑选部分文章 一&#xff1a;用户分析概…

浙大海洋法律与治理研究中心网站

近日&#xff0c;为浙江大学海洋法律与治理研究中心开发官方网站正式上线。2012年8月21日&#xff0c;浙江大学海洋法律与治理研究中心成立。中心将汇聚浙江大学跨学科优势资源&#xff0c;适应国家战略需求和促进海洋法制保障&#xff0c;致力打造一支国内顶尖、结构合理的海洋…

curl网站开发指南

转载 http://www.ruanyifeng.com/blog/2011/09/curl.html 我一向以为&#xff0c;curl只是一个编程用的函数库。最近才发现&#xff0c;这个命令本身&#xff0c;就是一个无比有用的网站开发工具&#xff0c;请看我整理的它的用法。curl网站开发指南阮一峰 整理curl是一种命令行…

ASP.NET MVC5 网站开发实践(二) Member区域 - 修改及删除文章

上次做了显示文章列表&#xff0c;再实现修改和删除文章这部分内容就结束了&#xff0c;这次内容比较简单&#xff0c;由于做过了添加文章&#xff0c;修改文章非常类似&#xff0c;就是多了一个TryUpdateModel部分更新模型数据。 目录&#xff1a; ASP.NET MVC5 网站开发实践 …