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

news/2024/5/9 18:41:39/文章来源:https://blog.csdn.net/java2009cgh/article/details/7551151

#友盟杯#一步步教你为网站开发Android客户端

  
楼主
发表于 2011-11-29 10:30:10|查看: 10907|回复: 225
本帖最后由 liupeinye 于 2011-11-30 10:37 编辑

本文参与:友盟—安卓巴士Android开发原创教程大赛

本文面向Android初级开发者,有一定的Java和Android知识即可。

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

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

以下内容100%原创,并在安卓巴士论坛首发,如需转载,请注明作者和出处。谢谢合作。

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

QQ截图20111129094559.png


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

QQ截图20111129094624.png



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

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

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

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

QQ截图20111129094753.png



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

QQ截图20111129094829.png



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

QQ截图20111129094848.png



我们点击进入

QQ截图20111129095321.png



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


QQ截图20111129095339.png



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

QQ截图20111129095358.png


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


QQ截图20111129095406.png


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

QQ截图20111129095541.png


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

QQ截图20111129095645.png


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

QQ截图20111129095655.png


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

QQ截图20111129095702.png


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

QQ截图20111129095712.png


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

QQ截图20111129095718.png


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

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


QQ截图20111129095738.png


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

QQ截图20111129095745.png


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

  1. //实例化HttpClient
  2. HttpClient client = new HttpClient();
  3. //Stream页面里面有Host地址 端口是80
  4. client.getHostConfiguration().setHost("http://coin.lib.scuec.edu.cn", 80);
  5. //用目标地址 实例一个POST方法
  6. PostMethod post = new PostMethod("http://coin.lib.scuec.edu.cn/cgi-bin/IlaswebBib");
  7. //将需要的键值对写出来
  8. NameValuePair beg = new NameValuePair("FLD_DAT_BEG" , “”);
  9. NameValuePair end = new NameValuePair("FLD_DAT_END" , “”);
  10. NameValuePair submit = new NameValuePair("submit" , "查 询"));
  11. NameValuePair vIndex = new NameValuePair("v_index" , “TITLE”);
  12. NameValuePair vLogicSrch = new NameValuePair("v_LogicSrch" , "0");
  13. NameValuePair vPagenum = new NameValuePair("v_pagenum" , "10");
  14. NameValuePair vSeldatabase = new NameValuePair("v_seldatabase" , "0");
  15. NameValuePair vValue = new NameValuePair("v_value" ,”android”);

  16. //给POST方法加入上述键值对
  17. post.setRequestBody(new NameValuePair[] {beg , end , submit , vIndex , vLogicSrch , vPagenum , vSeldatabase , vValue});
  18. //执行POST方法
  19. client.executeMethod(post);
  20. //将POST返回的数据以流的形式读入,再把输入流流至一个buff缓冲字节数组
  21. //StreamTool类是我自己写的一个工具类,其内容将在下文附出
  22. byte[] buff = StreamTool.readInputStream(post.getResponseBodyAsStream());
  23. //将返回的内容格式化为String存在html中
  24. String html = new String(buff);
  25. //任务完成了,释放连接
  26. post.releaseConnection();

复制代码
  1. //StreamTool类如下
  2. public class StreamTool {
  3.         /**
  4.          * 从输入流中获取数据
  5.          * @param inputStream 输入流
  6.          * @return 字节数组
  7.          * @throws Exception
  8.          */
  9.         public static byte[] readInputStream(InputStream inputStream) throws Exception
  10.         {
  11. //实例化一个输出流
  12.                 ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
  13. //一个1024字节的缓冲字节数组
  14.                 byte[] buffer = new byte[1024];
  15.                 int len = 0;
  16. //读流的基本知识
  17.                 while ((len=inputStream.read(buffer)) != -1) {
  18.                         outputStream.write(buffer, 0, len);
  19.                 }
  20. //用完要关,大家都懂的
  21.                 inputStream.close();
  22.                 return outputStream.toByteArray();
  23.         }
  24. }

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

QQ截图20111129095849.png


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


QQ截图20111129095912.png


经过几次试验后,发现一个规律,只要搜索内容中包括中文,就搜不到。
所以可以判定是中文编码的问题,(在开发这类客户端时候,中文编码往往是个很具困难的问题。 安卓巴士开发3群的某群友提到:服务器交流用的编码是”ISO-8859-1”,跟我起初用到的编码一致,但真实性仍需考证)所以我们修改上面的代码,将代表搜索内容的v_value对应的值编码为”ISO-8859-1”

就将上段代码中的
  1. NameValuePair vValue = new NameValuePair("v_value" ,”android”);
复制代码
改为
  1. NameValuePair vValue = new NameValuePair("v_value" , new String(“android开发”.getBytes(),"ISO-8859-1"));

复制代码

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

至此,我们POST请求才真正完成。 观察控制台的HTML后发现,我们需要的书目信息就在里面,只不过被一些HTML标签包裹住了,下一步我们就要解放这些信息,存储到容器里。
这里我们要用到Jsoup,一个Java开源HTML解析器(来自org.jsoup包)。
我们直接上代码,逐行解释(大家最好对应上面的HTML代码来理解)
首先我们建一个容器来装这些解析到的数据,由于我的项目是将这些数据以ListView呈现给用户,而ListView的数据是由Adapter提供,Adapter需要传一个特殊容器-包含HashMap的ArrayList(Android基础知识)

  1. //所以有
  2. List<Map<String,Object>> list = new ArrayList<Map<String,Object>>();
  3. //开始使用Jsoup
  4. //Jsoup支援一个Document类   将刚才的html转化成Document
  5. Document document = Jsoup.parse(html);
  6. //一个Document又由elements组成  我们选择”tr”开头的标签,存入 trs元素群中
  7. Elements trs = document.select("tr");
  8. //得到整个HTML中包含tr的标签的个数
  9. int totalTrs = trs.size();
  10. //我们可以观察上面没有搜索结果的那个HTML。发现,如果totalTrs<=3就表示没结果。
  11. //只要有书目结果totalTrs必定大于3,于是
  12. if(totalTrs > 3)
  13. for(int i = 0;i < totalTrs - 3;i++)
  14. {
  15. //观察HTML,从第i+2个tr开始,包含的才是我们要的书目信息
  16. //我们从每个tr中选出td标签元素群
  17.                         Elements tds = trs.get(i + 2).select("td");
  18. //得到每个tr中td的个数
  19.                         int totalTds = tds.size();
  20. //一个临时的HashMap,里面是String-Object键值对
  21.                         Map<String,Object> map = new HashMap<String,Object>();
  22. //j是一个标识数
  23.                         for(int j =0;j < totalTds ;j++)
  24.                         {
  25.                                 switch (j) {
  26. //0表示第一个,即书名
  27. //put方法即向map加入一条键值对
  28. //html()方法就得到标签括起来的内容
  29.                                 case 0:
  30.                                         map.put("book_title", tds.get(j).html().toString());
  31.                                         break;
  32.                                 case 1:
  33. //1表示第二个,即作者
  34.                                         map.put("book_author", tds.get(j).html().toString());
  35.                                         break;
  36.                                 case 2:
  37. //2表示第三个,即出版信息
  38.                                         map.put("book_press", tds.get(j).html().toString());
  39.                                         break;
  40.                                 case 3:
  41. //3表示第四个,即页数
  42.                                         map.put("book_page", tds.get(j).html().toString());
  43.                                         break;
  44.                                 case 4:
  45. //4表示第五个,即价格
  46.                                         map.put("book_price", tds.get(j).html().toString());
  47.                                         break;
  48.                                 case 5:
  49. //5表示第六个,即索取号
  50.                                         map.put("book_noFor", tds.get(j).html().toString());
  51.                                         break;
  52.                                 case 6:
  53. //6表示第七个,即那段网址
  54. //那段网址td中又包含一个a标签,a标签的href属性的值就是网址
  55. //attr(“href”)可以返回href属性的值
  56.                                         map.put("book_detail", tds.get(j).select("a").attr("href").toString());
  57.                                         break;
  58.                                 default:
  59.                                         break;
  60.                                 }
  61.                         }
  62.                         list.add(map);
  63. }
复制代码
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方法

  1. @Override
  2.         public void onScroll(AbsListView view, int firstVisibleItem,
  3.                         int visibleItemCount, int totalItemCount) {
  4.                 // TODO Auto-generated method stub
  5. //关键的判断代码,这句话表示用户将ListView拉至最底部
  6.                 if(firstVisibleItem + visibleItemCount == totalItemCount)
  7. //你只需要把继续得到下面十项的代码写在这里,就可以实现上述功能了。
  8. //同样再使用一次POST方法,不再赘述
  9. //代码由于同样原因不予以展示,敬请谅解
复制代码

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

项目成品展示:
device-2011-11-29-161307.png



看看这些信息是不是就是上面用网页以"android"为关键字搜索到的?


最后感谢安卓巴士论坛、安卓王子、安卓巴士开发3群的群友的支持。


转:http://www.apkbus.com/android-17712-1-1.html


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

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

相关文章

倾情分享:Android 开发者们不要错过的网站宝藏~

从事 Android 开发多年&#xff0c;攒了很多宝贵网站&#xff0c;分享给大家。 涵盖了系统、API、语言、开发工具、以及各种官方学习平台&#xff0c;不求面面俱到&#xff0c;只求无私分享&#xff01; 期望给各位 Android ROM 开发者、App 开发者带来最全最官方的学习资料&am…

如何在新浪云上传自己的网站(静态展示)

欢迎加入前端交流群交流知识获取视频资料&#xff1a;749539640 最近有小伙伴问我怎么在新浪云上传自己的本地页面&#xff1b;大家看教程吧&#xff01; 第一步&#xff1a;肯定是去注册账号了(需要先注册微博账号&#xff0c;只能使用微博账号登录) 注册地址&#xff1a;点击…

网站引导功能实现

欢迎加入前端交流群交流知识获取视频资料&#xff1a;749539640 背景&#xff1a;发布了新网站&#xff0c;需要引导用户操作或者发布了新功能需要展示给用户 实现&#xff1a;借助driver.js 第三方类库实现 demo&#xff1a;样式如下图 实现方式&#xff1a;点击查看示例代码 …

网站发布

文章目录IIS简介网站发布发布网站到本地IIS简介 iis(Internet Information Services)&#xff0c;译为互联网信息服务&#xff0c;由微软公司提出的基于运行windows的基本服务。现在IIS都内置在windows系统中一起发行。IIS意味着你能发布网页&#xff0c;并且有ASP&#xff08…

WEB网站与WEB应用程序的区别

WEB网站 每个页面(.ashx)生成一个独立的程序&#xff0c;一个页面出错不会对其他页面有影响没有命名空间&#xff0c;因为每个文件会生成一个dll文件&#xff0c;不会在文件内产生全名冲突网站中每个页面(aspx,ashx)都生成对应的程序集&#xff0c;名称是随机的&#xff0c;当…

常见的反爬虫技术有哪些?如何防止别人爬自己的网站?

搜索引擎可以通过爬虫抓取网页信息&#xff0c;同时也有很多企业通过爬虫获取其他平台的信息用于数据分析或者内容优化&#xff0c;但是对于自身网站有些页面或者信息并不希望被爬虫抓取&#xff0c;那我们如何来实现反爬虫技术呢&#xff1f;如何防止别人爬自己的网站呢&#…

研究生应该常去的网站

研究生应当常去的网站 1. 小木虫&#xff08; http://emuch.net/ &#xff09; 推荐理由&#xff1a;里边有不少学术科研用得到的资料&#xff0c;且全部为免费的。 2. 国家自然科学基金&#xff08; http://www.nsfc.gov.cn/Portal0/default40.htm &#xff09; 推荐理由&…

iOS开发学习的网站

----------------------------------------------------------------------------------------------------------------------------- 以下转自&#xff1a;http://blog.csdn.net/xietao3/article/details/9300583 http://forums.toucharcade.com/这个是大家公认的&#xff0c…

Foundation框架 - 快速创建跨平台的网站页面原型

转自 &#xff1a;http://ikeepu.com/bar/10417219 整个一周都在揪心的猫事中度过。从十月底到现在的这段日子里&#xff0c;倒是越发懂得珍惜每天中片刻的宁静时光。有时会怀疑家里是否有时空漩涡一类的东西&#xff0c;不然钟表怎么会走的那么快&#xff0c;一点儿也不愿停下…

web音乐系统 javaweb音乐网站 低仿网易云音乐网站项目 期末课设 课设项目

在一筹莫展的搞期末课设时&#xff0c;看到了这个up主的项目&#xff0c;简直是神仙下凡&#xff01;&#xff01;&#xff01; 视频链接&#xff1a;https://www.bilibili.com/video/BV1i4411K7g4/?spm_id_from333.788.b_636f6d6d656e74.4 我进群之后有不会的&#xff0c;u…

模仿天猫,京东等购物网站的随屏滚动导航

首先把html基本代码写好&#xff0c; index.html页面 <!DOCTYPE html> <html> <head lang"en"><meta charset"UTF-8"><title>随屏滚动导航</title><link rel"stylesheet" href"./css/style.css&quo…

国内多家视频下载网站关闭:或为暂避风头

国内多家视频下载网站关闭&#xff1a;或为暂避风头 02013-04-27 08:02 | 来源&#xff1a;现代快报 视频下载网站 关闭 大中小人人影视关站页面(新浪科技配图) 昨天是第十三个世界知识产权日&#xff0c;它由世界知识产权组织从2001年开始设立。这一原本并不十分著名的主题日&…

【一文入门】Git常用命令集锦--分支操作和版本管理篇

前言 Git 是一种分布式版本控制系统&#xff0c;可以帮助团队协作开发、管理和维护代码&#xff0c;提高代码质量和效率&#xff0c;掌握常用版本管理命令可以帮助我们更好地管理代码变更和历史记录。下面我将介绍开发中常用的一些Git分支操作和版本管理命令 1 分支操作 1.1 …

Java开发者必去的技术网站

<script type"text/javascript">function StorePage(){ddocument;td.selection?(d.selection.type!None?d.selection.createRange().text:):(d.getSelection?d.getSelection():);void(keyitwindow.open(http://www.365key.com/storeit.aspx?tescape(d.titl…

大型互联网网站架构心得

大型互联网网站架构心得之一&#xff1a;分 转自 &#xff1a; 朱晔 ID&#xff1a;LoveCherry http://blog.csdn.net/LoveCherry/archive/2008/06/19/2564096.aspx 我们知道&#xff0c;对于一个大型网站来说&#xff0c;可伸缩性是非常重要的&#xff0c;怎么样在纵向和横向…

我国公布整治互联网低俗之风第二批曝光网站名单

2009-01-08 17:04:08 来源: 中新网(北京) 网友评论 843 条 点击查看 核心提示&#xff1a;中国互联网协会互联网违法和不良信息举报中心8日公布全国整治互联网低俗之风第二批曝光网站名单。 中新网1月8日电 中国互联网协会互联网违法和不良信息举报中心今日发布公告&#xff…

剖析SNS网站的现状,预测其发展趋势

-------导读------------1、SNS的由来和价值2、SNS区别与BBS和社区网站3、点评目前SNS网站的现状和价值取向4、SNS的盈利模式5、未来SNS的发展趋势 1、SNS的由来和价值 在谈SNS之前我们先认清一下SNS的几个概念&#xff1a; SNS定义&#xff1a;Social Network Software&#…

网站图片防盗链:初级策略

哪个站长也不想自己的带宽白白像流入黑洞一般&#xff0c;被盗链流量所淹没&#xff0c;所以大致采取一些方法&#xff0c;或多或少减少这种盗链成本&#xff0c;下面介绍一种初级策略&#xff1a; 1、我们先举了例子&#xff0c;下面的图片我是在blog中引用www.souapp.com&am…

Django生成网站的sitemap.xml

Django有一个高级的Sitemap生成框架 一个Sitemap是一个你的网站的XML文件&#xff0c;它告诉搜索引擎索索引你的页面的更新频率和你的站点某些页面联系到其它页面 有多"重要"&#xff0c;这个信息帮助搜索引擎索引你的站点&#xff0c;参看http://www.sitemaps.org得…

django+apache配置网站的robots.txt和sitemaps等理静态文件

当你的网站已经在公网上正常上线后&#xff0c;为了能被搜索引擎很好的收录网站结构&#xff0c;就必须主动向搜索引擎提供robots.txt和sitemap.xml&#xff0c; 先来看看什么是robots.txt和 sitemap.xml吧&#xff0c;以下摘自“维基百科” http://zh.wikipedia.org/zh-cn/Si…